Commit Graph

36 Commits

Author SHA1 Message Date
akshayshirahatti-da
721575ea73
[JSON-API] Postgres perf job (#10986)
* Addition of a postgres perf job

CHANGELOG_BEGIN
CHANGELOG_END

* use a single job with strategy matrix

* cleanup test job from main pipeline
2021-09-23 09:16:58 +01:00
akshayshirahatti-da
35a853fd30
Async logging for http-json-perf tests and publish logs as a pipeline artifact (#10803)
CHANGELOG_BEGIN
CHANGELOG_END
2021-09-07 23:42:30 +01:00
Victor Peter Rouven Müller
5595d55c79
[JSON-API] Use the token from incoming requests to update the package list (#10602)
* Use the token from incoming requests to update the package list

changelog_begin
changelog_end

* Lazily initialize the ledger client

* Fix ee integration tests

* Fix package reloading behaviour by using a semaphore to check for ongoing updates

* Refactor out the semaphore code into a concurrency utility class

* Use correct locking for the updateTask so every thread always uses an up to date task

* Remove unused imports in utils.Concurrent & remove packages from the tests

* Hide & mark the token file cli option deprecated because we dont need it anymore and only keep it so client deployment code doesn't break

* Fix scala 2.12 build by adding more type annotations

* Update ledger-service/http-json-cli/src/main/scala/com/daml/http/OptionParser.scala

Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com>

* Update ledger-service/http-json/src/main/scala/com/digitalasset/http/PackageService.scala

Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com>

* Readd pgkManagementClient after it was removed accidentally (but now it's lazy)

* Remove concurrent object & use atomic boolean instead of a mutex because it makes more sense

* Replace semaphore with countdownlatch

* Refactor the caching into a separate class

* Use Instant instead of LocalDateTime

* Remove that ** of bad synchonization and do stupid simple synchronization because it JUST WORKS, besides adapt when we want to reload

* Remove await in tests because it can result in buggy tests

* remove unused code in WebSocketService.scala

* Unhide the access-token-file option as per request of Stefano

* Less implicit jwts per request of Stefano

* Try making some code more readable as by request of Akshay

* Use more shark because it expresses better than flatMaps if I don't need the arg

* Move defs in predicate in WebsocketService.scala around

* Try to minimize diff further in WebsocketService.scala

* Fix build and minimize diff in WebSocketService.scala further

* Minimize diff of function getTransactionSourceForParty in WebSocketService.scala

* Share the ec in WebSocketService.scala to minimize the diff

* Minimize in function predicate in WebSocketService.scala

* Further minimize in function predicate in WebSocketService.scala

* Change some case classes to be normal classes but with apply method

* Update ledger-service/http-json/src/main/scala/com/digitalasset/http/PackageService.scala

Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com>

* Update ledger-service/http-json/src/main/scala/com/digitalasset/http/Endpoints.scala

Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com>

* Get rid of implicit jwt tokens, the world is already confusing and full of implicits enough

* Improve readability

* Integrate the new LedgerClient which does not depend on a leder id

* Fix tests

* Apply suggestions from code review

thanks to @S11001001

Co-authored-by: Stephen Compall <stephen.compall@daml.com>

* Apply further review comments

* Remove outcommented code

* Deprecate access token file option in the description too

changelog_begin

- [JSON API] The cli option `--access-token-file` is now deprecated. It
    is not needed anymore and you can safely remove it. Reason is that
    the operations which prior required a token at startup are now done
    on demand using the token of the incoming request.

changelog_end

Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com>
Co-authored-by: Stephen Compall <stephen.compall@daml.com>
2021-09-03 10:12:01 +00:00
akshayshirahatti-da
4525b8c265
[JSON-API] vanilla oracle_perf ci job (#10688)
* vanilla job test on main pipeline

changelog_begin
changelog_end

* move job to daily compat tests

* add timeout to dev-env and changes based on code review
2021-09-02 09:31:56 +01:00
Stephen Compall
e5c4734780
enable JSON search index on Oracle by default (#10539)
* unconditionally enable JSON search index on Oracle

In '1kb of data' and larger Oracle integration tests:

ORA-29902: error in executing ODCIIndexStart() routine
ORA-20000: Oracle Text error:
DRG-50943: query token too long on line 1 on column 3

From https://docs.oracle.com/en/database/oracle/oracle-database/19/errmg/DRG-10000.html#GUID-46BC3B3F-4DB7-4EB4-85DA-55E9461966CB

    Cause: A query token is longer than 256 bytes

    Action: Rewrite query

* add changelog

CHANGELOG_BEGIN
- [JSON API] The Oracle database schema has changed; if using
  ``--query-store-jdbc-config``, you must rebuild the database by adding
  ``,start-mode=create-only``.  See #10539.
CHANGELOG_END

* test only 1kb

* extra flag in db config string

* let Queries backends configure themselves from maps

* new Queries constructor dataflow to better support config values

* remove fields as we go, isolating backend-specific from -agnostic conf

- we use StateT to avoid the problems that will definitely arise if we
  don't DRY.

* fix up DbConfig including DbStartupMode

* start to uncouple json-api's config from db-utils

* two JdbcConfigs with different purposes/scopes

- also moves db-utils contents to com.daml.dbutils

* adapt trigger service to refactoring

* fix JdbcConfig leftovers

* adapt http-json-cli to new JdbcConfig

* remove extra ConfigCompanion

* explain more about the QueryBackend/Queries distinction

* split SupportedJdbcDriver into two phases with a tparam

* use SupportedJdbcDriver.TC instead of SupportedJdbcDriver as the nullary typeclass

* patch around all the moved objects with imports

* missed import from moving ConnectionPool to dbutils

* use new 2-phase SupportedJdbcDriver for ContractDao setup

* left off part of a comment

* more q.queries imports

* other imports from the dbutils move

* nested JdbcConfig

* configure the driver in each backend-specific test

* very confusing error, but make the imports nicer and it goes away

* nested JdbcConfig in perf

* missing newline

* port contractdao-bench

* test new option parsing all the way through QueryBackend

* disable search index for some tests, enable for others

* add changelog

CHANGELOG_BEGIN
- [Trigger Service] ``--help`` no longer advertises unsupported JDBC
  options from JSON API.

- [JSON API] [EE only] By default, on Oracle, sets up a JSON search
  index to speed up the queries endpoints.  However, Oracle versions
  prior to 19.12 have an unrecoverably buggy implementation of this
  index; in addition, the current implementation fails on queries with
  strings >256 bytes, with no way to disable the index for that query.

  Pass the ``disableContractPayloadIndexing=true`` option as part of
  ``--query-store-jdbc-config`` to disable this index when creating the
  schema.
  See `issue #10539 <https://github.com/digital-asset/daml/pull/10539>`__.
CHANGELOG_END

* port failure tests

* init version table last, drop first

- suggested by @realvictorprm; thanks

* rename split DBConfig.scala

- suggested by @realvictorprm; thanks

* move imports to not be in alphabetical order

- suggested by @realvictorprm; thanks

* remove createSchema

- suggested by @realvictorprm; thanks

* Revert "test only 1kb"

This reverts commit 616e173e63.

* port to scala 2.12

- bug in unused imports

- old name `-` for `removed`
2021-08-31 09:29:36 +00:00
akshayshirahatti-da
77eb366627
[JSON-API] key_hash field to speed up fetchByKey queries (#10631)
* Addition of a key_hash field to speed up fetchByKey queries
CHANGELOG_BEGIN
CHANGELOG_END

* changes to make key_hash and Optional field

CHANGELOG_BEGIN
- Update schema version for http-json-api query store with new key_hash field
- Improved performance for fetchByKey query which now uses key_hash field
CHANGELOG_END

* remove btree index for postgres and other changes based on code review comments
2021-08-23 18:15:25 +01:00
akshayshirahatti-da
5f7a3691a5
[JSON-API] Perf gatling MultiUserQueryScenario (#10422)
* Gatling MultiUserQueryScenario initial version, 100k ACS , 100 users used for testing conn pool performance
    CHANGELOG_BEGIN
    CHANGELOG_END

* Configurable scenario parameters via env variables
2021-08-16 17:01:27 +00:00
Samir Talwar
4b8b67a1b5
Upgrade Scalatest to v3.2.9. (#10576)
* Upgrade Scalatest to v3.2.9.

Because of some coupling we also have to upgrade Scalaz to the latest
v7.2 point release, v7.2.33.

The Scalatest changes are quite involved because the JAR has been broken
up into several smaller JARs. Because Bazel expects us to specify all
dependencies and doesn't allow transitive dependencies to be used
directly, this means that we need to specify the explicit Scalatest
components that we use.

As you can imagine, this results in quite a big set of changes. They
are, however, constrained to dependency management; all the code remains
the same.

CHANGELOG_BEGIN
CHANGELOG_END

* http-json-oracle: Fix a Scalatest dependency.

* ledger-api-client: Fix a Scalatest dependency.
2021-08-12 23:19:35 +00:00
akshayshirahatti-da
b00e146aa0
[JSON-API/trigger-service] Refactor db conn (#10497)
* Move ExceptionOps from ledger-service/utils to //libs-scala/scala-utils

* extract connection and JdbcConfig from //ledger-service to independent db-utils module
Changelog_begin
Changelog_end

* update trigger service to use new libs-scala/db-utils

* missed changes for http-json-oracle

* minor cleanup based on comments

* fix breaking scala 2_12 build

* cleanup db-utils/BAZEL.md file
2021-08-09 09:56:58 +00:00
Victor Peter Rouven Müller
c97cbcabfd
[JSON-API] Validate schema version & add minimal options for schema creation (#10374)
* [JSON-API] Validate schema version & add minimal options for schema creation

* Add tests

* [JSON-API] Rework prior work and introduce the object SchemaHandling

* Add license headers & revert formatting changes

* Fix oracle build & scala 2_12 build

* correctly fix 2.12 build

* Update ledger-service/http-json/src/main/scala/com/digitalasset/http/SchemaHandlingResult.scala

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>

* [JSON-API] Change case names & add backwards compat (but deprecate createSchema=true)

changelog_begin

- [JSON-API] Schema versioning was introduced to the db schema. Because of this the field `createSchema` in the jdbcConfig was deprecated. Via the field `start-mode` you can specify:
   1. `create-only`: This is equal to the behaviour of `createSchema=true` so the db schema is created and then the application terminates.
   2. `start-only`: With this the schema version is checked and if no version or an version was found which is not equal to the internal schema version then the application terminates. This is also the replacement of `createsSchema=false`.
   3. `create-if-needed-and-start`: With this the schema version is checked and if no version or an version was found which is not equal to the internal schema version then the schema will be created/updated and the application proceeds with the startup.
   4. `create-and-start`: Similar to the first option but instead of terminating the application proceeds with the startup.

changelog_end

* Add info about deprecated createSchema field

* Fix build & improve logging

* Give suggestions on what option to take, to fix an outdated or missing schema

* Renaming of schemaHandling to DbStartupMode, added more tests & correct exit codes depending on how the db startup went

* Align name with sandbox

* Improve tests

* Only add new sql code which strictly uses the interpolation to align with other pr's & minimally adjust statements

* Minimize diff

* Add backwards compat test

* Fix scala 2.12 build & oracle integration tests build

* Update ledger-service/http-json-cli/src/main/scala/com/daml/http/Config.scala

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>

* Adjust code according to review request & tests & add a failure test

* If the call to initialize fails also log the error which was thrown

* Fix formatting

* Add missing collections compat import in integration tests

* Fix last build errors (scala 2.12) & use Either instead of Option for getDbVersionState

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
2021-07-27 18:27:58 +02:00
Stephen Compall
01d6770450
json-api perf tests: combine large-ACS frequencies combinatorially instead of in lockstep (#10101)
In #10016, 1% template ID and 1% party-set membership meant _the same_ 1%,
meaning that an index of both couldn't possibly yield interesting results.  This
changes how LargeAcs builds the large ACS so that it's "1% of 1%", as you'd
expect.

CHANGELOG_BEGIN
CHANGELOG_END
2021-06-24 10:00:02 -04:00
Stephen Compall
321c4da2dd
test different template-ID frequencies in the "mega" perf scenario (#10016)
* add a new template for testing template-ID-sensitive query

* add a tpid *and* party-set 1% scenario

CHANGELOG_BEGIN
CHANGELOG_END
2021-06-16 12:19:03 -04:00
Stephen Compall
ad529e9a8b
http-json-perf: querying larger ACSes with different data patterns (#9530)
* new perf test module LargeAcs to shift many-contract creation to Daml-side

* using MakeIouRange to make blocks of (more or less constant) Ious

* syntax and bad variable quasiquoting

* ACS data distribution plans

* run with 100k contracts, same template, 1% observer frequency

* use CanAssert instead of CanAbort

* query under proper alternative jwt

* no changelog

CHANGELOG_BEGIN
CHANGELOG_END

* make sure the database accurately represents the ACS
2021-05-25 08:23:31 -04:00
Moritz Kiefer
66d039eb5b
Upgrade gatling to version 3.5.1 (#9714)
Ths is required to get a version of Gatling that supports Scala
2.13 (and only that because they do not cross build).

Unfortunately the upgrade is a bit more annoying than I was hoping for:

Our custom gatling utils rely on parsing the simulation log. This is
an internal file format with zero documentation or stabilityt
guarantees and as expected it has changed in incompatible ways during
the upgrade.

Rather than trying to reverse engineer and adapt to changes everytime
we upgrade, this PR switches us to a slightly more supported codepath
by parsing the `stats.json` and `assertions.json` produced by the
highcharts stuff. Afaict this is also what for example the Jenkins
integration relies on so while it’s not completely public API it seems
like the best option I could find.

There are a few pieces of information we can’t get out of those
files. Specifically:

1. maxUsers: we only ever need one users anyway so not really relevant.
2. start, duration, end: no idea why we would want those. we want per
   request metrics not the total duration.
3. geometric mean: slightly annoying, but avg & stdev should be good
enough™.
4. The scenario name: Not really an issue but if it is, we can
   disambiguate by changing request names.

changelog_begin
changelog_end
2021-05-18 16:54:37 +00:00
Stephen Compall
4e712a01a0
add oracle option for json-api perf runner (#9492)
* add oracle option to http-json-perf-binary-ee

* add oracle path to perf Main's JDBC bracket

* adapt to availableJdbcDriverNames; missing deps

* add changelog

CHANGELOG_BEGIN
- [JSON-API Perf] ``--query-store-index=postgres`` must be passed
  to select PostgreSQL query store performance testing; ``true``
  and ``yes`` are no longer supported.
  See `issue #9492 <https://github.com/digital-asset/daml/pull/9492>`__.
CHANGELOG_END
2021-04-27 08:58:44 -04:00
Stefano Baghino
3fa05804bf
Make non-repudiation integration exclusive to enterprise edition (#9219)
* Make non-repudiation integration exclusive to enterprise edition

Closes #9182

changelog_begin
changelog_end

* Address https://github.com/digital-asset/daml/pull/9219#discussion_r599578614

* Address https://github.com/digital-asset/daml/pull/9219#pullrequestreview-618605511

* Add aliases for CE test targets, thanks to @S11001001 for the feedback

* Uh, turns out you need a main...

* Address https://github.com/digital-asset/daml/pull/9219#discussion_r599717526

* Add missing dependency for Oracle
2021-03-24 20:25:47 +01:00
Moritz Kiefer
7ae28beff9
More Scala 2.13 cleanup (#8855)
This fixes Scaladoc and our pom file generation.

It also clears up the confusing error around gatling and removes a
redundant dependency on sbt (no idea why we had that in the first
place) both of which resulted in Scala 2.12 dependencies in our 2.13
lockfile which is obviously bad.

With this, we should now be ready to publish Scala 2.13 artifacts once
the ledger API test tool PR lands.

changelog_begin
changelog_end
2021-02-16 09:39:16 +00:00
Moritz Kiefer
153a23d315
Port the rest of //ledger-service/... to 2.13 (#8836)
changelog_begin
changelog_end
2021-02-12 17:26:19 +01:00
Moritz Kiefer
22ce940954
Upgrade scalafmt and enable trailing commas (#8437)
This PR updates scalafmt and enables trailingCommas =
multiple. Unfortunately, scalafmt broke the version field which means
we cannot fully preserve the rest of the config. I’ve made some
attempts to stay reasonably close to the original config but couldn’t
find an exact equivalent in a lot of cases. I don’t feel strongly
about any of the settings so happy to change them to something else.

As announced, this will be merged on Saturday to avoid too many conflicts.

changelog_begin
changelog_end
2021-01-09 11:37:37 +01:00
Bernhard Elsner
cda93db944
Daml case and logo (#8433)
* Replace many occurrences of DAML with Daml

* Update docs logo

* A few more CLI occurrences

CHANGELOG_BEGIN
- Change DAML capitalization and docs logo
CHANGELOG_END

* Fix some over-eager replacements

* A few mor occurrences in md files

* Address comments in *.proto files

* Change case in comments and strings in .ts files

* Revert changes to frozen proto files

* Also revert LF 1.11

* Update get-daml.sh

* Update windows installer

* Include .py files

* Include comments in .daml files

* More instances in the assistant CLI

* some more help texts
2021-01-08 12:50:15 +00:00
Gary Verhaegen
a925f0174c
update copyright notices for 2021 (#8257)
* update copyright notices for 2021

To be merged on 2021-01-01.

CHANGELOG_BEGIN
CHANGELOG_END

* patch-bazel-windows & da-ghc-lib
2021-01-01 19:49:51 +01:00
Moritz Kiefer
76b6fd86fb
Upgrade Scala dependencies for 2.13 compatibility (#8268)
* Upgrade Scala dependencies for 2.13 compatibility

This upgrades a bunch of Scala libraries to versions that have 2.13
support. There are two libraries that are still missing:

- diffson, this has a new version but with significant breaking
  changes and it is only used in Naigator console which I hope to kill
  before I have to worry about this.

- ai.x:diff, this is used in the ledger API test tool. The library is
  abondened but there are a few alternatives.

changelog_begin
changelog_end

* Fix pureconfig

changelog_begin
changelog_end

* Fix Navigator

changelog_begin
changelog_end
2020-12-14 09:59:00 +01:00
Moritz Kiefer
ea453c35cf
Add tests for connection failures in the JSON API (#7751)
* Add tests for connection failures in the JSON API

This PR adds some toxiproxy based tests to see how the JSON API reacts
if the connection to the ledger is killed. There are a bunch of
inconsistencies here in the tests some of which we might want to
address and the others we should at least document but I’ll leave that
for future PRs.

changelog_begin
changelog_end

* Import HttpServiceTestFixture instead of prefixing

changelog_begin
changelog_end
2020-10-20 18:59:11 +02:00
Moritz Kiefer
aa3e5a7dbe
Support multi-party reads on the JSON API (#7571)
* Support multi-party reads on the JSON API

Given that those aren’t going away and we’re instead doubling down on
this and adding multi-party writes as well, the JSON API needs to
support this. This PR only implements the read side (since the ledgers
do not yet support the write side).

This does not deviate from the approach chosen by the JSON API to
infer the parties from the token, we just don’t error out anymore when
more than one party is passed.

changelog_begin
changelog_end

* Apply suggestions from code review

Co-authored-by: Stephen Compall <stephen.compall@daml.com>

* Remove dependency on doobie_postgres from db-backend

changelog_begin
changelog_end

* Fix offset update

changelog_begin
changelog_end

* Use nonempty sets for parties

changelog_begin
changelog_end

* Fix updateOffset under concurrent transactions

changelog_begin
changelog_end

* Add tests for multi-party websocket queries and fetches

changelog_begin
changelog_end

* fmt

changelog_begin
changelog_end

* Fix perf tests

changelog_begin
changelog_end

* Cleanup

changelog_begin
changelog_end

* Update ledger-service/http-json/src/main/scala/com/digitalasset/http/dbbackend/ContractDao.scala

Co-authored-by: Stephen Compall <stephen.compall@daml.com>

* Move ParsePayload instances, thanks Stephen!

changelog_begin
changelog_end

* More unsubst

changelog_begin
changelog_end

* Fix off by 1 error

changelog_begin
changelog_end

* Remove redundant type annotation

changelog_begin
changelog_end

* fmt

changelog_begin
changelog_end

Co-authored-by: Stephen Compall <stephen.compall@daml.com>
2020-10-08 13:46:15 +02:00
Leonid Shlyapnikov
0730102b99
JSON API Perf Test Runner Query Store Index Support (#7434)
* Postgresql setup for Gatling perf test

* Add JSON API `query-store-index` support

changelog_begin
changelog_end
2020-09-17 16:39:00 -04:00
Leonid Shlyapnikov
d13e7aa184
JSON API daily perf test cron job (#7406)
* Add http-json-perf daily cron job

changelog_begin
changelog_end

* commenting out other jobs so we can manually test the new one

* commenting out other jobs so we can manually test the new one

* Fix the shell script

* Fixing the gs bucket, `gs://http-json bucket does not exist`

* uncomment the other jobs

* timestamp from git log

* get rid of DAR copying

* comment out the other jobs, so we can test it

* uncomment the other jobs
2020-09-16 13:02:02 -04:00
Leonid Shlyapnikov
fe63816431
Write report summary in text format (#7407)
* write summary.txt

changelog_begin
changelog_end

* make `Response time distribution` brackets configurable
2020-09-16 09:31:54 -04:00
Leonid Shlyapnikov
ae2981eaf2
Updating readme (#7398)
changelog_begin
changelog_end
2020-09-15 08:51:57 -04:00
Leonid Shlyapnikov
4fbde3c672
Open-sourcing Gatling statistics reporter (#7325)
* Open sourcing gatling statistics reporter

Running gatling scenarios with `RunLikeGatling` from libs-scala/gatling-utils

* cleaning up

* Replace "\n" with System.lineSeparator

so the formatting test cases pass on windows

* Testing DurationStatistics Monoid laws

* Renaming RunLikeGatling -> CustomRunner
2020-09-11 13:39:05 +00:00
Leonid Shlyapnikov
ccecc46e70
JSON API Perf Scenario Runner (#7295)
* Run gatling scenario from the perf runner main

reports are disabled for now, getting a class not found
when generating them

changelog_begin
changelog_end
2020-09-02 09:00:43 -04:00
Leonid Shlyapnikov
20e2922b3e
JSON API perf test main that starts sandbox and json-api services (#7283)
* reintroducing the main

* Introducing `ledger-service/http-json-testing`

* cleaning up

* Starting sandbox and json-api from perf-test main

changelog_begin
changelog_end
2020-08-31 22:55:01 +00:00
Leonid Shlyapnikov
cb73542316
http-json-perf cleanup (#7145)
* Removing unused Main and Config,

cleaning up BUILD.bazel: removing common scala options,

* Removing unused dependencies

* Removing unused dependencies

changelog_begin
changelog_end
2020-08-14 17:02:45 +00:00
Leonid Shlyapnikov
213832572b
Sync query perf scenario, new ACS every query (#7078)
* AsyncQueryNewAcs scenario

sync query with totally new ACS every time

changelog_begin
changelog_end

* cleanup

* cleanup

* fixing numbers

* fixing numbers

* adding groups to self-document the scenario

* Archive and then Create

* cleanup

* silence archive and create

* with ACS of 5000 it takes too long to run
2020-08-10 22:23:46 +00:00
Leonid Shlyapnikov
ba22f5b9a4
AsyncQueryConstantAcs scenario (#7054)
changelog_begin
changelog_end
2020-08-07 09:33:05 -04:00
Leonid Shlyapnikov
a630e3c944
JSON API SyncQueryVariableAcs perf test scenario (#7028)
* Perf test scenario for query with variable ACS, WIP

* WIP

* change ACS with every query

exercise a choice + create a new contract to keep ACS size the same

* change ACS with every query

running exercise and create in parallel with the query

* exercise Archive instead of Transfer

* Adding copyright header

* Thanks @S11001001
2020-08-05 18:31:18 +00:00
Leonid Shlyapnikov
9acb47d994
JSON API command submission perf test (#6906)
* JSON API Perf test scenarios

changelog_begin
changelog_end

* addressing code review, thanks @S11001001

* addressing code review, thanks @S11001001

* cleanup

* cleanup + instructions

* cleanup + instructions

* Updates

* Updates
2020-08-04 18:51:44 +00:00