@reventlessdev/reventless-local 3.0.0-alpha.316 → 3.0.0-alpha.318

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 (57) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +11 -11
  3. package/src/LocalPlatformRegistry.res +19 -0
  4. package/src/LocalPlatformRegistry.res.mjs +19 -1
  5. package/src/Platform.res +24 -2
  6. package/src/Platform.res.mjs +22 -2
  7. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res +38 -0
  8. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res.mjs +29 -0
  9. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res +87 -0
  10. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res.mjs +76 -0
  11. package/src/adapter/DcbEventLog/LocalDcbEventLogStorage.res +8 -1
  12. package/src/adapter/DcbEventLog/LocalDcbEventLogStorage.res.mjs +17 -4
  13. package/src/adapter/EventLog/EventLogStorage_InMemory.res +49 -2
  14. package/src/adapter/EventLog/EventLogStorage_InMemory.res.mjs +57 -21
  15. package/src/adapter/EventLog/EventLogStorage_Sqlite.res +85 -0
  16. package/src/adapter/EventLog/EventLogStorage_Sqlite.res.mjs +50 -0
  17. package/src/adapter/EventLog/LocalEventLogStorage.res +3 -0
  18. package/src/adapter/EventLog/LocalEventLogStorage.res.mjs +6 -2
  19. package/src/adapter/LocalBus.res +32 -5
  20. package/src/adapter/LocalBus.res.mjs +27 -7
  21. package/src/adapter/LocalEventLogRead.res +477 -0
  22. package/src/adapter/LocalEventLogRead.res.mjs +507 -0
  23. package/src/adapter/LocalEventTap.res +18 -80
  24. package/src/adapter/LocalEventTap.res.mjs +19 -108
  25. package/src/adapter/LocalFeed.res +433 -0
  26. package/src/adapter/LocalFeed.res.mjs +419 -0
  27. package/src/adapter/LocalLogFeed.res +217 -0
  28. package/src/adapter/LocalLogFeed.res.mjs +295 -0
  29. package/src/adapter/LocalPgEventLogRead.res +85 -0
  30. package/src/adapter/LocalPgEventLogRead.res.mjs +91 -0
  31. package/src/adapter/LocalPlatformObserve.res +456 -0
  32. package/src/adapter/LocalPlatformObserve.res.mjs +505 -0
  33. package/src/adapter/LocalTapLines.res +147 -0
  34. package/src/adapter/LocalTapLines.res.mjs +229 -0
  35. package/src/adapter/PlatformGraphQL_Server.res +36 -3
  36. package/src/adapter/PlatformGraphQL_Server.res.mjs +15 -1
  37. package/src/reexport/CommandTopic.res.mjs +5 -2
  38. package/tests/adapter/GraphQLWsFixtures.mjs +46 -0
  39. package/tests/adapter/LocalEventLogReadTest.res +539 -0
  40. package/tests/adapter/LocalEventLogReadTest.res.mjs +466 -0
  41. package/tests/adapter/LocalFeedTest.res +314 -0
  42. package/tests/adapter/LocalFeedTest.res.mjs +329 -0
  43. package/tests/adapter/LocalPlatformObserveTest.res +165 -0
  44. package/tests/adapter/LocalPlatformObserveTest.res.mjs +183 -0
  45. package/tests/adapter/LocalTapLinesTest.res +182 -0
  46. package/tests/adapter/LocalTapLinesTest.res.mjs +242 -0
  47. package/tests/adapter/PlatformSubscriptionsTest.res +123 -0
  48. package/tests/adapter/PlatformSubscriptionsTest.res.mjs +132 -0
  49. package/tests/components/automationslice/AutomationSliceCallbackTest.res +80 -0
  50. package/tests/components/automationslice/AutomationSliceCallbackTest.res.mjs +81 -0
  51. package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res +17 -0
  52. package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res.mjs +24 -0
  53. package/tests/components/automationslice/AutomationSliceSelfDeadlockTest.res +30 -0
  54. package/tests/components/automationslice/AutomationSliceSelfDeadlockTest.res.mjs +28 -0
  55. package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res +58 -0
  56. package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res.mjs +71 -19
  57. package/tests/components/outboundtranslationslice/OutboundTranslationSlicePiiTest.res.mjs +7 -7
@@ -0,0 +1,295 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
4
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Logger$ReventlessCore from "@reventlessdev/reventless-core/src/util/Logger.res.mjs";
6
+ import * as LocalFeed$ReventlessLocal from "./LocalFeed.res.mjs";
7
+
8
+ function makeRing(maxCount, maxBytes) {
9
+ return {
10
+ maxCount: maxCount,
11
+ maxBytes: maxBytes,
12
+ entries: [],
13
+ head: 0,
14
+ bytes: 0
15
+ };
16
+ }
17
+
18
+ function size(r) {
19
+ return r.entries.length - r.head | 0;
20
+ }
21
+
22
+ function entryBytes(e) {
23
+ return e.item.line.length;
24
+ }
25
+
26
+ function push(r, e) {
27
+ if (!(r.maxCount > 0 && r.maxBytes > 0)) {
28
+ return;
29
+ }
30
+ r.entries.push(e);
31
+ r.bytes = r.bytes + e.item.line.length | 0;
32
+ while (size(r) > 0 && (size(r) > r.maxCount || r.bytes > r.maxBytes)) {
33
+ r.bytes = r.bytes - r.entries[r.head].item.line.length | 0;
34
+ r.head = r.head + 1 | 0;
35
+ };
36
+ if (r.head > 1024 && (r.head << 1) > r.entries.length) {
37
+ r.entries = r.entries.slice(r.head, r.entries.length);
38
+ r.head = 0;
39
+ return;
40
+ }
41
+ }
42
+
43
+ function toArray(r) {
44
+ return r.entries.slice(r.head, r.entries.length);
45
+ }
46
+
47
+ function ringBytes(r) {
48
+ return r.bytes;
49
+ }
50
+
51
+ function clear(r) {
52
+ r.entries = [];
53
+ r.head = 0;
54
+ r.bytes = 0;
55
+ }
56
+
57
+ let ringEnvVar = "REVENTLESS_LOG_RING";
58
+
59
+ let problemRingEnvVar = "REVENTLESS_LOG_PROBLEM_RING";
60
+
61
+ function boundsOf(value, count, bytes) {
62
+ let match = Stdlib_Option.map(value, v => v.trim().split(","));
63
+ if (match === undefined) {
64
+ return [
65
+ count,
66
+ bytes
67
+ ];
68
+ }
69
+ let len = match.length;
70
+ if (len >= 3) {
71
+ return [
72
+ count,
73
+ bytes
74
+ ];
75
+ }
76
+ switch (len) {
77
+ case 0 :
78
+ return [
79
+ count,
80
+ bytes
81
+ ];
82
+ case 1 :
83
+ let c = match[0];
84
+ return [
85
+ Stdlib_Option.getOr(Stdlib_Int.fromString(c.trim(), undefined), count),
86
+ bytes
87
+ ];
88
+ case 2 :
89
+ let c$1 = match[0];
90
+ let b = match[1];
91
+ return [
92
+ Stdlib_Option.getOr(Stdlib_Int.fromString(c$1.trim(), undefined), count),
93
+ Stdlib_Option.getOr(Stdlib_Int.fromString(b.trim(), undefined), bytes)
94
+ ];
95
+ }
96
+ }
97
+
98
+ let recent = {
99
+ maxCount: 5000,
100
+ maxBytes: 8388608,
101
+ entries: [],
102
+ head: 0,
103
+ bytes: 0
104
+ };
105
+
106
+ let problems = {
107
+ maxCount: 1000,
108
+ maxBytes: 2097152,
109
+ entries: [],
110
+ head: 0,
111
+ bytes: 0
112
+ };
113
+
114
+ function isProblem(level) {
115
+ switch (level) {
116
+ case "Debug" :
117
+ case "Info" :
118
+ return false;
119
+ case "Warn" :
120
+ case "Error" :
121
+ return true;
122
+ }
123
+ }
124
+
125
+ function snapshot() {
126
+ let seen = new Set();
127
+ return toArray(recent).concat(toArray(problems)).filter(e => {
128
+ if (seen.has(e.seq)) {
129
+ return false;
130
+ } else {
131
+ seen.add(e.seq);
132
+ return true;
133
+ }
134
+ }).toSorted((a, b) => a.seq - b.seq | 0);
135
+ }
136
+
137
+ function facetsOf(r) {
138
+ return {
139
+ plugin: r.plugin,
140
+ level: r.level,
141
+ comp: r.comp,
142
+ correlationId: r.annotations["correlationId"]
143
+ };
144
+ }
145
+
146
+ function itemOf(r) {
147
+ return {
148
+ line: JSON.stringify(Logger$ReventlessCore.recordToJson(r)),
149
+ facets: facetsOf(r)
150
+ };
151
+ }
152
+
153
+ let honours = [
154
+ "Plugins",
155
+ "Level",
156
+ "Components",
157
+ "CorrelationId"
158
+ ];
159
+
160
+ function recentRecords(filter, limit) {
161
+ let selected = snapshot().filter(e => LocalFeed$ReventlessLocal.matches(honours, filter, e.item.facets)).map(e => e.record);
162
+ if (limit !== undefined && limit >= 0 && selected.length > limit) {
163
+ return selected.slice(selected.length - limit | 0, selected.length);
164
+ } else {
165
+ return selected;
166
+ }
167
+ }
168
+
169
+ let envVar = "REVENTLESS_LOG_FEED";
170
+
171
+ let feed = LocalFeed$ReventlessLocal.make("LogFeed", honours, () => snapshot().map(e => e.item), undefined, 16777216, undefined, undefined);
172
+
173
+ function port() {
174
+ return LocalFeed$ReventlessLocal.port(feed);
175
+ }
176
+
177
+ function hasReaders() {
178
+ return LocalFeed$ReventlessLocal.hasReaders(feed);
179
+ }
180
+
181
+ let seq = {
182
+ contents: 0
183
+ };
184
+
185
+ let removeSink = {
186
+ contents: undefined
187
+ };
188
+
189
+ function onRecord(record) {
190
+ seq.contents = seq.contents + 1 | 0;
191
+ let entry_seq = seq.contents;
192
+ let entry_item = itemOf(record);
193
+ let entry = {
194
+ seq: entry_seq,
195
+ record: record,
196
+ item: entry_item
197
+ };
198
+ push(recent, entry);
199
+ if (isProblem(record.level)) {
200
+ push(problems, entry);
201
+ }
202
+ if (LocalFeed$ReventlessLocal.hasReaders(feed)) {
203
+ return LocalFeed$ReventlessLocal.publish(feed, entry_item);
204
+ }
205
+ }
206
+
207
+ function keepProblem(record) {
208
+ if (!isProblem(record.level)) {
209
+ return;
210
+ }
211
+ seq.contents = seq.contents + 1 | 0;
212
+ let entry_seq = seq.contents;
213
+ let entry_item = itemOf(record);
214
+ let entry = {
215
+ seq: entry_seq,
216
+ record: record,
217
+ item: entry_item
218
+ };
219
+ push(problems, entry);
220
+ if (LocalFeed$ReventlessLocal.hasReaders(feed)) {
221
+ return LocalFeed$ReventlessLocal.publish(feed, entry_item);
222
+ }
223
+ }
224
+
225
+ function install(envOpt) {
226
+ let env = envOpt !== undefined ? envOpt : process.env;
227
+ let match = boundsOf(env[ringEnvVar], 5000, 8388608);
228
+ recent.maxCount = match[0];
229
+ recent.maxBytes = match[1];
230
+ let match$1 = boundsOf(env[problemRingEnvVar], 1000, 2097152);
231
+ problems.maxCount = match$1[0];
232
+ problems.maxBytes = match$1[1];
233
+ let match$2 = removeSink.contents;
234
+ if (match$2 !== undefined) {
235
+ return;
236
+ } else {
237
+ removeSink.contents = Logger$ReventlessCore.addSink(onRecord);
238
+ return;
239
+ }
240
+ }
241
+
242
+ function start(envOpt, onBoundOpt, param) {
243
+ let env = envOpt !== undefined ? envOpt : process.env;
244
+ let onBound = onBoundOpt !== undefined ? onBoundOpt : param => {};
245
+ LocalFeed$ReventlessLocal.start(feed, LocalFeed$ReventlessLocal.settingOf(env[envVar]), onBound, undefined);
246
+ }
247
+
248
+ function resetForTests() {
249
+ Stdlib_Option.forEach(removeSink.contents, remove => remove());
250
+ removeSink.contents = undefined;
251
+ clear(recent);
252
+ clear(problems);
253
+ LocalFeed$ReventlessLocal.resetForTests(feed);
254
+ }
255
+
256
+ function stopForTests() {
257
+ return LocalFeed$ReventlessLocal.stopForTests(feed);
258
+ }
259
+
260
+ let Logger;
261
+
262
+ export {
263
+ Logger,
264
+ makeRing,
265
+ size,
266
+ entryBytes,
267
+ push,
268
+ toArray,
269
+ ringBytes,
270
+ clear,
271
+ ringEnvVar,
272
+ problemRingEnvVar,
273
+ boundsOf,
274
+ recent,
275
+ problems,
276
+ isProblem,
277
+ snapshot,
278
+ facetsOf,
279
+ itemOf,
280
+ honours,
281
+ recentRecords,
282
+ envVar,
283
+ feed,
284
+ port,
285
+ hasReaders,
286
+ seq,
287
+ removeSink,
288
+ onRecord,
289
+ keepProblem,
290
+ install,
291
+ start,
292
+ resetForTests,
293
+ stopForTests,
294
+ }
295
+ /* feed Not a pure module */
@@ -0,0 +1,85 @@
1
+ // The Postgres backend's part in the read across every event log and in the
2
+ // tap's positions: its logs are read backwards by `global_seq` (aggregate) and
3
+ // `position` (DCB), and each appended event's position is noted for the tap.
4
+
5
+ module AggOps = ReventlessPostgres.EventLogStorage_Postgres_Ops
6
+ module DcbOps = ReventlessPostgres.DcbEventLogStorage_Postgres_Ops
7
+
8
+ /** For an aggregate log's `onAppended`: notes each event's `global_seq`. */
9
+ let noteAppended = (~name: string) =>
10
+ (pairs: array<(string, int)>) =>
11
+ pairs->Array.forEach(((msgId, position)) =>
12
+ LocalEventLogRead.note(~log=name, ~msgId, ~position=position->Int.toFloat)
13
+ )
14
+
15
+ let registerAggregate = (~pool: ReventlessPostgres.PgDriver.pool, ~name: string) =>
16
+ LocalEventLogRead.register(~log=name, ~kind=Aggregate, async (~bound, ~limit, ~correlationId) =>
17
+ (
18
+ await AggOps.readBackwards(
19
+ pool,
20
+ ~name,
21
+ ~bound=bound->Option.map(b =>
22
+ switch b {
23
+ | LocalEventLogRead.Below(p) => AggOps.Below(p)
24
+ | AtMost(p) => AggOps.AtMost(p)
25
+ }
26
+ ),
27
+ ~limit,
28
+ ~correlationId,
29
+ )
30
+ )->Array.map(((position, entityId, payload)) =>
31
+ LocalEventLogRead.storedOfFlat(~log=name, ~position, ~entityId, payload)
32
+ )
33
+ )
34
+
35
+ let registerDcb = (~pool: ReventlessPostgres.PgDriver.pool, ~name: string) =>
36
+ LocalEventLogRead.register(~log=name, ~kind=Dcb, async (~bound, ~limit, ~correlationId) =>
37
+ (
38
+ await DcbOps.readBackwards(
39
+ pool,
40
+ ~name,
41
+ ~bound=bound->Option.map(b =>
42
+ switch b {
43
+ | LocalEventLogRead.Below(p) => DcbOps.Below(p)
44
+ | AtMost(p) => DcbOps.AtMost(p)
45
+ }
46
+ ),
47
+ ~limit,
48
+ ~correlationId,
49
+ )
50
+ )->Array.map(((position, e)): LocalEventLogRead.stored => {
51
+ log: name,
52
+ position,
53
+ eventType: e.eventType,
54
+ tags: e.tags,
55
+ payload: e.data,
56
+ meta: e.meta->Reventless.Util_Sury.toJson(Reventless.Message.metaSchema),
57
+ recordedAt: e.recordedAt,
58
+ })
59
+ )
60
+
61
+ /** A DCB append that also notes where each event went. The append returns only
62
+ its last cursor, so the positions are read back once. */
63
+ let notingDcbAppend = (
64
+ ~pool: ReventlessPostgres.PgDriver.pool,
65
+ ~name: string,
66
+ append: (
67
+ array<ReventlessCore.DcbEventLog_Adapter.rawStoredEvent>,
68
+ ~condition: Reventless.DcbTag.appendCondition=?,
69
+ ) => promise<result<Reventless.DcbTag.sequencePosition, ReventlessInfra.DcbEventLog.appendError>>,
70
+ ) =>
71
+ async (events, ~condition=?) => {
72
+ let result = await append(events, ~condition?)
73
+ switch result {
74
+ | Ok(cursor) =>
75
+ switch await DcbOps.positionsOfAppend(pool, ~name, ~cursor) {
76
+ | positions =>
77
+ positions->Array.forEach(((msgId, position)) =>
78
+ LocalEventLogRead.note(~log=name, ~msgId, ~position)
79
+ )
80
+ | exception _ => ()
81
+ }
82
+ | Error(_) => ()
83
+ }
84
+ result
85
+ }
@@ -0,0 +1,91 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+ import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
5
+ import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
6
+ import * as LocalEventLogRead$ReventlessLocal from "./LocalEventLogRead.res.mjs";
7
+ import * as EventLogStorage_Postgres_Ops$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/EventLogStorage_Postgres_Ops.res.mjs";
8
+ import * as DcbEventLogStorage_Postgres_Ops$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/DcbEventLogStorage_Postgres_Ops.res.mjs";
9
+
10
+ function noteAppended(name) {
11
+ return pairs => {
12
+ pairs.forEach(param => LocalEventLogRead$ReventlessLocal.note(name, param[0], param[1]));
13
+ };
14
+ }
15
+
16
+ function registerAggregate(pool, name) {
17
+ LocalEventLogRead$ReventlessLocal.register(name, "Aggregate", async (bound, limit, correlationId) => (await EventLogStorage_Postgres_Ops$ReventlessPostgres.readBackwards(pool, name, Stdlib_Option.map(bound, b => {
18
+ if (b.TAG === "Below") {
19
+ return {
20
+ TAG: "Below",
21
+ _0: b._0
22
+ };
23
+ } else {
24
+ return {
25
+ TAG: "AtMost",
26
+ _0: b._0
27
+ };
28
+ }
29
+ }), limit, correlationId)).map(param => LocalEventLogRead$ReventlessLocal.storedOfFlat(name, param[0], param[1], param[2])));
30
+ }
31
+
32
+ function registerDcb(pool, name) {
33
+ LocalEventLogRead$ReventlessLocal.register(name, "Dcb", async (bound, limit, correlationId) => (await DcbEventLogStorage_Postgres_Ops$ReventlessPostgres.readBackwards(pool, name, Stdlib_Option.map(bound, b => {
34
+ if (b.TAG === "Below") {
35
+ return {
36
+ TAG: "Below",
37
+ _0: b._0
38
+ };
39
+ } else {
40
+ return {
41
+ TAG: "AtMost",
42
+ _0: b._0
43
+ };
44
+ }
45
+ }), limit, correlationId)).map(param => {
46
+ let e = param[1];
47
+ return {
48
+ log: name,
49
+ position: param[0],
50
+ eventType: e.eventType,
51
+ tags: e.tags,
52
+ payload: e.data,
53
+ meta: Util_Sury$Reventless.toJson(e.meta, Message$Reventless.metaSchema),
54
+ recordedAt: e.recordedAt
55
+ };
56
+ }));
57
+ }
58
+
59
+ function notingDcbAppend(pool, name, append) {
60
+ return async (events, condition) => {
61
+ let result = await append(events, condition);
62
+ if (result.TAG === "Ok") {
63
+ let exit = 0;
64
+ let positions;
65
+ try {
66
+ positions = await DcbEventLogStorage_Postgres_Ops$ReventlessPostgres.positionsOfAppend(pool, name, result._0);
67
+ exit = 1;
68
+ } catch (exn) {
69
+
70
+ }
71
+ if (exit === 1) {
72
+ positions.forEach(param => LocalEventLogRead$ReventlessLocal.note(name, param[0], param[1]));
73
+ }
74
+ }
75
+ return result;
76
+ };
77
+ }
78
+
79
+ let AggOps;
80
+
81
+ let DcbOps;
82
+
83
+ export {
84
+ AggOps,
85
+ DcbOps,
86
+ noteAppended,
87
+ registerAggregate,
88
+ registerDcb,
89
+ notingDcbAppend,
90
+ }
91
+ /* Message-Reventless Not a pure module */