@reventlessdev/reventless-local 3.0.0-alpha.117 → 3.0.0-alpha.118

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 (66) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +7 -6
  3. package/rescript.json +2 -1
  4. package/src/Platform.res +44 -6
  5. package/src/Platform.res.mjs +53 -16
  6. package/src/adapter/Backend.res +23 -0
  7. package/src/adapter/Backend.res.mjs +23 -0
  8. package/src/adapter/BackendState.res +12 -7
  9. package/src/adapter/BackendState.res.mjs +18 -6
  10. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res +3 -22
  11. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res.mjs +1 -22
  12. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res +13 -10
  13. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res.mjs +22 -8
  14. package/src/adapter/DcbEventLog/LocalDcbEventLogStorage.res +52 -0
  15. package/src/adapter/DcbEventLog/LocalDcbEventLogStorage.res.mjs +35 -0
  16. package/src/adapter/EventLog/EventLogStorage_InMemory.res +3 -15
  17. package/src/adapter/EventLog/EventLogStorage_InMemory.res.mjs +0 -21
  18. package/src/adapter/EventLog/LocalEventLogStorage.res +33 -0
  19. package/src/adapter/EventLog/LocalEventLogStorage.res.mjs +35 -0
  20. package/src/adapter/LocalBus.res +1 -1
  21. package/src/adapter/PgProjectionCatchup.res +146 -0
  22. package/src/adapter/PgProjectionCatchup.res.mjs +114 -0
  23. package/src/adapter/QueryDb/LocalQueryDbStorage.res +43 -0
  24. package/src/adapter/QueryDb/LocalQueryDbStorage.res.mjs +42 -0
  25. package/src/adapter/QueryDb/QueryDbStorage_InMemory.res +3 -24
  26. package/src/adapter/QueryDb/QueryDbStorage_InMemory.res.mjs +1 -28
  27. package/src/adapter/Task/LocalTaskBucket.res +1 -1
  28. package/src/adapter/Task/LocalTaskBucket.res.mjs +1 -1
  29. package/src/components/Aggregate_Builder.res +1 -1
  30. package/src/components/Aggregate_Builder.res.mjs +3 -3
  31. package/src/components/AutomationSlice_Builder.res +1 -1
  32. package/src/components/AutomationSlice_Builder.res.mjs +3 -3
  33. package/src/components/Counter_Builder.res +1 -1
  34. package/src/components/Counter_Builder.res.mjs +2 -2
  35. package/src/components/DcbEventLog_Builder.res +1 -1
  36. package/src/components/DcbEventLog_Builder.res.mjs +2 -2
  37. package/src/components/InboundTranslationSlice_Builder.res +1 -1
  38. package/src/components/InboundTranslationSlice_Builder.res.mjs +2 -2
  39. package/src/components/OutboundTranslationSlice_Builder.res +1 -1
  40. package/src/components/OutboundTranslationSlice_Builder.res.mjs +2 -2
  41. package/src/components/Plugin_Builder.res +1 -1
  42. package/src/components/Plugin_Builder.res.mjs +2 -2
  43. package/src/components/ReadModel_Builder.res +1 -1
  44. package/src/components/ReadModel_Builder.res.mjs +2 -2
  45. package/src/components/StateViewSlice_Builder.res +1 -1
  46. package/src/components/StateViewSlice_Builder.res.mjs +2 -2
  47. package/src/test/Mocks/MockDcbEventLogStorage.res +2 -2
  48. package/src/test/Mocks/MockDcbEventLogStorage.res.mjs +5 -2
  49. package/tests/adapter/BackendParityTest.res +43 -8
  50. package/tests/adapter/BackendParityTest.res.mjs +39 -9
  51. package/tests/adapter/DcbEventLogStorageSqliteTest.res +17 -9
  52. package/tests/adapter/DcbEventLogStorageSqliteTest.res.mjs +19 -10
  53. package/tests/adapter/PgProjectionCatchupTest.res +149 -0
  54. package/tests/adapter/PgProjectionCatchupTest.res.mjs +181 -0
  55. package/tests/adapter/QueryDbGsiTtlTest.res +2 -2
  56. package/tests/adapter/QueryDbGsiTtlTest.res.mjs +3 -2
  57. package/tests/adapter/QueryDbListResolverTest.res +1 -1
  58. package/tests/adapter/QueryDbListResolverTest.res.mjs +2 -2
  59. package/tests/adapter/QueryDbStorageTest.res +10 -10
  60. package/tests/adapter/QueryDbStorageTest.res.mjs +11 -11
  61. package/tests/adapter/QueryEngineTest.res +8 -8
  62. package/tests/adapter/QueryEngineTest.res.mjs +9 -9
  63. package/tests/components/querydb/QueryDbFixtures.res +1 -1
  64. package/tests/components/querydb/QueryDbFixtures.res.mjs +2 -2
  65. package/tests/components/querydb/QueryDbSubIdFixtures.res +1 -1
  66. package/tests/components/querydb/QueryDbSubIdFixtures.res.mjs +2 -2
@@ -5,11 +5,8 @@ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
5
5
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
6
  import * as Stream from "effect/Stream";
7
7
  import * as Pulumi from "@pulumi/pulumi";
8
- import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
8
  import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
10
9
  import * as LocalBus$ReventlessLocal from "../LocalBus.res.mjs";
11
- import * as BackendState$ReventlessLocal from "../BackendState.res.mjs";
12
- import * as QueryDbStorage_Sqlite$ReventlessLocal from "./QueryDbStorage_Sqlite.res.mjs";
13
10
 
14
11
  function getSubKey(item, subIdField) {
15
12
  if (subIdField === undefined) {
@@ -56,21 +53,7 @@ function flattenStore(store) {
56
53
  }
57
54
 
58
55
  function Make(Bus) {
59
- let sqliteBusCallbacks_publishStateChange = Bus.publishStateChange;
60
- let sqliteBusCallbacks_registerQueryDb = Bus.registerQueryDb;
61
- let sqliteBusCallbacks_registerQueryDbScan = Bus.registerQueryDbScan;
62
- let sqliteBusCallbacks_registerQueryDbStream = Bus.registerQueryDbStream;
63
- let sqliteBusCallbacks_registerQueryDbIndexLookup = Bus.registerQueryDbIndexLookup;
64
- let sqliteBusCallbacks_registerQueryDbListPage = Bus.registerQueryDbListPage;
65
- let sqliteBusCallbacks = {
66
- publishStateChange: sqliteBusCallbacks_publishStateChange,
67
- registerQueryDb: sqliteBusCallbacks_registerQueryDb,
68
- registerQueryDbScan: sqliteBusCallbacks_registerQueryDbScan,
69
- registerQueryDbStream: sqliteBusCallbacks_registerQueryDbStream,
70
- registerQueryDbIndexLookup: sqliteBusCallbacks_registerQueryDbIndexLookup,
71
- registerQueryDbListPage: sqliteBusCallbacks_registerQueryDbListPage
72
- };
73
- let makeMemory = (name, param, subIdField, param$1, param$2, param$3, param$4) => {
56
+ let make = (name, param, subIdField, param$1, param$2, param$3, param$4) => {
74
57
  let store = {
75
58
  contents: {}
76
59
  };
@@ -317,17 +300,7 @@ function Make(Bus) {
317
300
  operations: Pulumi.output(ops)
318
301
  };
319
302
  };
320
- let make = (name, indexes, subIdField, ttl, api, apiRole, opts) => {
321
- let db = BackendState$ReventlessLocal.getDb();
322
- if (db !== undefined) {
323
- return QueryDbStorage_Sqlite$ReventlessLocal.makeStorage(Primitive_option.valFromOption(db), sqliteBusCallbacks, name, indexes, subIdField);
324
- } else {
325
- return makeMemory(name, indexes, subIdField, ttl, api, apiRole, opts);
326
- }
327
- };
328
303
  return {
329
- sqliteBusCallbacks: sqliteBusCallbacks,
330
- makeMemory: makeMemory,
331
304
  make: make
332
305
  };
333
306
  }
@@ -56,7 +56,7 @@ let makeHandler = (callback: Task.bucketCallback): Runtime.eventHandler<
56
56
  let make: Task_Adapter.bucketMaker<bucketParts> = (~name, ~opts as _) => {
57
57
  // When SQLite is the active backend, eagerly provision the task_object
58
58
  // table so put/get helpers can be used outside the bucketMaker contract.
59
- switch BackendState.getDb() {
59
+ switch BackendState.getSqliteDb() {
60
60
  | Some(db) => TaskBucket_Sqlite.ensureSchema(db)
61
61
  | None => ()
62
62
  }
@@ -30,7 +30,7 @@ function makeHandler(callback) {
30
30
  }
31
31
 
32
32
  function make(name, param) {
33
- let db = BackendState$ReventlessLocal.getDb();
33
+ let db = BackendState$ReventlessLocal.getSqliteDb();
34
34
  if (db !== undefined) {
35
35
  TaskBucket_Sqlite$ReventlessLocal.ensureSchema(Primitive_option.valFromOption(db));
36
36
  }
@@ -37,7 +37,7 @@ module MakeWithHooks = (
37
37
  RuntimeEnvironment,
38
38
  CommandGeneratorResolvers_GraphQL,
39
39
  CommandTopicChannel,
40
- EventLogStorage_InMemory.Make(Bus),
40
+ LocalEventLogStorage.Make(Bus),
41
41
  EventTopicPublisher,
42
42
  EventCollectorChannel,
43
43
  AggregateRuntimeBuilder,
@@ -2,8 +2,8 @@
2
2
 
3
3
  import * as Pulumi from "@pulumi/pulumi";
4
4
  import * as Aggregate_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/Aggregate/Aggregate_Builder.res.mjs";
5
+ import * as LocalEventLogStorage$ReventlessLocal from "../adapter/EventLog/LocalEventLogStorage.res.mjs";
5
6
  import * as LocalRuntimeEnvironment$ReventlessLocal from "../adapter/Runtime/LocalRuntimeEnvironment.res.mjs";
6
- import * as EventLogStorage_InMemory$ReventlessLocal from "../adapter/EventLog/EventLogStorage_InMemory.res.mjs";
7
7
  import * as LocalCommandTopicChannel$ReventlessLocal from "../adapter/CommandTopic/LocalCommandTopicChannel.res.mjs";
8
8
  import * as LocalEventTopicPublisher$ReventlessLocal from "../adapter/EventTopic/LocalEventTopicPublisher.res.mjs";
9
9
  import * as LocalEventCollectorChannel$ReventlessLocal from "../adapter/EventCollector/LocalEventCollectorChannel.res.mjs";
@@ -66,7 +66,7 @@ function MakeWithHooks(Bus) {
66
66
  make: CommandGeneratorResolvers_GraphQL$ReventlessLocal.make
67
67
  })({
68
68
  make: CommandTopicChannel.make
69
- })(EventLogStorage_InMemory$ReventlessLocal.Make(Bus))(EventTopicPublisher)(EventCollectorChannel)(AggregateRuntimeBuilder)(HooksConfig);
69
+ })(LocalEventLogStorage$ReventlessLocal.Make(Bus))(EventTopicPublisher)(EventCollectorChannel)(AggregateRuntimeBuilder)(HooksConfig);
70
70
  return {
71
71
  Spec: include.Spec,
72
72
  AggregateRuntimeBuilder: include.AggregateRuntimeBuilder,
@@ -112,7 +112,7 @@ function Make(Bus) {
112
112
  make: CommandGeneratorResolvers_GraphQL$ReventlessLocal.make
113
113
  })({
114
114
  make: CommandTopicChannel.make
115
- })(EventLogStorage_InMemory$ReventlessLocal.Make(Bus))(EventTopicPublisher)(EventCollectorChannel)(AggregateRuntimeBuilder)(HooksConfig);
115
+ })(LocalEventLogStorage$ReventlessLocal.Make(Bus))(EventTopicPublisher)(EventCollectorChannel)(AggregateRuntimeBuilder)(HooksConfig);
116
116
  return {
117
117
  Spec: include.Spec,
118
118
  AggregateRuntimeBuilder: include.AggregateRuntimeBuilder,
@@ -8,7 +8,7 @@ module Make = (Bus: LocalBus.T) => {
8
8
  Bus,
9
9
  EventCollectorChannel,
10
10
  )
11
- module QueryDbStorage = QueryDbStorage_InMemory.Make(Bus)
11
+ module QueryDbStorage = LocalQueryDbStorage.Make(Bus)
12
12
  module QueryDbResolvers = QueryDbResolvers_GraphQL.Make(Bus)
13
13
 
14
14
  // InMemory api/apiRole are both unit
@@ -1,8 +1,8 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as LocalQueryDbStorage$ReventlessLocal from "../adapter/QueryDb/LocalQueryDbStorage.res.mjs";
3
4
  import * as AutomationSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/AutomationSlice/AutomationSlice_Builder.res.mjs";
4
5
  import * as LocalRuntimeEnvironment$ReventlessLocal from "../adapter/Runtime/LocalRuntimeEnvironment.res.mjs";
5
- import * as QueryDbStorage_InMemory$ReventlessLocal from "../adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
6
6
  import * as QueryDbResolvers_GraphQL$ReventlessLocal from "../adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs";
7
7
  import * as LocalEventCollectorChannel$ReventlessLocal from "../adapter/EventCollector/LocalEventCollectorChannel.res.mjs";
8
8
  import * as LocalEventCollectorRuntime_Builder$ReventlessLocal from "../adapter/Runtime/LocalEventCollectorRuntime_Builder.res.mjs";
@@ -10,7 +10,7 @@ import * as LocalEventCollectorRuntime_Builder$ReventlessLocal from "../adapter/
10
10
  function Make(Bus) {
11
11
  let EventCollectorChannel = LocalEventCollectorChannel$ReventlessLocal.Make(Bus);
12
12
  let EventCollectorRuntimeBuilder = LocalEventCollectorRuntime_Builder$ReventlessLocal.Make(Bus)(EventCollectorChannel);
13
- let QueryDbStorage = QueryDbStorage_InMemory$ReventlessLocal.Make(Bus);
13
+ let QueryDbStorage = LocalQueryDbStorage$ReventlessLocal.Make(Bus);
14
14
  let QueryDbResolvers = QueryDbResolvers_GraphQL$ReventlessLocal.Make(Bus);
15
15
  let api = () => {};
16
16
  let apiRole = () => {};
@@ -54,4 +54,4 @@ function Make(Bus) {
54
54
  export {
55
55
  Make,
56
56
  }
57
- /* AutomationSlice_Builder-ReventlessCore Not a pure module */
57
+ /* LocalQueryDbStorage-ReventlessLocal Not a pure module */
@@ -1,7 +1,7 @@
1
1
  // In-memory Counter builder.
2
2
 
3
3
  module Make = (Bus: LocalBus.T) => {
4
- module QueryDbStorage = QueryDbStorage_InMemory.Make(Bus)
4
+ module QueryDbStorage = LocalQueryDbStorage.Make(Bus)
5
5
  module Api = {
6
6
  let api = () => ()
7
7
  let apiRole = () => ()
@@ -2,10 +2,10 @@
2
2
 
3
3
  import * as Counter_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/Counter/Counter_Builder.res.mjs";
4
4
  import * as LocalCounterHandler$ReventlessLocal from "../adapter/Counter/LocalCounterHandler.res.mjs";
5
- import * as QueryDbStorage_InMemory$ReventlessLocal from "../adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
5
+ import * as LocalQueryDbStorage$ReventlessLocal from "../adapter/QueryDb/LocalQueryDbStorage.res.mjs";
6
6
 
7
7
  function Make(Bus) {
8
- let QueryDbStorage = QueryDbStorage_InMemory$ReventlessLocal.Make(Bus);
8
+ let QueryDbStorage = LocalQueryDbStorage$ReventlessLocal.Make(Bus);
9
9
  let api = () => {};
10
10
  let apiRole = () => {};
11
11
  let Api = {
@@ -8,7 +8,7 @@ module Make = (Bus: LocalBus.T) => {
8
8
  // REVENTLESS_LOCAL_BACKEND=sqlite, and it registers the read with the Bus so
9
9
  // `Bus.getDcbEventLogRead` can see it. The plain module did neither — the log
10
10
  // silently stayed in memory under SQLite and was invisible to bus readers.
11
- module Storage = DcbEventLogStorage_InMemory.Make(Bus)
11
+ module Storage = LocalDcbEventLogStorage.Make(Bus)
12
12
  module Inner = ReventlessCore.DcbEventLog_Builder.Make(Storage, EventTopicPublisher)
13
13
  type component = ReventlessInfra.DcbEventLog.component
14
14
  let make: (
@@ -2,12 +2,12 @@
2
2
 
3
3
  import * as Component$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Component.res.mjs";
4
4
  import * as DcbEventLog_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/DcbEventLog/DcbEventLog_Builder.res.mjs";
5
+ import * as LocalDcbEventLogStorage$ReventlessLocal from "../adapter/DcbEventLog/LocalDcbEventLogStorage.res.mjs";
5
6
  import * as LocalEventTopicPublisher$ReventlessLocal from "../adapter/EventTopic/LocalEventTopicPublisher.res.mjs";
6
- import * as DcbEventLogStorage_InMemory$ReventlessLocal from "../adapter/DcbEventLog/DcbEventLogStorage_InMemory.res.mjs";
7
7
 
8
8
  function Make(Bus) {
9
9
  let EventTopicPublisher = LocalEventTopicPublisher$ReventlessLocal.Make(Bus);
10
- let Storage = DcbEventLogStorage_InMemory$ReventlessLocal.Make(Bus);
10
+ let Storage = LocalDcbEventLogStorage$ReventlessLocal.Make(Bus);
11
11
  let Inner = DcbEventLog_Builder$ReventlessCore.Make(Storage)(EventTopicPublisher);
12
12
  return {
13
13
  EventTopicPublisher: EventTopicPublisher,
@@ -2,7 +2,7 @@
2
2
  // Wires in-memory adapters and delegates to the core ReventlessCore.InboundTranslationSlice_Builder.
3
3
 
4
4
  module Make = (Bus: LocalBus.T) => {
5
- module QueryDbStorage = QueryDbStorage_InMemory.Make(Bus)
5
+ module QueryDbStorage = LocalQueryDbStorage.Make(Bus)
6
6
  module QueryDbResolvers = QueryDbResolvers_GraphQL.Make(Bus)
7
7
 
8
8
  // InMemory api/apiRole are both unit
@@ -1,12 +1,12 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
4
- import * as QueryDbStorage_InMemory$ReventlessLocal from "../adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
4
+ import * as LocalQueryDbStorage$ReventlessLocal from "../adapter/QueryDb/LocalQueryDbStorage.res.mjs";
5
5
  import * as QueryDbResolvers_GraphQL$ReventlessLocal from "../adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs";
6
6
  import * as InboundTranslationSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs";
7
7
 
8
8
  function Make(Bus) {
9
- let QueryDbStorage = QueryDbStorage_InMemory$ReventlessLocal.Make(Bus);
9
+ let QueryDbStorage = LocalQueryDbStorage$ReventlessLocal.Make(Bus);
10
10
  let QueryDbResolvers = QueryDbResolvers_GraphQL$ReventlessLocal.Make(Bus);
11
11
  let api = () => {};
12
12
  let apiRole = () => {};
@@ -8,7 +8,7 @@ module Make = (Bus: LocalBus.T) => {
8
8
  Bus,
9
9
  EventCollectorChannel,
10
10
  )
11
- module QueryDbStorage = QueryDbStorage_InMemory.Make(Bus)
11
+ module QueryDbStorage = LocalQueryDbStorage.Make(Bus)
12
12
  module QueryDbResolvers = QueryDbResolvers_GraphQL.Make(Bus)
13
13
 
14
14
  // InMemory api/apiRole are both unit
@@ -1,8 +1,8 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
4
+ import * as LocalQueryDbStorage$ReventlessLocal from "../adapter/QueryDb/LocalQueryDbStorage.res.mjs";
4
5
  import * as LocalRuntimeEnvironment$ReventlessLocal from "../adapter/Runtime/LocalRuntimeEnvironment.res.mjs";
5
- import * as QueryDbStorage_InMemory$ReventlessLocal from "../adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
6
6
  import * as QueryDbResolvers_GraphQL$ReventlessLocal from "../adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs";
7
7
  import * as LocalEventCollectorChannel$ReventlessLocal from "../adapter/EventCollector/LocalEventCollectorChannel.res.mjs";
8
8
  import * as OutboundTranslationSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs";
@@ -11,7 +11,7 @@ import * as LocalEventCollectorRuntime_Builder$ReventlessLocal from "../adapter/
11
11
  function Make(Bus) {
12
12
  let EventCollectorChannel = LocalEventCollectorChannel$ReventlessLocal.Make(Bus);
13
13
  let EventCollectorRuntimeBuilder = LocalEventCollectorRuntime_Builder$ReventlessLocal.Make(Bus)(EventCollectorChannel);
14
- let QueryDbStorage = QueryDbStorage_InMemory$ReventlessLocal.Make(Bus);
14
+ let QueryDbStorage = LocalQueryDbStorage$ReventlessLocal.Make(Bus);
15
15
  let QueryDbResolvers = QueryDbResolvers_GraphQL$ReventlessLocal.Make(Bus);
16
16
  let api = () => {};
17
17
  let apiRole = () => {};
@@ -29,7 +29,7 @@ module Make = (Bus: LocalBus.T, HooksConfig: ReventlessCore.Plugin_Helpers.Hooks
29
29
  RemoteChannel,
30
30
  LocalHeartbeatRunner,
31
31
  PluginRuntimeBuilder,
32
- DcbEventLogStorage_InMemory.Make(Bus),
32
+ LocalDcbEventLogStorage.Make(Bus),
33
33
  LocalEventTopicPublisher.Make(Bus),
34
34
  LocalCommandTopicChannel.Make(Bus),
35
35
  LocalCommandTopicChannel.Make(Bus),
@@ -5,12 +5,12 @@ import * as LocalPluginSpec$ReventlessLocal from "../adapter/LocalPluginSpec.res
5
5
  import * as LocalQueryEngine$ReventlessLocal from "../adapter/QueryEngine/LocalQueryEngine.res.mjs";
6
6
  import * as LocalGraphQL_Adapter$ReventlessLocal from "../adapter/Api/LocalGraphQL_Adapter.res.mjs";
7
7
  import * as LocalHeartbeatRunner$ReventlessLocal from "../adapter/Heartbeat/LocalHeartbeatRunner.res.mjs";
8
+ import * as LocalDcbEventLogStorage$ReventlessLocal from "../adapter/DcbEventLog/LocalDcbEventLogStorage.res.mjs";
8
9
  import * as LocalRuntimeEnvironment$ReventlessLocal from "../adapter/Runtime/LocalRuntimeEnvironment.res.mjs";
9
10
  import * as LocalCommandTopicChannel$ReventlessLocal from "../adapter/CommandTopic/LocalCommandTopicChannel.res.mjs";
10
11
  import * as LocalEventTopicPublisher$ReventlessLocal from "../adapter/EventTopic/LocalEventTopicPublisher.res.mjs";
11
12
  import * as LocalEventCollectorChannel$ReventlessLocal from "../adapter/EventCollector/LocalEventCollectorChannel.res.mjs";
12
13
  import * as LocalPluginRuntime_Builder$ReventlessLocal from "../adapter/Runtime/LocalPluginRuntime_Builder.res.mjs";
13
- import * as DcbEventLogStorage_InMemory$ReventlessLocal from "../adapter/DcbEventLog/DcbEventLogStorage_InMemory.res.mjs";
14
14
  import * as LocalCommandTopicRemoteChannel$ReventlessLocal from "../adapter/CommandTopic/LocalCommandTopicRemoteChannel.res.mjs";
15
15
 
16
16
  function Make(Bus) {
@@ -44,7 +44,7 @@ function Make(Bus) {
44
44
  forPluginHeartbeat: PluginRuntimeBuilder.forPluginHeartbeat,
45
45
  forDcbCommandTopic: PluginRuntimeBuilder.forDcbCommandTopic,
46
46
  finish: PluginRuntimeBuilder.finish
47
- })(DcbEventLogStorage_InMemory$ReventlessLocal.Make(Bus))(LocalEventTopicPublisher$ReventlessLocal.Make(Bus))({
47
+ })(LocalDcbEventLogStorage$ReventlessLocal.Make(Bus))(LocalEventTopicPublisher$ReventlessLocal.Make(Bus))({
48
48
  make: $$let.make
49
49
  })({
50
50
  make: $$let$1.make
@@ -9,7 +9,7 @@ module Make = (Bus: LocalBus.T) => {
9
9
  Bus,
10
10
  EventCollectorChannel,
11
11
  )
12
- module QueryDbStorage = QueryDbStorage_InMemory.Make(Bus)
12
+ module QueryDbStorage = LocalQueryDbStorage.Make(Bus)
13
13
  module QueryDbResolvers = QueryDbResolvers_GraphQL.Make(Bus)
14
14
 
15
15
  module Make = (
@@ -2,8 +2,8 @@
2
2
 
3
3
  import * as QueryDb_Adapter$ReventlessCore from "@reventlessdev/reventless-core/src/components/QueryDb/QueryDb_Adapter.res.mjs";
4
4
  import * as ReadModel_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/ReadModel/ReadModel_Builder.res.mjs";
5
+ import * as LocalQueryDbStorage$ReventlessLocal from "../adapter/QueryDb/LocalQueryDbStorage.res.mjs";
5
6
  import * as LocalRuntimeEnvironment$ReventlessLocal from "../adapter/Runtime/LocalRuntimeEnvironment.res.mjs";
6
- import * as QueryDbStorage_InMemory$ReventlessLocal from "../adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
7
7
  import * as QueryDbResolvers_GraphQL$ReventlessLocal from "../adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs";
8
8
  import * as LocalEventCollectorChannel$ReventlessLocal from "../adapter/EventCollector/LocalEventCollectorChannel.res.mjs";
9
9
  import * as LocalEventCollectorRuntime_Builder$ReventlessLocal from "../adapter/Runtime/LocalEventCollectorRuntime_Builder.res.mjs";
@@ -14,7 +14,7 @@ function Make(Bus) {
14
14
  make: EventCollectorChannel.make,
15
15
  connect: EventCollectorChannel.connect
16
16
  });
17
- let QueryDbStorage = QueryDbStorage_InMemory$ReventlessLocal.Make(Bus);
17
+ let QueryDbStorage = LocalQueryDbStorage$ReventlessLocal.Make(Bus);
18
18
  let QueryDbResolvers = QueryDbResolvers_GraphQL$ReventlessLocal.Make(Bus);
19
19
  let Make$1 = Spec => (Mappings => ReadModel_Builder$ReventlessCore.Make(Spec)(Mappings)({
20
20
  make: LocalRuntimeEnvironment$ReventlessLocal.make,
@@ -11,7 +11,7 @@ module Make = (Bus: LocalBus.T) => {
11
11
  Bus,
12
12
  EventCollectorChannel,
13
13
  )
14
- module QueryDbStorage = QueryDbStorage_InMemory.Make(Bus)
14
+ module QueryDbStorage = LocalQueryDbStorage.Make(Bus)
15
15
  module QueryDbResolvers = QueryDbResolvers_GraphQL.Make(Bus)
16
16
 
17
17
  // InMemory api/apiRole are both unit
@@ -1,9 +1,9 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
4
+ import * as LocalQueryDbStorage$ReventlessLocal from "../adapter/QueryDb/LocalQueryDbStorage.res.mjs";
4
5
  import * as StateViewSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs";
5
6
  import * as LocalRuntimeEnvironment$ReventlessLocal from "../adapter/Runtime/LocalRuntimeEnvironment.res.mjs";
6
- import * as QueryDbStorage_InMemory$ReventlessLocal from "../adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
7
7
  import * as QueryDbResolvers_GraphQL$ReventlessLocal from "../adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs";
8
8
  import * as LocalEventCollectorChannel$ReventlessLocal from "../adapter/EventCollector/LocalEventCollectorChannel.res.mjs";
9
9
  import * as LocalEventCollectorRuntime_Builder$ReventlessLocal from "../adapter/Runtime/LocalEventCollectorRuntime_Builder.res.mjs";
@@ -14,7 +14,7 @@ function Make(Bus) {
14
14
  make: EventCollectorChannel.make,
15
15
  connect: EventCollectorChannel.connect
16
16
  });
17
- let QueryDbStorage = QueryDbStorage_InMemory$ReventlessLocal.Make(Bus);
17
+ let QueryDbStorage = LocalQueryDbStorage$ReventlessLocal.Make(Bus);
18
18
  let QueryDbResolvers = QueryDbResolvers_GraphQL$ReventlessLocal.Make(Bus);
19
19
  let api = () => {};
20
20
  let apiRole = () => {};
@@ -69,7 +69,7 @@ let make = (~name="mock-dcb-log", ~indexes: array<string>=[], ~opts: Pulumi.Cust
69
69
  let append = async (newEvents, ~condition=?) => {
70
70
  if failNextAppends.contents > 0 {
71
71
  failNextAppends := failNextAppends.contents - 1
72
- Error("mock append failure")
72
+ Error(ReventlessInfra.DcbEventLog.StorageFailure("mock append failure"))
73
73
  } else {
74
74
  let conflictDetected = switch condition {
75
75
  | Some(cond: Reventless.DcbTag.appendCondition) =>
@@ -83,7 +83,7 @@ let make = (~name="mock-dcb-log", ~indexes: array<string>=[], ~opts: Pulumi.Cust
83
83
  | None => false
84
84
  }
85
85
  if conflictDetected {
86
- Error("conflict: condition check failed")
86
+ Error(ReventlessInfra.DcbEventLog.Conflict)
87
87
  } else {
88
88
  let storedEvents = newEvents->Array.map((event: DcbEventLog_Adapter.rawStoredEvent) => {
89
89
  position := position.contents + 1
@@ -68,7 +68,10 @@ function make(nameOpt, indexesOpt, optsOpt) {
68
68
  failNextAppends.contents = failNextAppends.contents - 1 | 0;
69
69
  return {
70
70
  TAG: "Error",
71
- _0: "mock append failure"
71
+ _0: {
72
+ TAG: "StorageFailure",
73
+ _0: "mock append failure"
74
+ }
72
75
  };
73
76
  }
74
77
  let conflictDetected = condition !== undefined ? events.contents.some(event => {
@@ -83,7 +86,7 @@ function make(nameOpt, indexesOpt, optsOpt) {
83
86
  if (conflictDetected) {
84
87
  return {
85
88
  TAG: "Error",
86
- _0: "conflict: condition check failed"
89
+ _0: "Conflict"
87
90
  };
88
91
  }
89
92
  let storedEvents = newEvents.map(event => {
@@ -1,11 +1,32 @@
1
- // Behavioural parity between Memory and Sqlite backends at the adapter layer.
2
- // Each test runs the same scenario against both BackendState settings.
1
+ // Behavioural parity between Memory, Sqlite, and Postgres backends at the adapter
2
+ // layer. Each test runs the same scenario against every BackendState setting.
3
+ //
4
+ // The Postgres arm is exercised only when PG_URL is set (so the default test run
5
+ // stays dependency-free), and only for EventLog scenarios: under Backend.Postgres
6
+ // the read-model (QueryDb) path routes to the in-memory arm by design (the sync
7
+ // LocalBus registrations can't consume async pg — see LocalQueryDbStorage), so a
8
+ // QueryDb "runUnderPostgres" would just re-test Memory. Event logs, however, are
9
+ // genuinely Postgres-backed and must match Memory/Sqlite exactly.
3
10
 
4
11
  open JestGlobals
5
12
 
13
+ @val external processEnv: dict<string> = "process.env"
14
+
6
15
  let _ = TestRunner.setup()
7
16
  let opts: Pulumi.CustomResourceOptions.t = {}
8
17
 
18
+ let pgPool =
19
+ processEnv
20
+ ->Dict.get("PG_URL")
21
+ ->Option.map(url => ReventlessPostgres.PgDriver.makePool({connectionString: url}))
22
+
23
+ afterAll(() =>
24
+ switch pgPool {
25
+ | Some(pool) => ignore(pool->ReventlessPostgres.PgDriver.endPool)
26
+ | None => ()
27
+ }
28
+ )
29
+
9
30
  let runUnderMemory = async fn => {
10
31
  BackendState.setMemory()
11
32
  await fn()
@@ -19,11 +40,23 @@ let runUnderSqlite = async fn => {
19
40
  db->SqliteDriver.close
20
41
  }
21
42
 
43
+ // No-op when PG_URL is unset. Resets the schema before each scenario for isolation.
44
+ let runUnderPostgres = async fn =>
45
+ switch pgPool {
46
+ | Some(pool) =>
47
+ await ReventlessPostgres.PgSchema.ensureSchema(pool)
48
+ await ReventlessPostgres.PgSchema.truncateAll(pool)
49
+ BackendState.setPostgres(~pool)
50
+ await fn()
51
+ BackendState.setMemory()
52
+ | None => ()
53
+ }
54
+
22
55
  describe("Backend parity (Memory vs Sqlite)", () => {
23
56
  testPromise("EventLog: append + replay returns the same events under both", async () => {
24
57
  let scenario = async () => {
25
58
  module TestBus = LocalBus.Make()
26
- module Storage = EventLogStorage_InMemory.Make(TestBus)
59
+ module Storage = LocalEventLogStorage.Make(TestBus)
27
60
  let s = Storage.make(~name="parity-events", ~opts)
28
61
  let ops = await s.operations->TestRunner.resolve
29
62
 
@@ -41,12 +74,13 @@ describe("Backend parity (Memory vs Sqlite)", () => {
41
74
 
42
75
  await runUnderMemory(scenario)
43
76
  await runUnderSqlite(scenario)
77
+ await runUnderPostgres(scenario)
44
78
  })
45
79
 
46
80
  testPromise("QueryDb: save + loadStream returns the same item under both", async () => {
47
81
  let scenario = async () => {
48
82
  module TestBus = LocalBus.Make()
49
- module Storage = QueryDbStorage_InMemory.Make(TestBus)
83
+ module Storage = LocalQueryDbStorage.Make(TestBus)
50
84
  let s = Storage.make(~name="parity-qdb", ~indexes=[], ~api=(), ~apiRole=(), ~opts)
51
85
  let ops = await s.operations->TestRunner.resolve
52
86
 
@@ -73,7 +107,7 @@ describe("Backend parity (Memory vs Sqlite)", () => {
73
107
  testPromise("QueryDb: count returns a running total and loadStream reflects it under both", async () => {
74
108
  let scenario = async () => {
75
109
  module TestBus = LocalBus.Make()
76
- module Storage = QueryDbStorage_InMemory.Make(TestBus)
110
+ module Storage = LocalQueryDbStorage.Make(TestBus)
77
111
  let s = Storage.make(~name="parity-count", ~indexes=[], ~api=(), ~apiRole=(), ~opts)
78
112
  let ops = await s.operations->TestRunner.resolve
79
113
 
@@ -108,7 +142,7 @@ describe("Backend parity (Memory vs Sqlite)", () => {
108
142
  testPromise("QueryDb: an expired-TTL item is filtered from loadStream under both", async () => {
109
143
  let scenario = async () => {
110
144
  module TestBus = LocalBus.Make()
111
- module Storage = QueryDbStorage_InMemory.Make(TestBus)
145
+ module Storage = LocalQueryDbStorage.Make(TestBus)
112
146
  let s = Storage.make(~name="parity-ttl", ~indexes=[], ~api=(), ~apiRole=(), ~opts)
113
147
  let ops = await s.operations->TestRunner.resolve
114
148
 
@@ -137,14 +171,14 @@ describe("Backend parity (Memory vs Sqlite)", () => {
137
171
  testPromise("EventLog: conflict detection works under both", async () => {
138
172
  let scenario = async () => {
139
173
  module TestBus = LocalBus.Make()
140
- module Storage = EventLogStorage_InMemory.Make(TestBus)
174
+ module Storage = LocalEventLogStorage.Make(TestBus)
141
175
  let s = Storage.make(~name="parity-conflict", ~opts)
142
176
  let ops = await s.operations->TestRunner.resolve
143
177
 
144
178
  let e = JSON.Encode.object(Dict.fromArray([("t", JSON.Encode.string("C"))]))
145
179
  let _ = await ops.append(0, "cid", [e])
146
180
 
147
- // Reusing seqNr=0 must conflict under both backends.
181
+ // Reusing seqNr=0 must conflict under every backend.
148
182
  let result = await ops.append(0, "cid", [e])
149
183
  switch result {
150
184
  | Error(_) => expect(true)->toBe(true)
@@ -154,5 +188,6 @@ describe("Backend parity (Memory vs Sqlite)", () => {
154
188
 
155
189
  await runUnderMemory(scenario)
156
190
  await runUnderSqlite(scenario)
191
+ await runUnderPostgres(scenario)
157
192
  })
158
193
  })
@@ -4,17 +4,31 @@ import * as Stream from "@reventlessdev/rescript-effect/src/Stream.res.mjs";
4
4
  import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
5
5
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
6
  import * as Effect from "effect/Effect";
7
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
7
8
  import * as LocalBus$ReventlessLocal from "../../src/adapter/LocalBus.res.mjs";
8
9
  import * as TestRunner$ReventlessLocal from "../../src/test/TestRunner.res.mjs";
10
+ import * as PgDriver$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/PgDriver.res.mjs";
11
+ import * as PgSchema$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/PgSchema.res.mjs";
9
12
  import * as BackendState$ReventlessLocal from "../../src/adapter/BackendState.res.mjs";
10
13
  import * as SqliteDriver$ReventlessLocal from "../../src/adapter/SqliteDriver.res.mjs";
11
- import * as QueryDbStorage_InMemory$ReventlessLocal from "../../src/adapter/QueryDb/QueryDbStorage_InMemory.res.mjs";
12
- import * as EventLogStorage_InMemory$ReventlessLocal from "../../src/adapter/EventLog/EventLogStorage_InMemory.res.mjs";
14
+ import * as LocalQueryDbStorage$ReventlessLocal from "../../src/adapter/QueryDb/LocalQueryDbStorage.res.mjs";
15
+ import * as LocalEventLogStorage$ReventlessLocal from "../../src/adapter/EventLog/LocalEventLogStorage.res.mjs";
13
16
 
14
17
  TestRunner$ReventlessLocal.setup();
15
18
 
16
19
  let opts = {};
17
20
 
21
+ let pgPool = Stdlib_Option.map(process.env["PG_URL"], url => PgDriver$ReventlessPostgres.makePool({
22
+ connectionString: url
23
+ }));
24
+
25
+ globalThis.afterAll(() => {
26
+ if (pgPool !== undefined) {
27
+ PgDriver$ReventlessPostgres.endPool(Primitive_option.valFromOption(pgPool));
28
+ return;
29
+ }
30
+ });
31
+
18
32
  async function runUnderMemory(fn) {
19
33
  BackendState$ReventlessLocal.setMemory();
20
34
  return await fn();
@@ -28,11 +42,23 @@ async function runUnderSqlite(fn) {
28
42
  return SqliteDriver$ReventlessLocal.close(db);
29
43
  }
30
44
 
45
+ async function runUnderPostgres(fn) {
46
+ if (pgPool === undefined) {
47
+ return;
48
+ }
49
+ let pool = Primitive_option.valFromOption(pgPool);
50
+ await PgSchema$ReventlessPostgres.ensureSchema(pool);
51
+ await PgSchema$ReventlessPostgres.truncateAll(pool);
52
+ BackendState$ReventlessLocal.setPostgres(pool);
53
+ await fn();
54
+ return BackendState$ReventlessLocal.setMemory();
55
+ }
56
+
31
57
  globalThis.describe("Backend parity (Memory vs Sqlite)", () => {
32
58
  globalThis.test("EventLog: append + replay returns the same events under both", async () => {
33
59
  let scenario = async () => {
34
60
  let TestBus = LocalBus$ReventlessLocal.Make({});
35
- let Storage = EventLogStorage_InMemory$ReventlessLocal.Make(TestBus);
61
+ let Storage = LocalEventLogStorage$ReventlessLocal.Make(TestBus);
36
62
  let s = Storage.make("parity-events", opts);
37
63
  let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
38
64
  let e1 = Object.fromEntries([[
@@ -51,12 +77,13 @@ globalThis.describe("Backend parity (Memory vs Sqlite)", () => {
51
77
  globalThis.expect(replayed[1]).toEqual(e2);
52
78
  };
53
79
  await runUnderMemory(scenario);
54
- return await runUnderSqlite(scenario);
80
+ await runUnderSqlite(scenario);
81
+ return await runUnderPostgres(scenario);
55
82
  });
56
83
  globalThis.test("QueryDb: save + loadStream returns the same item under both", async () => {
57
84
  let scenario = async () => {
58
85
  let TestBus = LocalBus$ReventlessLocal.Make({});
59
- let Storage = QueryDbStorage_InMemory$ReventlessLocal.Make(TestBus);
86
+ let Storage = LocalQueryDbStorage$ReventlessLocal.Make(TestBus);
60
87
  let s = Storage.make("parity-qdb", [], undefined, undefined, undefined, undefined, opts);
61
88
  let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
62
89
  await ops.save("k", "val", "Any", undefined);
@@ -70,7 +97,7 @@ globalThis.describe("Backend parity (Memory vs Sqlite)", () => {
70
97
  globalThis.test("QueryDb: count returns a running total and loadStream reflects it under both", async () => {
71
98
  let scenario = async () => {
72
99
  let TestBus = LocalBus$ReventlessLocal.Make({});
73
- let Storage = QueryDbStorage_InMemory$ReventlessLocal.Make(TestBus);
100
+ let Storage = LocalQueryDbStorage$ReventlessLocal.Make(TestBus);
74
101
  let s = Storage.make("parity-count", [], undefined, undefined, undefined, undefined, opts);
75
102
  let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
76
103
  let r1 = await ops.count("prod-1", "orderCount", 3);
@@ -94,7 +121,7 @@ globalThis.describe("Backend parity (Memory vs Sqlite)", () => {
94
121
  globalThis.test("QueryDb: an expired-TTL item is filtered from loadStream under both", async () => {
95
122
  let scenario = async () => {
96
123
  let TestBus = LocalBus$ReventlessLocal.Make({});
97
- let Storage = QueryDbStorage_InMemory$ReventlessLocal.Make(TestBus);
124
+ let Storage = LocalQueryDbStorage$ReventlessLocal.Make(TestBus);
98
125
  let s = Storage.make("parity-ttl", [], undefined, undefined, undefined, undefined, opts);
99
126
  let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
100
127
  let item = k => Object.fromEntries([[
@@ -113,7 +140,7 @@ globalThis.describe("Backend parity (Memory vs Sqlite)", () => {
113
140
  globalThis.test("EventLog: conflict detection works under both", async () => {
114
141
  let scenario = async () => {
115
142
  let TestBus = LocalBus$ReventlessLocal.Make({});
116
- let Storage = EventLogStorage_InMemory$ReventlessLocal.Make(TestBus);
143
+ let Storage = LocalEventLogStorage$ReventlessLocal.Make(TestBus);
117
144
  let s = Storage.make("parity-conflict", opts);
118
145
  let ops = await TestRunner$ReventlessLocal.resolve(s.operations);
119
146
  let e = Object.fromEntries([[
@@ -129,13 +156,16 @@ globalThis.describe("Backend parity (Memory vs Sqlite)", () => {
129
156
  globalThis.expect(true).toBe(true);
130
157
  };
131
158
  await runUnderMemory(scenario);
132
- return await runUnderSqlite(scenario);
159
+ await runUnderSqlite(scenario);
160
+ return await runUnderPostgres(scenario);
133
161
  });
134
162
  });
135
163
 
136
164
  export {
137
165
  opts,
166
+ pgPool,
138
167
  runUnderMemory,
139
168
  runUnderSqlite,
169
+ runUnderPostgres,
140
170
  }
141
171
  /* Not a pure module */