@reventlessdev/reventless-aws 3.0.0-alpha.419 → 3.0.0-alpha.421

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +9 -9
  3. package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +4 -1
  4. package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res.mjs +1 -1
  5. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +4 -1
  6. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res.mjs +1 -1
  7. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +4 -1
  8. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res.mjs +1 -1
  9. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res.mjs +3 -3
  10. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +4 -1
  11. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res.mjs +1 -1
  12. package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +4 -1
  13. package/src/adapter/EventCollector/EventCollectorChannel_SQS.res.mjs +1 -1
  14. package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +4 -1
  15. package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res.mjs +1 -1
  16. package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res.mjs +2 -2
  17. package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res.mjs +1 -1
  18. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +4 -1
  19. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +1 -1
  20. package/src/adapter/Postgres/PgProjectionFeed.res +4 -1
  21. package/src/adapter/Postgres/PgProjectionFeed.res.mjs +1 -1
  22. package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +12 -0
  23. package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs +4 -1
  24. package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res.mjs +14 -14
  25. package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res.mjs +4 -4
  26. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +5 -5
  27. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +3 -3
  28. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +2 -2
  29. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res.mjs +1 -1
  30. package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +18 -1
  31. package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res.mjs +20 -6
  32. package/src/adapter/ScheduledPublisher/ScheduledPublisher_EventBridgeScheduler_Runtime.res.mjs +1 -1
  33. package/src/plugin/runtime/Util_PluginMessage_Runtime.res.mjs +1 -1
  34. package/src/util/Util_CognitoGroupUser_Runtime.res.mjs +2 -2
  35. package/src/util/Util_Cognito_Runtime.res.mjs +1 -1
  36. package/src/util/Util_DeadLetterHandler.res +138 -0
  37. package/src/util/Util_DeadLetterHandler.res.mjs +113 -0
  38. package/src/util/Util_DeadLetterQueue.res +10 -53
  39. package/src/util/Util_DeadLetterQueue.res.mjs +6 -26
  40. package/src/util/Util_DynamoDb_Runtime.res.mjs +4 -4
  41. package/src/util/Util_Kinesis_Runtime.res.mjs +1 -1
  42. package/src/util/Util_SNS_Runtime.res.mjs +2 -2
  43. package/src/util/Util_SQS_Runtime.res.mjs +5 -5
  44. package/tests/Util_DeadLetterHandlerTest.res +78 -0
  45. package/tests/Util_DeadLetterHandlerTest.res.mjs +101 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,24 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.421 (2026-11-02)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **aws:** a dead letter's first delivery writes its full line ([3436633](https://github.com/ReventlessDev/reventless-core/commit/3436633809b671fc750fc5f717523f080c084b64))
11
+ ### Features
12
+
13
+ * a view row knows its last change, and the local platform keeps every change ([1a1fd71](https://github.com/ReventlessDev/reventless-core/commit/1a1fd7117d9837696a7c0080dcd6f0983e57780c))
14
+ * **local:** the app's API logs each request and subscription it answers ([31a163c](https://github.com/ReventlessDev/reventless-core/commit/31a163c945d8929e9a604cc0dc8a74939320f85e))
15
+
16
+
17
+ # 3.0.0-alpha.420 (2026-11-01)
18
+
19
+ ### Features
20
+
21
+ * **core:** a component's log line carries the ids of the message it is about ([9c26267](https://github.com/ReventlessDev/reventless-core/commit/9c26267ca6d03ff66b8406caa32243e205e29b5a))
22
+
23
+
6
24
  # 3.0.0-alpha.419 (2026-11-01)
7
25
 
8
26
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-aws",
3
- "version": "3.0.0-alpha.419",
3
+ "version": "3.0.0-alpha.421",
4
4
  "description": "AWS adapters for Reventless",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -22,19 +22,19 @@
22
22
  "sury": "11.0.0",
23
23
  "uuid": "^13.0.0",
24
24
  "yaml": "^2.8.3",
25
- "@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.38",
25
+ "@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.39",
26
+ "@reventlessdev/rescript-node": "2.0.0-alpha.26",
26
27
  "@reventlessdev/rescript-effect": "1.0.0-alpha.1",
28
+ "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.39",
27
29
  "@reventlessdev/rescript-jest": "1.0.0-alpha.13",
28
- "@reventlessdev/rescript-node": "2.0.0-alpha.25",
29
- "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.38",
30
30
  "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
31
- "@reventlessdev/rescript-web": "1.0.0-alpha.8",
32
31
  "@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
33
- "@reventlessdev/reventless-core": "3.0.0-alpha.326",
32
+ "@reventlessdev/rescript-web": "1.0.0-alpha.8",
33
+ "@reventlessdev/reventless-core": "3.0.0-alpha.328",
34
34
  "@reventlessdev/reventless-interop": "3.0.0-alpha.42",
35
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.190",
36
- "@reventlessdev/reventless-infra": "3.0.0-alpha.221",
37
- "@reventlessdev/reventless-spec": "3.0.0-alpha.192"
35
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.193",
36
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.222",
37
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.192"
38
38
  },
39
39
  "devDependencies": {
40
40
  "rescript": "12.3.1",
@@ -60,7 +60,10 @@ let make: ReventlessCore.CommandTopic_Adapter.channelMaker<
60
60
  PulumiAws.SQS.Queue.visibilityTimeoutSeconds: (6 * 30)->Pulumi.Input.make, // TODO rethink timeout
61
61
  redrivePolicy: Util_DeadLetterQueue.queue.arn
62
62
  ->Pulumi.Output.apply(dlqArn =>
63
- PulumiAws.SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
63
+ PulumiAws.SQS.Queue.RedrivePolicy.make(
64
+ ~deadLetterTargetArn=dlqArn,
65
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
66
+ )
64
67
  )
65
68
  ->Pulumi.Output.asInput,
66
69
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -43,7 +43,7 @@ function make(name, owner, opts) {
43
43
  let opts$1 = Stdlib_Option.map(opts, Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions);
44
44
  let tags = AWS_Tags$ReventlessAws.make(name, CommandTopic$ReventlessCore.componentType, "CommandTopic", undefined, undefined, owner, undefined, undefined);
45
45
  let queue = new (Aws.sqs.Queue)(name, {
46
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
46
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
47
47
  tags: tags,
48
48
  visibilityTimeoutSeconds: 180,
49
49
  sqsManagedSseEnabled: false
@@ -37,7 +37,10 @@ let make: ReventlessCore.CommandTopic_Adapter.channelMaker<
37
37
  visibilityTimeoutSeconds: (6 * 30)->Pulumi.Input.make,
38
38
  redrivePolicy: Util_DeadLetterQueue.fifoQueue.arn
39
39
  ->Pulumi.Output.apply(dlqArn => {
40
- PulumiAws.SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
40
+ PulumiAws.SQS.Queue.RedrivePolicy.make(
41
+ ~deadLetterTargetArn=dlqArn,
42
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
43
+ )
41
44
  })
42
45
  ->Pulumi.Output.asInput,
43
46
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -24,7 +24,7 @@ function make(name, owner, opts) {
24
24
  let queue = new (Aws.sqs.Queue)(name, {
25
25
  contentBasedDeduplication: true,
26
26
  fifoQueue: true,
27
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.fifoQueue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
27
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.fifoQueue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
28
28
  tags: tags,
29
29
  visibilityTimeoutSeconds: 180,
30
30
  deduplicationScope: "messageGroup",
@@ -26,7 +26,10 @@ let make: ReventlessCore.CommandTopic_Adapter.channelMaker<
26
26
  visibilityTimeoutSeconds: (6 * 30)->Pulumi.Input.make,
27
27
  redrivePolicy: Util_DeadLetterQueue.fifoQueue.arn
28
28
  ->Pulumi.Output.apply(dlqArn => {
29
- PulumiAws.SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
29
+ PulumiAws.SQS.Queue.RedrivePolicy.make(
30
+ ~deadLetterTargetArn=dlqArn,
31
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
32
+ )
30
33
  })
31
34
  ->Pulumi.Output.asInput,
32
35
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -24,7 +24,7 @@ function make(name, owner, opts) {
24
24
  let queue = new (Aws.sqs.Queue)(name, {
25
25
  contentBasedDeduplication: true,
26
26
  fifoQueue: true,
27
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.fifoQueue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
27
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.fifoQueue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
28
28
  tags: tags,
29
29
  visibilityTimeoutSeconds: 180,
30
30
  deduplicationScope: "messageGroup",
@@ -31,10 +31,10 @@ function handleQueueEvent(queue, handleJsonCommands) {
31
31
  ReceiptHandle: result._0
32
32
  };
33
33
  }
34
- Effect.runSync(EffectLogger$ReventlessCore.logError("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, "handleQueueEvent: Couldn't handle command with ReceiptHandle: " + result._0));
34
+ Effect.runSync(EffectLogger$ReventlessCore.logError("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, undefined, "handleQueueEvent: Couldn't handle command with ReceiptHandle: " + result._0));
35
35
  }), x => x);
36
36
  if (deleteEntries.length !== 0) {
37
- return Effect.catchAll(Effect.tap(Util_SQS_Runtime$ReventlessAws.deleteMessages(deleteEntries, queue), () => EffectLogger$ReventlessCore.logInfo("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, "handleQueueEvent: Deleted all commands from queue")), errorMsg => EffectLogger$ReventlessCore.logError("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, "handleQueueEvent: Couldn't deleteMessageBatch: " + errorMsg));
37
+ return Effect.catchAll(Effect.tap(Util_SQS_Runtime$ReventlessAws.deleteMessages(deleteEntries, queue), () => EffectLogger$ReventlessCore.logInfo("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, undefined, "handleQueueEvent: Deleted all commands from queue")), errorMsg => EffectLogger$ReventlessCore.logError("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, undefined, "handleQueueEvent: Couldn't deleteMessageBatch: " + errorMsg));
38
38
  } else {
39
39
  return Effect.succeed();
40
40
  }
@@ -52,7 +52,7 @@ function publishJsons(queue, queueService) {
52
52
  return await Effect.runPromise(Util_SQS_Runtime$ReventlessAws.send(queue, queueService, jsons[0]));
53
53
  }
54
54
  } else {
55
- Effect.runPromise(EffectLogger$ReventlessCore.logInfo("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, "publishJsons: No commands to send"));
55
+ Effect.runPromise(EffectLogger$ReventlessCore.logInfo("CommandTopicChannel_SQS_Runtime-ReventlessAws", undefined, undefined, "publishJsons: No commands to send"));
56
56
  return;
57
57
  }
58
58
  };
@@ -40,7 +40,10 @@ let make: ReventlessCore.CommandTopic_Adapter.channelMaker<
40
40
  PulumiAws.SQS.Queue.visibilityTimeoutSeconds: (6 * 30)->Pulumi.Input.make,
41
41
  redrivePolicy: Util_DeadLetterQueue.queue.arn
42
42
  ->Pulumi.Output.apply(dlqArn =>
43
- PulumiAws.SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
43
+ PulumiAws.SQS.Queue.RedrivePolicy.make(
44
+ ~deadLetterTargetArn=dlqArn,
45
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
46
+ )
44
47
  )
45
48
  ->Pulumi.Output.asInput,
46
49
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -23,7 +23,7 @@ function make(name, owner, opts) {
23
23
  let opts$1 = Stdlib_Option.map(opts, Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions);
24
24
  let tags = AWS_Tags$ReventlessAws.make(name, CommandTopic$ReventlessCore.componentType, "CommandTopic", undefined, undefined, owner, undefined, undefined);
25
25
  let queue = new (Aws.sqs.Queue)(name, {
26
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
26
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
27
27
  tags: tags,
28
28
  visibilityTimeoutSeconds: 180,
29
29
  sqsManagedSseEnabled: false
@@ -49,7 +49,10 @@ let make: ReventlessCore.EventCollector_Adapter.channelMaker<
49
49
  PulumiAws.SQS.Queue.visibilityTimeoutSeconds: 120->Pulumi.Input.make,
50
50
  redrivePolicy: Util_DeadLetterQueue.queue.arn
51
51
  ->Pulumi.Output.apply(dlqArn =>
52
- PulumiAws.SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
52
+ PulumiAws.SQS.Queue.RedrivePolicy.make(
53
+ ~deadLetterTargetArn=dlqArn,
54
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
55
+ )
53
56
  )
54
57
  ->Pulumi.Output.asInput,
55
58
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -29,7 +29,7 @@ function make(name, eventTopics, owner, opts) {
29
29
  let opts$1 = Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions(opts);
30
30
  let tags = AWS_Tags$ReventlessAws.make(name, EventCollector$ReventlessCore.componentType, "EventCollector", undefined, undefined, owner, undefined, undefined);
31
31
  let queue = new (Aws.sqs.Queue)(name, {
32
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
32
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
33
33
  tags: tags,
34
34
  visibilityTimeoutSeconds: 120,
35
35
  sqsManagedSseEnabled: false
@@ -27,7 +27,10 @@ let make: ReventlessCore.EventCollector_Adapter.channelMaker<
27
27
  visibilityTimeoutSeconds: 30->Pulumi.Input.make, // TODO fix timeout
28
28
  redrivePolicy: Util_DeadLetterQueue.fifoQueue.arn
29
29
  ->Pulumi.Output.apply(dlqArn =>
30
- PulumiAws.SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
30
+ PulumiAws.SQS.Queue.RedrivePolicy.make(
31
+ ~deadLetterTargetArn=dlqArn,
32
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
33
+ )
31
34
  )
32
35
  ->Pulumi.Output.asInput,
33
36
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -16,7 +16,7 @@ function make(name, eventTopics, owner, opts) {
16
16
  let queue = new (Aws.sqs.Queue)(name, {
17
17
  contentBasedDeduplication: true,
18
18
  fifoQueue: true,
19
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.fifoQueue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
19
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.fifoQueue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
20
20
  tags: tags,
21
21
  visibilityTimeoutSeconds: 30,
22
22
  deduplicationScope: "messageGroup",
@@ -73,11 +73,11 @@ function handleDynamoDbEvent(handleEvents) {
73
73
  }
74
74
 
75
75
  function enqueueEvent(queue, delay, _id, messageBody) {
76
- return Effect.runPromise(Effect.map(Effect.flatMap(EffectLogger$ReventlessCore.logInfo("EventCollectorChannel_SQS_Runtime-ReventlessAws", undefined, "enqueueEvent: " + delay.toString() + " " + messageBody + " " + queue.name), () => Effect.promise(() => Util_SQS_Runtime$ReventlessAws.sendMessage(queue, delay, messageBody))), () => {}));
76
+ return Effect.runPromise(Effect.map(Effect.flatMap(EffectLogger$ReventlessCore.logInfo("EventCollectorChannel_SQS_Runtime-ReventlessAws", undefined, undefined, "enqueueEvent: " + delay.toString() + " " + messageBody + " " + queue.name), () => Effect.promise(() => Util_SQS_Runtime$ReventlessAws.sendMessage(queue, delay, messageBody))), () => {}));
77
77
  }
78
78
 
79
79
  function enqueueFifoEvent(queue, delay, id, messageBody) {
80
- return Effect.runPromise(Effect.map(Effect.flatMap(EffectLogger$ReventlessCore.logInfo("EventCollectorChannel_SQS_Runtime-ReventlessAws", undefined, "enqueueFifoEvent: " + delay.toString() + " " + messageBody + " " + queue.name), () => Effect.promise(() => Util_SQS_Runtime$ReventlessAws.sendFifoMessage(queue, delay, Util_SQS_Runtime$ReventlessAws.safeGroupId(id), messageBody))), () => {}));
80
+ return Effect.runPromise(Effect.map(Effect.flatMap(EffectLogger$ReventlessCore.logInfo("EventCollectorChannel_SQS_Runtime-ReventlessAws", undefined, undefined, "enqueueFifoEvent: " + delay.toString() + " " + messageBody + " " + queue.name), () => Effect.promise(() => Util_SQS_Runtime$ReventlessAws.sendFifoMessage(queue, delay, Util_SQS_Runtime$ReventlessAws.safeGroupId(id), messageBody))), () => {}));
81
81
  }
82
82
 
83
83
  export {
@@ -248,7 +248,7 @@ function replayStream(table) {
248
248
  }
249
249
 
250
250
  function replay(table) {
251
- return id => Effect$1.runPromise(Effect$1.catchAll(Stream.runCollect(replayStream(table)(id, undefined)), msg => Effect$1.flatMap(EffectLogger$ReventlessCore.logError("EventLogStorage_DynamoDb_Runtime-ReventlessAws", undefined, `Couldn't replay events for id ` + id + ` after retries: ` + msg), () => Effect$1.fail(msg))));
251
+ return id => Effect$1.runPromise(Effect$1.catchAll(Stream.runCollect(replayStream(table)(id, undefined)), msg => Effect$1.flatMap(EffectLogger$ReventlessCore.logError("EventLogStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `Couldn't replay events for id ` + id + ` after retries: ` + msg), () => Effect$1.fail(msg))));
252
252
  }
253
253
 
254
254
  function appendStream(table) {
@@ -39,7 +39,10 @@ let make = (
39
39
  SQS.Queue.visibilityTimeoutSeconds: 60->Pulumi.Input.make,
40
40
  redrivePolicy: Util_DeadLetterQueue.queue.arn
41
41
  ->Pulumi.Output.apply(dlqArn =>
42
- SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
42
+ SQS.Queue.RedrivePolicy.make(
43
+ ~deadLetterTargetArn=dlqArn,
44
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
45
+ )
43
46
  )
44
47
  ->Pulumi.Output.asInput,
45
48
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -21,7 +21,7 @@ function channelNameOf(topicName) {
21
21
 
22
22
  function make(name, topicName, eventTopicOutputs, eventsApi, opts) {
23
23
  let queue = new (Aws.sqs.Queue)(name + "EventLogSubQueue", {
24
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
24
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
25
25
  tags: AWS_Tags$ReventlessAws.make(name + "EventLogSubQueue", EventTopic$ReventlessCore.componentType, "EventLogSubscription", undefined, name, undefined, undefined, undefined),
26
26
  visibilityTimeoutSeconds: 60,
27
27
  sqsManagedSseEnabled: false
@@ -47,7 +47,10 @@ let makeQueue = (
47
47
  PulumiAws.SQS.Queue.visibilityTimeoutSeconds: 120->Pulumi.Input.make,
48
48
  redrivePolicy: Util_DeadLetterQueue.queue.arn
49
49
  ->Pulumi.Output.apply(dlqArn =>
50
- PulumiAws.SQS.Queue.RedrivePolicy.make(~deadLetterTargetArn=dlqArn, ~maxReceiveCount=5)
50
+ PulumiAws.SQS.Queue.RedrivePolicy.make(
51
+ ~deadLetterTargetArn=dlqArn,
52
+ ~maxReceiveCount=Util_DeadLetterQueue.maxReceiveCount,
53
+ )
51
54
  )
52
55
  ->Pulumi.Output.asInput,
53
56
  sqsManagedSseEnabled: false->Pulumi.Input.make,
@@ -15,7 +15,7 @@ function getFeedQueues() {
15
15
 
16
16
  function makeQueue(name, scope, includeClassic, includeDcb, opts) {
17
17
  let queue = new (Aws.sqs.Queue)(name, {
18
- redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, 5)),
18
+ redrivePolicy: Util_DeadLetterQueue$ReventlessAws.queue.arn.apply(dlqArn => SQS_Queue$PulumiAws.RedrivePolicy.make(dlqArn, Util_DeadLetterQueue$ReventlessAws.maxReceiveCount)),
19
19
  tags: AWS_Tags$ReventlessAws.make(name, "Plugin", "EventCollector", "Plugin", undefined, undefined, undefined, undefined),
20
20
  visibilityTimeoutSeconds: 120,
21
21
  sqsManagedSseEnabled: false
@@ -709,12 +709,24 @@ let make: ReventlessCore.QueryDb_Adapter.resolversMaker<api, role> = (
709
709
  // is independent of whether this view has a sub-id door, and adding a third
710
710
  // dimension to that match would spell eight cases to say one thing.
711
711
  let refsResolvers = resolverRefs->Option.mapOr([], r => [r])
712
+ // The row's last change, for an elevated caller only. A field resolver, so it also covers
713
+ // a row reached through another view's cross-table field.
714
+ let changeResolver = Resolver.makeUnitJsResolver(
715
+ ~name=name ++ "RowChange",
716
+ ~api,
717
+ ~dataSourceName,
718
+ ~type_=parentTypeName->Pulumi.Input.make,
719
+ ~field=ReventlessCore.RowChange.key->Pulumi.Input.make,
720
+ ~code=Resolver.Functions.rowChangeField(~field=ReventlessCore.RowChange.key, ~elevatedGroups),
721
+ ~opts,
722
+ )
712
723
  Array.flat([
713
724
  mainResolvers,
714
725
  refsResolvers,
715
726
  resolversByIndex,
716
727
  idResolvers,
717
728
  idsResolvers,
729
+ [changeResolver],
718
730
  ])->Array.map(Util.AppSync.toResourceNative)
719
731
  }
720
732
 
@@ -9,6 +9,7 @@ import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/compon
9
9
  import * as Logger$ReventlessCore from "@reventlessdev/reventless-core/src/util/Logger.res.mjs";
10
10
  import * as OwnerScope$Reventless from "@reventlessdev/reventless-spec/src/types/OwnerScope.res.mjs";
11
11
  import * as Adapter$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Adapter.res.mjs";
12
+ import * as RowChange$ReventlessCore from "@reventlessdev/reventless-core/src/RowChange.res.mjs";
12
13
  import * as AppSync_Function$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/AppSync/AppSync_Function.res.mjs";
13
14
  import * as Util_AppSync$ReventlessAws from "../../util/Util_AppSync.res.mjs";
14
15
  import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
@@ -303,12 +304,14 @@ function make(name, api, apiRole, dataSourceName, indexes, subIdField, idResolve
303
304
  ]
304
305
  );
305
306
  let refsResolvers = Stdlib_Option.mapOr(resolverRefs, [], r => [r]);
307
+ let changeResolver = AppSync_Resolver_Retrying$ReventlessAws.makeUnitJsResolver(name$1 + "RowChange", api, dataSourceName, parentTypeName, RowChange$ReventlessCore.key, AppSync_Resolver_Functions$PulumiAws.rowChangeField(RowChange$ReventlessCore.key, elevatedGroups), opts);
306
308
  return [
307
309
  mainResolvers,
308
310
  refsResolvers,
309
311
  resolversByIndex,
310
312
  idResolvers,
311
- idsResolvers
313
+ idsResolvers,
314
+ [changeResolver]
312
315
  ].flat().map(Util_AppSync$ReventlessAws.toResourceNative);
313
316
  };
314
317
  return {
@@ -56,7 +56,7 @@ function load(table) {
56
56
  })), err => {
57
57
  let tableName = table.name;
58
58
  let msg = QueryDb$ReventlessCore.storageErrorToString(err);
59
- return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `load: Couldn't load state for ` + id + ` from ` + tableName + `: ` + msg), () => ({
59
+ return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `load: Couldn't load state for ` + id + ` from ` + tableName + `: ` + msg), () => ({
60
60
  TAG: "Error",
61
61
  _0: err
62
62
  }));
@@ -73,13 +73,13 @@ function save(table) {
73
73
  case "Init" :
74
74
  tmp = Effect$1.flatMap(Util_DynamoDb_Runtime$ReventlessAws.putIfNotExistsWithRetries(table.hashKey, table.rangeKey, table, id, json$1), result => {
75
75
  if (result.TAG === "Ok") {
76
- return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `save: saved Init state to ` + tableName + `: id=` + id), () => ({
76
+ return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `save: saved Init state to ` + tableName + `: id=` + id), () => ({
77
77
  TAG: "Ok",
78
78
  _0: undefined
79
79
  }));
80
80
  }
81
81
  let errorMsg = result._0;
82
- return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `save: Couldn't save Init state to ` + tableName + `, id=` + id + `: ` + errorMsg), () => ({
82
+ return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `save: Couldn't save Init state to ` + tableName + `, id=` + id + `: ` + errorMsg), () => ({
83
83
  TAG: "Error",
84
84
  _0: {
85
85
  TAG: "NotSavedToStorage",
@@ -96,13 +96,13 @@ function save(table) {
96
96
  if (exit === 1) {
97
97
  tmp = Effect$1.flatMap(Util_DynamoDb_Runtime$ReventlessAws.putWithRetries(table, id, json$1), result => {
98
98
  if (result.TAG === "Ok") {
99
- return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `save: saved state to ` + tableName + `: id=` + id), () => ({
99
+ return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `save: saved state to ` + tableName + `: id=` + id), () => ({
100
100
  TAG: "Ok",
101
101
  _0: undefined
102
102
  }));
103
103
  }
104
104
  let errorMsg = result._0;
105
- return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `save: Couldn't save state to ` + tableName + `, id=` + id + `: ` + errorMsg), () => ({
105
+ return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `save: Couldn't save state to ` + tableName + `, id=` + id + `: ` + errorMsg), () => ({
106
106
  TAG: "Error",
107
107
  _0: {
108
108
  TAG: "NotSavedToStorage",
@@ -127,7 +127,7 @@ function writeMultiple(writeRequests, op, ids, table) {
127
127
  let allIdsStr = ids.join(", ");
128
128
  let size = writeRequests.length;
129
129
  let batches = Stdlib_Math.Int.ceil(size / DynamoDb_DocumentClient$AwsSdk.BatchWriteCommand.maxBatchSize);
130
- let logSplitEffect = batches > 1 ? EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `writeBatch: splitting up batch of size ` + size.toString() + ` into ` + batches.toString() + ` batches`) : Effect$1.succeed();
130
+ let logSplitEffect = batches > 1 ? EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `writeBatch: splitting up batch of size ` + size.toString() + ` into ` + batches.toString() + ` batches`) : Effect$1.succeed();
131
131
  let batchEffects = Stdlib_Array.fromInitializer(batches, batchNr => Effect$1.map(Util_DynamoDb_Runtime$ReventlessAws.batchWriteWithRetries(Util_DynamoDb_Runtime$ReventlessAws.toTable(sliceBatch(writeRequests, batchNr), tableName)), result => {
132
132
  let batchIds = sliceBatch(ids, batchNr);
133
133
  let batchCount = batchIds.length.toString();
@@ -142,14 +142,14 @@ function writeMultiple(writeRequests, op, ids, table) {
142
142
  concurrency: "unbounded"
143
143
  })), results => Stdlib_Array.filterMap(results, x => x)), errors => {
144
144
  if (errors.length === 0) {
145
- return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `writeBatch: ` + op + ` ` + count + ` states: ` + tableName + `, ids:` + allIdsStr), () => ({
145
+ return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `writeBatch: ` + op + ` ` + count + ` states: ` + tableName + `, ids:` + allIdsStr), () => ({
146
146
  TAG: "Ok",
147
147
  _0: undefined
148
148
  }));
149
149
  }
150
150
  let errorsStr = errors.join("; ");
151
151
  let errorMsg = `writeBatch: Couldn't save states to ` + tableName + `: ` + errorsStr;
152
- return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, errorMsg), () => ({
152
+ return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, errorMsg), () => ({
153
153
  TAG: "Error",
154
154
  _0: {
155
155
  TAG: "BatchNotFullyWrittenToStorage",
@@ -159,7 +159,7 @@ function writeMultiple(writeRequests, op, ids, table) {
159
159
  }), err => {
160
160
  let msg = DynamoDb_Error$ReventlessAws.message(err);
161
161
  let errorMsg = `writeBatch: Couldn't save states to ` + tableName + `, ` + count + ` ids:` + allIdsStr + `: ` + msg;
162
- return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, errorMsg), () => ({
162
+ return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, errorMsg), () => ({
163
163
  TAG: "Error",
164
164
  _0: {
165
165
  TAG: "BatchNotFullyWrittenToStorage",
@@ -190,7 +190,7 @@ function saveBatch(table) {
190
190
  function count(table) {
191
191
  return (id, fieldName, inc) => {
192
192
  let tableName = table.name;
193
- return Effect$1.runPromise(Effect$1.catchAll(Effect$1.flatMap(Effect$1.flatMap(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `count: ` + tableName + `, ` + id + `, ` + fieldName + `, ` + inc.toString()), () => Effect.tryPromise(err => Util_Error$ReventlessCore.messageFromUnknown(err, "count"), () => DynamoDb_DocumentClient$AwsSdk.UpdateCommand.send(new LibDynamodb.UpdateCommand({
193
+ return Effect$1.runPromise(Effect$1.catchAll(Effect$1.flatMap(Effect$1.flatMap(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `count: ` + tableName + `, ` + id + `, ` + fieldName + `, ` + inc.toString()), () => Effect.tryPromise(err => Util_Error$ReventlessCore.messageFromUnknown(err, "count"), () => DynamoDb_DocumentClient$AwsSdk.UpdateCommand.send(new LibDynamodb.UpdateCommand({
194
194
  Key: Object.fromEntries([[
195
195
  "id",
196
196
  id
@@ -214,7 +214,7 @@ function count(table) {
214
214
  _0: value
215
215
  });
216
216
  } else {
217
- return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `count: Invalid updateOutput in count on ` + tableName), () => ({
217
+ return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `count: Invalid updateOutput in count on ` + tableName), () => ({
218
218
  TAG: "Error",
219
219
  _0: {
220
220
  TAG: "NotCountedOnStorage",
@@ -222,7 +222,7 @@ function count(table) {
222
222
  }
223
223
  }));
224
224
  }
225
- }), errorMsg => Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `count: Couldn't count on ` + tableName + `: ` + errorMsg), () => ({
225
+ }), errorMsg => Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `count: Couldn't count on ` + tableName + `: ` + errorMsg), () => ({
226
226
  TAG: "Error",
227
227
  _0: {
228
228
  TAG: "NotCountedOnStorage",
@@ -237,13 +237,13 @@ function $$delete(table) {
237
237
  let tableName = table.name;
238
238
  return Effect$1.runPromise(Effect$1.flatMap(Util_DynamoDb_Runtime$ReventlessAws.deleteWithRetries(sort, table, id), result => {
239
239
  if (result.TAG === "Ok") {
240
- return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `delete: deleted state from ` + tableName + `: id=` + id + `, sort=` + Stdlib_Option.getOr(JSON.stringify(sort), "None")), () => ({
240
+ return Effect$1.map(EffectLogger$ReventlessCore.logInfo("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `delete: deleted state from ` + tableName + `: id=` + id + `, sort=` + Stdlib_Option.getOr(JSON.stringify(sort), "None")), () => ({
241
241
  TAG: "Ok",
242
242
  _0: undefined
243
243
  }));
244
244
  }
245
245
  let errorMsg = result._0;
246
- return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, `delete: Couldn't delete state from ` + tableName + `, id=` + id + `, sort=` + Stdlib_Option.getOr(JSON.stringify(sort), "None") + `: ` + errorMsg), () => ({
246
+ return Effect$1.map(EffectLogger$ReventlessCore.logError("QueryDbStorage_DynamoDb_Runtime-ReventlessAws", undefined, undefined, `delete: Couldn't delete state from ` + tableName + `, id=` + id + `, sort=` + Stdlib_Option.getOr(JSON.stringify(sort), "None") + `: ` + errorMsg), () => ({
247
247
  TAG: "Error",
248
248
  _0: {
249
249
  TAG: "NotDeletedFromStorage",
@@ -167,9 +167,9 @@ function queryByTableName(tableName, keyOpt, id, subIdConfig, filterConfigsOpt,
167
167
  Limit: params_Limit,
168
168
  ScanIndexForward: params_ScanIndexForward
169
169
  };
170
- return Effect.runPromise(Effect.flatMap(EffectLogger$ReventlessCore.logDebug("QueryEngine_DynamoDb-ReventlessAws", undefined, "queryByTableName params: " + LogFormat$ReventlessCore.truncate(Stdlib_Option.getOr(JSON.stringify(params), ""))), () => Effect.catchAll(Effect.map(Stream.runCollect(Util_DynamoDb_Runtime$ReventlessAws.queryStream(params)), items => items.map(js => JSON.parse(JSON.stringify(js)))), err => {
170
+ return Effect.runPromise(Effect.flatMap(EffectLogger$ReventlessCore.logDebug("QueryEngine_DynamoDb-ReventlessAws", undefined, undefined, "queryByTableName params: " + LogFormat$ReventlessCore.truncate(Stdlib_Option.getOr(JSON.stringify(params), ""))), () => Effect.catchAll(Effect.map(Stream.runCollect(Util_DynamoDb_Runtime$ReventlessAws.queryStream(params)), items => items.map(js => JSON.parse(JSON.stringify(js)))), err => {
171
171
  let msg = DynamoDb_Error$ReventlessAws.message(err);
172
- return Effect.map(EffectLogger$ReventlessCore.logError("QueryEngine_DynamoDb-ReventlessAws", undefined, "queryByTableName: " + msg), () => []);
172
+ return Effect.map(EffectLogger$ReventlessCore.logError("QueryEngine_DynamoDb-ReventlessAws", undefined, undefined, "queryByTableName: " + msg), () => []);
173
173
  })));
174
174
  }
175
175
 
@@ -197,9 +197,9 @@ function scanByTableName(tableName, filterConfigs, limit) {
197
197
  FilterExpression: params_FilterExpression,
198
198
  Limit: params_Limit
199
199
  };
200
- return Effect.runPromise(Effect.flatMap(EffectLogger$ReventlessCore.logDebug("QueryEngine_DynamoDb-ReventlessAws", undefined, "scanByTableName params: " + LogFormat$ReventlessCore.truncate(Stdlib_Option.getOr(JSON.stringify(params), ""))), () => Effect.catchAll(Effect.map(Stream.runCollect(Util_DynamoDb_Runtime$ReventlessAws.scanStream(params)), items => items.map(js => JSON.parse(JSON.stringify(js)))), err => {
200
+ return Effect.runPromise(Effect.flatMap(EffectLogger$ReventlessCore.logDebug("QueryEngine_DynamoDb-ReventlessAws", undefined, undefined, "scanByTableName params: " + LogFormat$ReventlessCore.truncate(Stdlib_Option.getOr(JSON.stringify(params), ""))), () => Effect.catchAll(Effect.map(Stream.runCollect(Util_DynamoDb_Runtime$ReventlessAws.scanStream(params)), items => items.map(js => JSON.parse(JSON.stringify(js)))), err => {
201
201
  let msg = DynamoDb_Error$ReventlessAws.message(err);
202
- return Effect.map(EffectLogger$ReventlessCore.logError("QueryEngine_DynamoDb-ReventlessAws", undefined, "scanByTableName: " + msg), () => []);
202
+ return Effect.map(EffectLogger$ReventlessCore.logError("QueryEngine_DynamoDb-ReventlessAws", undefined, undefined, "scanByTableName: " + msg), () => []);
203
203
  })));
204
204
  }
205
205
 
@@ -187,9 +187,9 @@ function makeLoadTodoItems(queryDbTableName, todoItems, rowSchema, comp) {
187
187
  }
188
188
  todoItems[id] = row;
189
189
  return count + 1 | 0;
190
- })), err => Effect.map(EffectLogger$ReventlessCore.logError(comp, undefined, `restore: couldn't read pending TODO rows from ` + queryDbTableName + `: ` + DynamoDb_Error$ReventlessAws.message(err)), () => 0)));
190
+ })), err => Effect.map(EffectLogger$ReventlessCore.logError(comp, undefined, undefined, `restore: couldn't read pending TODO rows from ` + queryDbTableName + `: ` + DynamoDb_Error$ReventlessAws.message(err)), () => 0)));
191
191
  if (restored > 0) {
192
- return Effect.runSync(EffectLogger$ReventlessCore.logInfo(comp, undefined, `restore: reloaded ` + restored.toString() + ` unfinished TODO row(s) from ` + queryDbTableName));
192
+ return Effect.runSync(EffectLogger$ReventlessCore.logInfo(comp, undefined, undefined, `restore: reloaded ` + restored.toString() + ` unfinished TODO row(s) from ` + queryDbTableName));
193
193
  }
194
194
  };
195
195
  }
@@ -237,7 +237,7 @@ function makeScheduleStore(tableName, rows, comp) {
237
237
  return;
238
238
  }
239
239
  });
240
- }), err => EffectLogger$ReventlessCore.logError(comp, undefined, `restore: couldn't read the schedules from ` + tableName + `: ` + DynamoDb_Error$ReventlessAws.message(err))));
240
+ }), err => EffectLogger$ReventlessCore.logError(comp, undefined, undefined, `restore: couldn't read the schedules from ` + tableName + `: ` + DynamoDb_Error$ReventlessAws.message(err))));
241
241
  stored.contents = Object.keys(rows);
242
242
  };
243
243
  let sync = async () => {
@@ -440,7 +440,7 @@ async function runSweeps(slices) {
440
440
  } catch (raw_exn) {
441
441
  let exn = Primitive_exceptions.internalToException(raw_exn);
442
442
  let msg = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(exn), Stdlib_JsExn.message), "unknown");
443
- Effect.runSync(EffectLogger$ReventlessCore.logError(slice.comp, undefined, `sweep failed: ` + msg));
443
+ Effect.runSync(EffectLogger$ReventlessCore.logError(slice.comp, undefined, undefined, `sweep failed: ` + msg));
444
444
  }
445
445
  }
446
446
  }
@@ -465,7 +465,7 @@ async function reconcileSchedules(slices) {
465
465
  for (let i = 0, i_finish = reconciles.length; i < i_finish; ++i) {
466
466
  await reconciles[i]();
467
467
  }
468
- return Effect.runSync(EffectLogger$ReventlessCore.logInfo("AutomationSliceRuntime", undefined, `reconcile: the schedules of ` + reconciles.length.toString() + ` automation(s) are in line`));
468
+ return Effect.runSync(EffectLogger$ReventlessCore.logInfo("AutomationSliceRuntime", undefined, undefined, `reconcile: the schedules of ` + reconciles.length.toString() + ` automation(s) are in line`));
469
469
  }
470
470
 
471
471
  export {
@@ -45,7 +45,7 @@ function deriveScope(specs) {
45
45
  let err = Primitive_exceptions.internalToException(raw_err);
46
46
  if (err.RE_EXN_ID === "JsExn") {
47
47
  let err$1 = err._1;
48
- Effect.runSync(EffectLogger$ReventlessCore.logError("DcbCommandTopicRuntime", undefined, `refusing to start: ` + Stdlib_Option.getOr(Stdlib_JsExn.message(err$1), "unknown error")));
48
+ Effect.runSync(EffectLogger$ReventlessCore.logError("DcbCommandTopicRuntime", undefined, undefined, `refusing to start: ` + Stdlib_Option.getOr(Stdlib_JsExn.message(err$1), "unknown error")));
49
49
  throw err$1;
50
50
  }
51
51
  throw err;
@@ -135,12 +135,12 @@ async function persistAudit(callback, auditQueryDbOps, result) {
135
135
  if (err.TAG === "Ok") {
136
136
  return;
137
137
  } else {
138
- return Effect.runSync(EffectLogger$ReventlessCore.logError("InboundTranslationSlice.audit", undefined, `failed to persist audit row ` + id + `: ` + QueryDb$ReventlessCore.storageErrorToString(err._0)));
138
+ return Effect.runSync(EffectLogger$ReventlessCore.logError("InboundTranslationSlice.audit", undefined, undefined, `failed to persist audit row ` + id + `: ` + QueryDb$ReventlessCore.storageErrorToString(err._0)));
139
139
  }
140
140
  } catch (raw_exn) {
141
141
  let exn = Primitive_exceptions.internalToException(raw_exn);
142
142
  let detail = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(exn), Stdlib_JsExn.message), "unknown error");
143
- return Effect.runSync(EffectLogger$ReventlessCore.logError("InboundTranslationSlice.audit", undefined, `failed to persist audit row ` + id + `: ` + detail));
143
+ return Effect.runSync(EffectLogger$ReventlessCore.logError("InboundTranslationSlice.audit", undefined, undefined, `failed to persist audit row ` + id + `: ` + detail));
144
144
  }
145
145
  }
146
146
 
@@ -711,8 +711,8 @@ let makeSqsHandlerBundle = (input: bundleInput): bundle => {
711
711
  ),
712
712
  // Backs both the admin and every per-plugin EventCollector Lambda, so the
713
713
  // comp names the plugin whose events it drains — matching the
714
- // `Plugin(<id>)` shape Plugin_Callback logs under.
715
- comp: `Plugin(${input.pluginDefinition.id})`,
714
+ // `ExtensionRouting(<id>)` shape Plugin_Callback logs under.
715
+ comp: `ExtensionRouting(${input.pluginDefinition.id})`,
716
716
  }
717
717
  }
718
718
 
@@ -531,7 +531,7 @@ function makeSqsHandlerBundle(input) {
531
531
  };
532
532
  return {
533
533
  sqsHandler: EventCollectorChannel_SQS_Runtime$ReventlessAws.handleDynamoDbOrSqsEvent(queue, Callback.handleJsonEvents),
534
- comp: `Plugin(` + input.pluginDefinition.id + `)`
534
+ comp: `ExtensionRouting(` + input.pluginDefinition.id + `)`
535
535
  };
536
536
  }
537
537
 
@@ -124,6 +124,23 @@ let withDisplayName = (
124
124
  }
125
125
  }
126
126
 
127
+ /**
128
+ Stamps every saved row with the change being written (`_change`: flow, event, time), as
129
+ `QueryDb_Operations.Make` does on the typed path. Outermost, so the live update publishes
130
+ the stamped row.
131
+ */
132
+ let withRowChange = (
133
+ base: ReventlessCore.QueryDb_Adapter.operations,
134
+ ): ReventlessCore.QueryDb_Adapter.operations => {
135
+ ...base,
136
+ save: (id, state, saveMode, ttl) =>
137
+ base.save(id, ReventlessCore.RowChange.stamp(state), saveMode, ttl),
138
+ saveBatch: items =>
139
+ base.saveBatch(
140
+ items->Array.map(((id, state, ttl)) => (id, ReventlessCore.RowChange.stamp(state), ttl)),
141
+ ),
142
+ }
143
+
127
144
  let makeQueryDbOps = (
128
145
  ~queryDbTableName: string,
129
146
  ~pgConnection: option<PgConnection.connectionConfig>,
@@ -145,4 +162,4 @@ let makeQueryDbOps = (
145
162
  ?subIdField,
146
163
  })
147
164
  | None => QueryDbEntryPoint_Ops.makeDynamoQueryDbOps(~tableName=queryDbTableName)
148
- }
165
+ }->withRowChange