Commit Graph

982 Commits

Author SHA1 Message Date
Miklos
9dd78fc508
Ledger data export for non-determinism checks (#6418)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-19 17:52:11 +02:00
Samir Talwar
6496ddd903
caching | kvutils | sandbox: Use a size-based cache for LF value translation. (#6432)
* caching: Split caches into new files.

* caching: Rename `Cache.from` to `WeightedCache.from`.

* caching: Move `Configuration` inside `WeightedCache`.

* caching: Add test cases.

* caching: Allow for Caffeine builders to be covariant.

* caching: When instrumenting the Caffeine cache, compose, don't inherit.

* caching: Add a size-based cache.

* caching: Extract out common test cases into base classes.

* caching: Use the size-based cache for LF value translation.

CHANGELOG_BEGIN
CHANGELOG_END

* caching: Simplify the eviction tests.

* caching: Increase the encapsulation in CaffeineCache.

* caching: Commas are important.

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

Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com>
2020-06-19 14:42:40 +00:00
Remy
1b1b4eab2c
Speedy: clean machine builder name (#6427)
* Address comment martin made in #6368

* changelog

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-19 14:58:13 +02:00
Moritz Kiefer
f5078046e4
Do not expect a specific location in ledger-api-test-tool (#6429)
* Do not expect a specific source location in ledger-api-test-tool

This broke running the ledger-api-test-tool against older ledgers
since the behavior of Speedy has changed slightly.

This PR changes `assertGrpcError` to accept a regex and uses that to
match for a wildcard in place of a specific location. I’ve gone
through the existing calls and added appropriate levels of escaping.

changelog_begin
changelog_end

* Pass an Option[Pattern] to avoid having to convert back to a String

changelog_begin
changelog_end
2020-06-19 14:28:43 +02:00
Gary Verhaegen
ddd8eec701
remove LedgerSession from LedgerTestSuite constructor (#6414)
This is another refactoring extracted from #6314. This is removing the
`LedgerSession` argument from `LedgerTestSuite`. The goal of this change
is to remove the closures from the `Tests.Tests` type, so it becomes a
plain map of name to test suite, rather than a map of name to
function-that-returns-a-test-suite.

In context, this is another step towards removing the name duplication
that occurs in the `Tests.default` and `Tests.optional` maps. I have
separated this step from the one that actually removes the duplication
because removing the duplication in #6314 was done by turning the maps
into seqs, thereby changing the order in which tests are run, which
caused the flakiness issues I've been investigating over the past week.

This commit does not yet change the order in which tests are run and is
therefore safe from that perspective. It's still a true refactoring.

It's a fairly simple one at that as `LedgerTestSuite` itself never uses
the session, and there was only one subclass that did. The subclass,
`TransactionScaleIT`, only used it to get at one config parameter. In
this PR, that config parameter is instead passed down directly to the
`Tests.default` method.

The other use of the `session` attribute was to extract it from the test
suite in order to pass it to the `run` method of
`LedgerTestSuiteRunner`. This was done right after creating the test
suites and giving them that same session, so we're now skipping that
round trip and just giving the session directly to `run`.

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-18 20:32:46 +02:00
Remy
86ceeea8d8
LF: shield value versioning in Transaction builder. (#6415)
We want to avoid that code outside LF version is own LF values.

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-18 17:20:47 +02:00
Remy
5a9e7ebc7c
Speedy: refactor Machine builders (#6368)
In this PR we cleanup the constructor for the speedy Machine.

* We remove the `case`  keyword since `Machine` is a stateful class,
* We replace the pre-existing builders with
  + one generic builder `Machine.apply`,
  + scenario specific builder,

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-18 15:39:55 +02:00
Gary Verhaegen
3e0fe58c53
rename test suites to match their names (#6409)
This is extracted from #6314. This is a simple renaming of a few
classes. The goal here is to have the `LedgerTestSuite#name` match the
key currently used in the `Tests.default` and `Tests.optional` maps so
that we can eventually remove that duplication (after the
`LedgerSession` argument is removed so we can actually construct the
`LedgerTestSuite` objects and ask them their name).

Note that `LedgerTestSuite#name` is [already defined][0] as:

```
  val name: String = getClass.getSimpleName
```

In the context of #6314, this is useful to align the existing behaviour
of `--include` with the desired future behaviour of `--exclude`, so we
can use the same names in both. Alternatives could be to remove the
`LedgerTestSuite#name` method and thread the key `String`s through to
the individual tests somehow, or make the `name` field a constructor
argument rather than reconstruct it based on the class name. This
approach of using the class name is the cleanest I could think of.

CHANGELOG_BEGIN
CHANGELOG_END

[0]: d01715bf2f/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuite.scala (L14)
2020-06-18 15:16:12 +02:00
Gary Verhaegen
3f5f907212
api test tool: remove dead code (#6408)
This is extracted from #6314, but actually has nothing to do with it.
This is removing two functions that are never called, as well as a type
that is never constructed (and the one pattern match on it).

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-18 14:52:11 +02:00
Gary Verhaegen
300895a802
remove ec from LedgerTestSuite (#6387)
`LedgerTestSuite` itself does not do anything with the `ExecutionContext`;
it is only used to provide it as an "ambient" implicit throughout each
test definition. Instead, with this PR, the `ExecutionContext` is
explicitly passed down as an additional argument to the `runTestCase`
closure.

For this not to change the behaviour of the program, we need to be
confident that the `ExecutionContext` is still the same. Let's first
look at how the `ExecutionContext` used to reach a test case. For any
execution of the test tool, there is only one `LedgerTestSuiteRunner`
created [by the main method][0], on which [we call][1] the
`verifyRequirementsAndRun` method. This in turn [calls][2] the `run`
method after checking that the given configuration is valid, and
[that][3] is where the `ExecutionContext` gets created. It is declared
as implicit so it gets picked up by the [`LedgerSession`][4] constructor
[call][5]. This (single) `LedgerSession` then [gets passed][6] to the
[constructor][7] of each individual `LedgerTestSuite`, which [extracts
the `ExecutionContext` from the session][8] to make it available to each
individual test created in the enclosing scope of a subclass when
calling the [`test`][9] method.

With this PR, the `ExecutionContext` is no longer extracted from the
`LedgerSession` in the `LedgerTestSuite` constructor, but is instead
threaded through to the `apply` method of `LedgerTestCase` through the
`run` (different signature) [call][10] for the individual test, which
itself [calls][11] `start`, which then [calls][12] the `apply` method of
`LedgerTestCase`. Because each of these methods (`run` and `start` on
`LedgerTestSuiterunner` and `apply` on `LedgerTestCase`) already
expected an implicit `ExecutionContext`, no change is required on the
`LedgerTestSuiteRunner` side.

A handful of helper functions in various test suites also needed to be
changed to fetch the `ExecutionContext` implicitly from their calling
context rather than capturing it lexically from the enclosing
`LedgerTestSuite`. This is, again, the same `ExecutionContext` it used
to be, but instead of getting it from the `LedgerSession` they get it
from the `LedgerTestCase` closure.

This was originally part of #6314, but despite it being a pure
refactoring, it is quite a large (and somewhat subtle) changeset, so I
believe it is better to review/merge separately.

CHANGELOG_BEGIN
CHANGELOG_END

[0]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/LedgerApiTestTool.scala (L125-L136)
[1]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/LedgerApiTestTool.scala (L138)
[2]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuiteRunner.scala (L155)
[3]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuiteRunner.scala (L119)
[4]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerSession.scala (L13-L16)
[5]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuiteRunner.scala (L122)
[6]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuiteRunner.scala (L123)
[7]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuite.scala (L13)
[8]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuite.scala (L20)
[9]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuite.scala (L22-L32)
[10]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuiteRunner.scala (L134)
[11]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuiteRunner.scala (L114)
[12]: 53bddb54d7/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/LedgerTestSuiteRunner.scala (L60)
2020-06-18 13:29:56 +02:00
Remy
cbe423fc6c
LF: rename library transaction-scalacheck to transaction-test-lib (#6347)
* LF: rename library transaction-scalacheck to transaction-test-lib

CHANGELOG_BEGIN
CHANGELOG_END

* move files in com/daml

* missing change in release/artifacts.yaml

* remove 'com/dam' from the path
2020-06-17 10:52:40 -04:00
Miklos
50ad201b11
Make conflict explanation deterministic (#6380) 2020-06-17 15:59:32 +02:00
Miklos
3373f92df6
Use consistent style for definition of metrics (#6351)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-16 10:57:30 +02:00
daravep
39c589af7a
Added minor logging to scala command client (#5906)
* Added minor logging to scala command client

Before, the scala command client did not log anything when a command was
leaving the application. Now, we get a small debug message that logs the
command id, which is going to be helpful for debugging and tracing
purposes.

CHANGELOG_BEGIN
CHANGELOG_END

* Addressed reviewer comments

* Fixed formatting
2020-06-16 08:34:12 +00:00
Remy
39ceac7a2c
LF: Change engine output from GenTransaction to VersionedTransaction (#6311)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-15 17:35:15 +02:00
Samir Talwar
5399f3ff44
ledger-api-client: More backwards-compatibility. (#6346)
Let's not break others' code until they've had a chance to migrate.
This changes `LedgerIdRequirement` so that properties don't change
types, and adds `@deprecated` where necessary.

There is one behavior change: `ledgerId` used to return whatever string
was passed in (typically `""`) if the requirement was not enabled. It
now throws an exception.

In the future, we will change the type of `ledgerId` to be
`Option[String]`, and make `optionalLedgerId` an alias for that
property.

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-15 14:26:13 +00:00
Stefano Baghino
55f9de87ca
Check application identifier when authorizing a Ledger API call (#6342)
* Check application identifier when authorizing a Ledger API call

Fixes #4409

changelog_begin
[Ledger API] Bugfix: the application identifier in a request is checked against
the authorization token. See https://github.com/digital-asset/daml/issues/4409.
changelog_end

* Fix accidental infinite loop

* Address a few comments from https://github.com/digital-asset/daml/pull/6342#pullrequestreview-430401649

- Address https://github.com/digital-asset/daml/pull/6342#discussion_r439992312
- Address https://github.com/digital-asset/daml/pull/6342#discussion_r439999084
- Address https://github.com/digital-asset/daml/pull/6342#discussion_r439999280

* Address https://github.com/digital-asset/daml/pull/6342#discussion_r440001538

As discussed in https://github.com/digital-asset/daml/pull/6342#discussion_r440003568

* Address https://github.com/digital-asset/daml/pull/6342#discussion_r439993762
2020-06-15 12:35:55 +00:00
Remy
45746ac604
Ledger: move TransactionBuilder in LF and use it more broadly (#6322)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-15 14:13:14 +02:00
Miklos
d033f6560e
Fix prefix for some validator metrics (#6343)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-15 13:43:45 +02:00
Miklos
bee5af77c1
Made CacheMetrics public so that caches defined outside of com.daml.metrics can be instrumented. (#6345)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-15 13:43:11 +02:00
Robert Autenrieth
31ccc8b9f5
Add cache for contract arguments during execution (#6289)
* Add cache for contract arguments during execution

Fixes #5754

CHANGELOG_BEGIN
CHANGELOG_END

* Add proper ADT for cache keys

* scalafmt

* Address review comments

* Separate contract and event caches

* Address review comments
2020-06-15 10:46:18 +02:00
Samir Talwar
858dbc67fd
ledger-api-client: Support legacy LedgerApiRequirement#copy behavior. (#6330)
* ledger-api-client: Clarify LedgerIdRequirementTest names.

* ledger-api-client: Re-add the old `LedgerApiRequirement#copy` behavior.

This is used by some users; we don't want to break their code if we can
help it.

CHANGELOG_BEGIN
- [Ledger API Client] The signature of `LedgerApiRequirement` has
  changed slightly. The old signature is now deprecated.
CHANGELOG_END

* ledger-api-client: Test deprecated LedgerApiRequirement behavior.
2020-06-15 07:56:36 +00:00
Simon Maxen
5329a4f97f
Ledger id requirement (#6323)
* Add option based constructor for LedgerIdRequirement

changelog_begin
changelog_end

* Make option based consructor the default, deprecate old constructor

* Update with review comments
2020-06-12 15:00:32 +00:00
Remy
5051383aca
Ledger: remove optionality of submissionSeed in TransactionMeta (#6307)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-11 17:49:59 +02:00
Remy
f487b051f9
Ledger: use standard transactions in the indexer (#6297)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-11 16:12:21 +02:00
Remy
cb23eb2c29
Ledger: use EventId instead of LedgerString (#6278)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-11 09:49:12 +02:00
Robert Autenrieth
ad16f563b4
Add CLI option for ledger time skew (#6287)
* Add CLI option for ledger time skew

CHANGELOG_BEGIN
- [sandbox] Added a CLI option for specifying the initial ledger time model
CHANGELOG_END

* scalafmt
2020-06-10 20:49:24 +02:00
Remy
acdca6533a
Indexer: Fix function newRoots in TransactionConversion. (#6272)
* reduce complexity from quadratic to linear
* output node in creating order
* avoid useless allocation of GenTransaction
* make it clearer

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-09 13:41:14 +02:00
Remy
5ff15a8ef5
DAML-LF: discriminate submitted and committed transactions (#6143)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-09 09:05:15 +02:00
Remy
00972f38b5
DAML-LF: split com.daml.lf.types.Ledger (#6264)
We split the object  com.daml.lf.types.ledger in three:
- one part in `com.daml.lf.ledger.` (in //daml-lf/transaction) for the part relative to EventId (shares between scenario service and sandbox)
- one part in `com.daml.lf.ledger.` (in //daml-lf/interpreter) for the part common to Blinding and Scenario
- one part in `com.daml.lf.scenario.` (in //daml-lf/interpreter) for the part specific to Scenario

fixes #6260

CHANGELOG_BEGIN
CHANGELOG_END
2020-06-08 17:29:10 +02:00
Remy
d064ea485f
DAML-LF: factorize ScenarioNodeId and EventId (#6256)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-08 16:00:42 +02:00
Robert Autenrieth
2a4e9dcaf3
Add metric for SQL commits (#6222)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-08 13:13:37 +02:00
Remy
1c0c30433b
kvutils: cosmetic factorization in protobuf conversions (#6235)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-05 15:41:15 +02:00
Davin K. Tanabe
ae463b6bea
sandbox: Wait for a database to be available instead of crashing immediately (#6146)
* sandbox: Wait for a database to be available instead of crashing immediately on startup.

changelog_begin
[Sandbox] Wait for a database to be available instead of crashing
immediately on startup.
changelog_end
2020-06-04 14:33:48 -04:00
Remy
bffc289868
DAML-LF: deprecate Transaction.TContractId (#6223)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-04 19:13:41 +02:00
Martin Huschenbett
4a176c4f46
Sandbox: Fix build instructions in README (#6227)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-04 15:52:51 +00:00
Miklos
60b46bbe57
Expose configuration of interceptors via LedgerFactory (#6224) 2020-06-04 17:13:04 +02:00
Stephen Compall
8e3e296572
factor common structure in RawBatch.Event (#6216)
CHANGELOG_BEGIN
CHANGELOG_END
2020-06-04 09:55:28 -04:00
Stefano Baghino
003549ecbf
Introduce CLI option for input buffer size (#6211)
* Introduce CLI option for input buffer size

Also improves CLI help text for other back-pressure related options.

changelog_begin
[Sandbox] Allow to configure --input-buffer-size, which allows to tune the number of commands waiting to be submitted before the Sandbox applies back-pressure, run daml sandbox --help for more info.
changelog_end

* Update ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/cli/Cli.scala

Co-authored-by: Samir Talwar <samir.talwar@digitalasset.com>

Co-authored-by: Samir Talwar <samir.talwar@digitalasset.com>
2020-06-04 06:50:50 +00:00
Miklos
b0c1b5a2b3
Improve batched submission validation related docs (#6186) 2020-06-03 15:20:09 +02:00
Moritz Kiefer
8fa28023e2
Fix --help output for sandbox time modes (#6206)
changelog_begin
changelog_end
2020-06-03 12:30:29 +02:00
Leonid Shlyapnikov
1386abc05a
move event witnesses directly into the participant_events table (#6172)
* events denormalization, WIP

* too soon to drop

* migration script

* add generated sha256 digest

* fixing the migration script naming

has to be double undescore after the version number

* flat event table queries

* write witnesses to events table during insert; disable inserts to witnesses tables

* use varchar[] for new witness columns instead of text[]

* ::varchar[] cast

* remove event witnesses table support code

* lookupFlatTransactionById works for postgres

* lookupTransactionTreeById works with postgres

* fixing the queries, replacing @> with &&

* cleanup

* multi-party postgres queries, WIP

* fixing multi-party queries, thanks @stefano.baghino

* fixing wildcardParties query

* minor cleanup

* h2 schema changes, h2 queries is WIP

* inlining some constants

* SqlFunctions introduced

* reformat

* Adding `SqlFunctions.arrayIntersectionValues`

* Adding `SqlFunctions.arrayIntersectionValues`

* Removing truncates for deleted tables

* Removing truncates for deleted tables

* filtering tree_event_witnesses

Co-authored-by: Stephen Compall <stephen.compall@daml.com>
2020-06-03 10:38:13 +02:00
Robert Autenrieth
dde5af0804
Add collectd metrics (#6189)
* Add collectd metrics

CHANGELOG_BEGIN
CHANGELOG_END

* Remove useless file

* Fix typo
2020-06-03 09:01:09 +02:00
Stephen Compall
39dc5aa88b
replace NodeExercises#controllers with controllersDifferFromActors boolean (#6073)
* replace NodeExercises#controllers with controllersDifferFromActors

* remove controllers from ActorMismatch and scenario service exercise

* no changelog

CHANGELOG_BEGIN
CHANGELOG_END

* remove reserved ID #s in scenario-service grpc

As discussed, we don't need to worry about
version mismatches.

Co-authored-by: Remy <remy.haemmerle@daml.com>
2020-06-02 13:43:47 -04:00
Miklos
5be061c2ef
Enable caching of immutable state values only (#6187)
* Moved caching related classes to under validator.caching package.

* Introduced CacheUpdatePolicy for controlling what type of state keys should be updated in the cache and when.

* Consistently use 'cache update policy'.
CHANGELOG_BEGIN
CHANGELOG_END

* Made it explicit what policy we are testing against.
2020-06-02 16:50:39 +00:00
Miklos
cb4917c812
Do not write output key whose value is identical to input (#6166)
CHANGELOG_BEGIN
* [kvutils] Do not commit output keys whose value is identical to input
CHANGELOG_END
2020-06-02 14:58:30 +02:00
Leonid Shlyapnikov
e097cf410b
Making PaginatingAsyncStream.streamFrom more generic (#6170)
* Making `PaginatingAsyncStream.streamFrom` more generic

so it does not specify what exactly `Offset` is.

changelog_begin
changelog_end

* Addressing code review comments + cleanup
2020-05-29 19:57:04 +00:00
Gerolf Seitz
e71e8e862d
Add LF value translation cache to Sandbox Classic (#6164)
* Add LF value translation cache to Sandbox Classic

CHANGELOG_BEGIN
CHANGELOG_END
2020-05-29 19:00:58 +02:00
Gerolf Seitz
070bd18951
More detailed store transaction metrics (#6163)
* Add additional metrics when storing transactions

Since event witnesses will soon be denormalized into the participant_events
table, I did not include metrics right now.

CHANGELOG_BEGIN
[DAML Ledger Integration Kit] Add additional metrics for storing transactions. The overall time is measured by ``daml.index.db.store_ledger_entry``.
- Timer ``daml.index.db.store_ledger_entry.prepare_batches``: measures the time for preparing batch insert/delete statements
- Timer ``daml.index.db.store_ledger_entry.events_batch``: measures the time for inserting events
- Timer ``daml.index.db.store_ledger_entry.delete_contract_witnesses_batch``:  measures the time for deleting contract witnesses
- Timer ``daml.index.db.store_ledger_entry.delete_contracts_batch``: measures the time for deleting contracts
- Timer ``daml.index.db.store_ledger_entry.insert_contracts_batch``: measures the time for inserting contracts
- Timer ``daml.index.db.store_ledger_entry.insert_contract_witnesses_batch``: measures the time for inserting contract witnesses
- Timer ``daml.index.db.store_ledger_entry.insert_completion``: measures the time for inserting the completion
- Timer ``daml.index.db.store_ledger_entry.update_ledger_end``: measures the time for updating the ledger end
[Sandbox Classic] Added Timer ``daml.index.db.store_ledger_entry.commit_validation``: measure the time for commit validation in Sandbox Classic

CHANGELOG_END

* Refactoring: rename metrics *dao to *DbMetrics
2020-05-29 18:19:54 +02:00
Leonid Shlyapnikov
12c05c408a
Experiment: replacing row OFFSET with ledger offset (#6083)
* Experiment: replacing row OFFSET with ledger offset in the flat transactions query for one party.

if this improves the perf numbers, the rest of the queries can be updated.

* Flat transaction query optimization:

replacing row offset with ledger offset

* Flat transaction query optimization:

replacing row offset with ledger offset

* transaction tree query optimization

changelog_begin

[Sandbox-next/Postgres]
Flat Transaction Stream, Transaction Tree Stream SQL query optimizations.
Pagination based on Ledger Offset instead of SQL Row Offset.

changelog_end

* Addressing code review comments
2020-05-29 11:49:46 -04:00