@reventlessdev/reventless-core 3.0.0-alpha.197 → 3.0.0-alpha.198

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,13 @@
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.198 (2026-08-01)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **core:** drain the inbound audit log per request, not wholesale ([e18d4ec](https://github.com/ReventlessDev/reventless-core/commit/e18d4ec4b7ffb38a9e2bd3594d39a07e2ee91851))
11
+
12
+
6
13
  # 3.0.0-alpha.197 (2026-08-01)
7
14
 
8
15
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-core",
3
- "version": "3.0.0-alpha.197",
3
+ "version": "3.0.0-alpha.198",
4
4
  "description": "Core package for Reventless framework",
5
5
  "license": "Apache-2.0",
6
6
  "jest": {
@@ -29,16 +29,16 @@
29
29
  "sury": "11.0.0-alpha.4",
30
30
  "uuid": "^13.0.0",
31
31
  "@reventlessdev/rescript-effect": "0.1.0-alpha.32",
32
- "@reventlessdev/rescript-fast-csv": "2.0.0-alpha.0",
33
32
  "@reventlessdev/rescript-hash-object": "1.2.0-alpha.14",
33
+ "@reventlessdev/rescript-fast-csv": "2.0.0-alpha.0",
34
34
  "@reventlessdev/rescript-jest": "1.0.0-alpha.10",
35
35
  "@reventlessdev/rescript-node": "2.0.0-alpha.0",
36
36
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
37
37
  "@reventlessdev/rescript-ssh2": "2.0.0-alpha.0",
38
+ "@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
38
39
  "@reventlessdev/reventless-interop": "3.0.0-alpha.30",
39
40
  "@reventlessdev/reventless-infra": "3.0.0-alpha.115",
40
- "@reventlessdev/reventless-spec": "3.0.0-alpha.90",
41
- "@reventlessdev/rescript-uuid": "2.0.0-alpha.0"
41
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.90"
42
42
  },
43
43
  "devDependencies": {
44
44
  "rescript": "12.3.0",
@@ -41,18 +41,19 @@ module Make = (
41
41
 
42
42
  module SpecificQueryDb = QueryDb_Builder.Make(AuditQueryDbSpec, QueryDbStorage, QueryDbResolvers)
43
43
 
44
- let syncToQueryDb = async (queryDbOps: SpecificQueryDb.operations) => {
45
- let items = Callback.auditLog->Dict.toArray
46
- let _ = await items->Array.reduce(Promise.resolve(), async (prev, (id, row)) => {
47
- let _ = await prev
44
+ // Persist just this request's audit row, taking it out of the in-memory log
45
+ // as it goes — see `takeAuditRow` for why draining the whole dict is wrong.
46
+ let syncToQueryDb = async (queryDbOps: SpecificQueryDb.operations, requestId: string) =>
47
+ switch Callback.auditLog->InboundTranslationSlice_Callback.takeAuditRow(requestId) {
48
+ | Some(row) =>
48
49
  let _ = await queryDbOps.save(
49
- id->Reventless.Id.String.makeFromString,
50
+ requestId->Reventless.Id.String.makeFromString,
50
51
  row,
51
52
  QueryDb.Overwrite,
52
53
  None,
53
54
  )
54
- })
55
- }
55
+ | None => ()
56
+ }
56
57
 
57
58
  let construct = (~publishJsons, self, _name) => {
58
59
  let opts = {Pulumi.ComponentResource.parent: self->Component.toPulumiResource}
@@ -77,7 +78,10 @@ module Make = (
77
78
  let ops: InboundTranslationSlice.operations = {
78
79
  receive: async inputJson => {
79
80
  let result = await Callback.receive(publishJsonsFn, inputJson)
80
- await syncToQueryDb(queryDbOps)
81
+ await syncToQueryDb(
82
+ queryDbOps,
83
+ result->InboundTranslationSlice_Callback.requestIdOf,
84
+ )
81
85
  result
82
86
  },
83
87
  }
@@ -1,6 +1,5 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
4
3
  import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
5
4
  import * as Pulumi from "@pulumi/pulumi";
6
5
  import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/components/ReadModel.res.mjs";
@@ -27,12 +26,12 @@ function Make(QueryDbStorage) {
27
26
  authorization: "AllowAuthenticated",
28
27
  visibility: "Public"
29
28
  })(QueryDbStorage)(QueryDbResolvers);
30
- let syncToQueryDb = async queryDbOps => {
31
- let items = Object.entries(Callback.auditLog);
32
- await Stdlib_Array.reduce(items, Promise.resolve(), async (prev, param) => {
33
- await prev;
34
- await queryDbOps.save(Id$Reventless.$$String.makeFromString(param[0]), param[1], "Overwrite", undefined);
35
- });
29
+ let syncToQueryDb = async (queryDbOps, requestId) => {
30
+ let row = InboundTranslationSlice_Callback$ReventlessCore.takeAuditRow(Callback.auditLog, requestId);
31
+ if (row !== undefined) {
32
+ await queryDbOps.save(Id$Reventless.$$String.makeFromString(requestId), row, "Overwrite", undefined);
33
+ return;
34
+ }
36
35
  };
37
36
  let make = (publishJsons, param, opts) => Component$ReventlessCore.make(ComponentType$ReventlessCore.toString(InboundTranslationSlice$ReventlessCore.componentType), Spec.name, (extra, extra$1) => {
38
37
  let opts_parent = Component$ReventlessCore.toPulumiResource(extra);
@@ -58,7 +57,7 @@ function Make(QueryDbStorage) {
58
57
  return {
59
58
  receive: async inputJson => {
60
59
  let result = await Callback.receive(publishJsonsFn, inputJson);
61
- await syncToQueryDb(queryDbOps);
60
+ await syncToQueryDb(queryDbOps, InboundTranslationSlice_Callback$ReventlessCore.requestIdOf(result));
62
61
  return result;
63
62
  }
64
63
  };
@@ -46,6 +46,33 @@ let receiveResultToOutcome = (
46
46
  Rejected({msgId: requestId, errorCode: "TranslationFailed", errorDetail: Some(error)})
47
47
  }
48
48
 
49
+ /**
50
+ The request a `receive` outcome belongs to, from either arm. Both carry the id
51
+ that keys the outcome's audit row, so a caller draining the log does not have to
52
+ match on the result to find its own row.
53
+ */
54
+ let requestIdOf = (result: ReventlessInfra.InboundTranslationSlice.receiveResult): string =>
55
+ switch result {
56
+ | Ok({requestId}) | Error({requestId}) => requestId
57
+ }
58
+
59
+ /**
60
+ Remove one request's audit row from the in-memory log and hand it back.
61
+
62
+ `auditLog` is a hand-off buffer between `receive` and whoever persists the row,
63
+ not a log in its own right — the QueryDb it drains into is the durable one. It
64
+ has to be emptied as it drains: the dict lives as long as the process (a warm
65
+ Lambda container serves many requests), so a drain that walked the whole dict
66
+ would rewrite every row the container had ever seen on every request — quadratic
67
+ writes, unbounded retention, and, because the write is an overwrite by row id,
68
+ resurrection of rows deleted from the table since.
69
+ */
70
+ let takeAuditRow = (auditLog: Dict.t<auditRow>, requestId: string): option<auditRow> => {
71
+ let row = auditLog->Dict.get(requestId)
72
+ auditLog->Dict.delete(requestId)
73
+ row
74
+ }
75
+
49
76
  module type T = {
50
77
  module Spec: Reventless.InboundTranslationSlice.Spec
51
78
  module Translation: Reventless.InboundTranslationSlice.Translation with module Spec := Spec
@@ -2,6 +2,7 @@
2
2
 
3
3
  import * as S from "sury/src/S.res.mjs";
4
4
  import * as Uuid from "uuid";
5
+ import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
5
6
  import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
6
7
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
8
  import * as Effect from "effect/Effect";
@@ -55,6 +56,16 @@ function receiveResultToOutcome(result) {
55
56
  };
56
57
  }
57
58
 
59
+ function requestIdOf(result) {
60
+ return result._0.requestId;
61
+ }
62
+
63
+ function takeAuditRow(auditLog, requestId) {
64
+ let row = auditLog[requestId];
65
+ Stdlib_Dict.$$delete(auditLog, requestId);
66
+ return row;
67
+ }
68
+
58
69
  function Make(Spec) {
59
70
  return Translation => {
60
71
  let auditLog = {};
@@ -221,6 +232,8 @@ export {
221
232
  auditStatusSchema,
222
233
  auditRowSchema,
223
234
  receiveResultToOutcome,
235
+ requestIdOf,
236
+ takeAuditRow,
224
237
  Make,
225
238
  }
226
239
  /* Not a pure module */