@arvo-tools/postgres 1.2.2 → 1.3.1

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.
@@ -1,62 +1,15 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
- return new (P || (P = Promise))(function (resolve, reject) {
16
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
- step((generator = generator.apply(thisArg, _arguments || [])).next());
20
- });
21
- };
22
- var __generator = (this && this.__generator) || function (thisArg, body) {
23
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
- function verb(n) { return function (v) { return step([n, v]); }; }
26
- function step(op) {
27
- if (f) throw new TypeError("Generator is already executing.");
28
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
- if (y = 0, t) op = [op[0] & 2, t.value];
31
- switch (op[0]) {
32
- case 0: case 1: t = op; break;
33
- case 4: _.label++; return { value: op[1], done: false };
34
- case 5: _.label++; y = op[1]; op = [0]; continue;
35
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
- default:
37
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
- if (t[2]) _.ops.pop();
42
- _.trys.pop(); continue;
43
- }
44
- op = body.call(thisArg, _);
45
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
- }
48
- };
49
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
50
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
51
4
  };
52
5
  Object.defineProperty(exports, "__esModule", { value: true });
53
6
  exports.PostgressMachineMemoryV1 = void 0;
54
- var api_1 = require("@opentelemetry/api");
55
- var arvo_core_1 = require("arvo-core");
56
- var arvo_event_handler_1 = require("arvo-event-handler");
57
- var pg_1 = require("pg");
58
- var pg_format_1 = __importDefault(require("pg-format"));
59
- var schema_1 = require("./schema");
7
+ const api_1 = require("@opentelemetry/api");
8
+ const arvo_core_1 = require("arvo-core");
9
+ const arvo_event_handler_1 = require("arvo-event-handler");
10
+ const pg_1 = require("pg");
11
+ const pg_format_1 = __importDefault(require("pg-format"));
12
+ const schema_1 = require("./schema");
60
13
  /**
61
14
  * PostgreSQL-backed implementation of IMachineMemory for distributed workflow state management.
62
15
  *
@@ -72,454 +25,302 @@ var schema_1 = require("./schema");
72
25
  * - Lock table: Manages distributed locks with automatic expiration
73
26
  * - Hierarchy table: Tracks workflow parent-child relationships and root subjects
74
27
  */
75
- var PostgressMachineMemoryV1 = /** @class */ (function () {
76
- function PostgressMachineMemoryV1(param) {
77
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
28
+ class PostgressMachineMemoryV1 {
29
+ dbSchemaName;
30
+ tables;
31
+ lockConfig;
32
+ enableCleanup;
33
+ enableOtel;
34
+ pool;
35
+ constructor(param) {
36
+ this.dbSchemaName = param.schema;
78
37
  this.tables = param.tables;
79
38
  this.lockConfig = {
80
- maxRetries: (_c = (_b = (_a = param.config) === null || _a === void 0 ? void 0 : _a.lockConfig) === null || _b === void 0 ? void 0 : _b.maxRetries) !== null && _c !== void 0 ? _c : 3,
81
- initialDelayMs: (_f = (_e = (_d = param.config) === null || _d === void 0 ? void 0 : _d.lockConfig) === null || _e === void 0 ? void 0 : _e.initialDelayMs) !== null && _f !== void 0 ? _f : 100,
82
- backoffExponent: (_j = (_h = (_g = param.config) === null || _g === void 0 ? void 0 : _g.lockConfig) === null || _h === void 0 ? void 0 : _h.backoffExponent) !== null && _j !== void 0 ? _j : 1.5,
83
- ttlMs: (_m = (_l = (_k = param.config) === null || _k === void 0 ? void 0 : _k.lockConfig) === null || _l === void 0 ? void 0 : _l.ttlMs) !== null && _m !== void 0 ? _m : 120000,
39
+ maxRetries: param.config?.lockConfig?.maxRetries ?? 3,
40
+ initialDelayMs: param.config?.lockConfig?.initialDelayMs ?? 100,
41
+ backoffExponent: param.config?.lockConfig?.backoffExponent ?? 1.5,
42
+ ttlMs: param.config?.lockConfig?.ttlMs ?? 120000,
84
43
  };
85
- this.enableCleanup = (_p = (_o = param.config) === null || _o === void 0 ? void 0 : _o.enableCleanup) !== null && _p !== void 0 ? _p : false;
86
- this.enableOtel = (_r = (_q = param.config) === null || _q === void 0 ? void 0 : _q.enableOtel) !== null && _r !== void 0 ? _r : false;
87
- var poolConfig;
44
+ this.enableCleanup = param.config?.enableCleanup ?? false;
45
+ this.enableOtel = param.config?.enableOtel ?? false;
46
+ let poolConfig;
88
47
  if (param.config && 'connectionString' in param.config) {
89
48
  poolConfig = {
90
49
  connectionString: param.config.connectionString,
91
- max: (_s = param.config.max) !== null && _s !== void 0 ? _s : 10,
92
- idleTimeoutMillis: (_t = param.config.idleTimeoutMillis) !== null && _t !== void 0 ? _t : 30000,
93
- connectionTimeoutMillis: (_u = param.config.connectionTimeoutMillis) !== null && _u !== void 0 ? _u : 5000,
94
- statement_timeout: (_v = param.config.statementTimeoutMillis) !== null && _v !== void 0 ? _v : 30000,
95
- query_timeout: (_w = param.config.queryTimeoutMillis) !== null && _w !== void 0 ? _w : 30000,
50
+ max: param.config.max ?? 10,
51
+ idleTimeoutMillis: param.config.idleTimeoutMillis ?? 30000,
52
+ connectionTimeoutMillis: param.config.connectionTimeoutMillis ?? 5000,
53
+ statement_timeout: param.config.statementTimeoutMillis ?? 30000,
54
+ query_timeout: param.config.queryTimeoutMillis ?? 30000,
96
55
  };
97
56
  }
98
57
  else {
99
- var cfg = param.config;
58
+ const cfg = param.config;
100
59
  poolConfig = {
101
- host: (_x = cfg === null || cfg === void 0 ? void 0 : cfg.host) !== null && _x !== void 0 ? _x : 'localhost',
102
- port: (_y = cfg === null || cfg === void 0 ? void 0 : cfg.port) !== null && _y !== void 0 ? _y : 5432,
103
- user: (_z = cfg === null || cfg === void 0 ? void 0 : cfg.user) !== null && _z !== void 0 ? _z : 'postgres',
104
- password: (_0 = cfg === null || cfg === void 0 ? void 0 : cfg.password) !== null && _0 !== void 0 ? _0 : 'postgres',
105
- database: (_1 = cfg === null || cfg === void 0 ? void 0 : cfg.database) !== null && _1 !== void 0 ? _1 : 'postgres',
106
- max: (_2 = cfg === null || cfg === void 0 ? void 0 : cfg.max) !== null && _2 !== void 0 ? _2 : 10,
107
- idleTimeoutMillis: (_3 = cfg === null || cfg === void 0 ? void 0 : cfg.idleTimeoutMillis) !== null && _3 !== void 0 ? _3 : 30000,
108
- connectionTimeoutMillis: (_4 = cfg === null || cfg === void 0 ? void 0 : cfg.connectionTimeoutMillis) !== null && _4 !== void 0 ? _4 : 5000,
109
- statement_timeout: (_5 = cfg === null || cfg === void 0 ? void 0 : cfg.statementTimeoutMillis) !== null && _5 !== void 0 ? _5 : 30000,
110
- query_timeout: (_6 = cfg === null || cfg === void 0 ? void 0 : cfg.queryTimeoutMillis) !== null && _6 !== void 0 ? _6 : 30000,
60
+ host: cfg?.host ?? 'localhost',
61
+ port: cfg?.port ?? 5432,
62
+ user: cfg?.user ?? 'postgres',
63
+ password: cfg?.password ?? 'postgres',
64
+ database: cfg?.database ?? 'postgres',
65
+ max: cfg?.max ?? 10,
66
+ idleTimeoutMillis: cfg?.idleTimeoutMillis ?? 30000,
67
+ connectionTimeoutMillis: cfg?.connectionTimeoutMillis ?? 5000,
68
+ statement_timeout: cfg?.statementTimeoutMillis ?? 30000,
69
+ query_timeout: cfg?.queryTimeoutMillis ?? 30000,
111
70
  };
112
71
  }
113
72
  this.pool = new pg_1.Pool(poolConfig);
114
73
  }
115
- PostgressMachineMemoryV1.prototype.close = function () {
116
- return __awaiter(this, void 0, void 0, function () {
117
- return __generator(this, function (_a) {
118
- switch (_a.label) {
119
- case 0: return [4 /*yield*/, this.pool.end()];
120
- case 1:
121
- _a.sent();
122
- return [2 /*return*/];
123
- }
124
- });
125
- });
126
- };
127
- PostgressMachineMemoryV1.prototype.delay = function (ms) {
128
- return __awaiter(this, void 0, void 0, function () {
129
- return __generator(this, function (_a) {
130
- return [2 /*return*/, new Promise(function (resolve) { return setTimeout(resolve, ms); })];
131
- });
74
+ async close() {
75
+ await this.pool.end();
76
+ }
77
+ async delay(ms) {
78
+ return new Promise((resolve) => setTimeout(resolve, ms));
79
+ }
80
+ async validateTableStructure() {
81
+ const client = await this.pool.connect();
82
+ try {
83
+ await Promise.all([
84
+ (0, schema_1.validateTable)(client, this.dbSchemaName, this.tables.state, 'state'),
85
+ (0, schema_1.validateTable)(client, this.dbSchemaName, this.tables.lock, 'lock'),
86
+ (0, schema_1.validateTable)(client, this.dbSchemaName, this.tables.hierarchy, 'hierarchy'),
87
+ ]);
88
+ }
89
+ finally {
90
+ client.release();
91
+ }
92
+ }
93
+ async otel({ name, fn }) {
94
+ if (!this.enableOtel) {
95
+ return await fn();
96
+ }
97
+ return await arvo_core_1.ArvoOpenTelemetry.getInstance().startActiveSpan({
98
+ name: name,
99
+ disableSpanManagement: true,
100
+ fn,
132
101
  });
133
- };
134
- PostgressMachineMemoryV1.prototype.validateTableStructure = function () {
135
- return __awaiter(this, void 0, void 0, function () {
136
- var client;
137
- return __generator(this, function (_a) {
138
- switch (_a.label) {
139
- case 0: return [4 /*yield*/, this.pool.connect()];
140
- case 1:
141
- client = _a.sent();
142
- _a.label = 2;
143
- case 2:
144
- _a.trys.push([2, , 4, 5]);
145
- return [4 /*yield*/, Promise.all([
146
- (0, schema_1.validateTable)(client, this.tables.state, 'state'),
147
- (0, schema_1.validateTable)(client, this.tables.lock, 'lock'),
148
- (0, schema_1.validateTable)(client, this.tables.hierarchy, 'hierarchy'),
149
- ])];
150
- case 3:
151
- _a.sent();
152
- return [3 /*break*/, 5];
153
- case 4:
154
- client.release();
155
- return [7 /*endfinally*/];
156
- case 5: return [2 /*return*/];
102
+ }
103
+ async read(id) {
104
+ return await this.otel({
105
+ name: 'PostgresMachineMemory.v1.read',
106
+ fn: async (span) => {
107
+ span?.setStatus({ code: api_1.SpanStatusCode.OK });
108
+ span?.setAttribute('subject', id);
109
+ const client = await this.pool.connect();
110
+ try {
111
+ const result = await client.query((0, pg_format_1.default)('SELECT data, version FROM %I.%I WHERE subject = $1', this.dbSchemaName, this.tables.state), [id]);
112
+ if (!result.rows.length) {
113
+ span?.setAttribute('available', 0);
114
+ return null;
115
+ }
116
+ span?.setAttribute('available', 1);
117
+ return {
118
+ ...(result.rows[0].data ?? {}),
119
+ __postgres_version_counter_data_$$__: result.rows[0].version,
120
+ };
157
121
  }
158
- });
159
- });
160
- };
161
- PostgressMachineMemoryV1.prototype.otel = function (_a) {
162
- return __awaiter(this, arguments, void 0, function (_b) {
163
- var name = _b.name, fn = _b.fn;
164
- return __generator(this, function (_c) {
165
- switch (_c.label) {
166
- case 0:
167
- if (!!this.enableOtel) return [3 /*break*/, 2];
168
- return [4 /*yield*/, fn()];
169
- case 1: return [2 /*return*/, _c.sent()];
170
- case 2: return [4 /*yield*/, arvo_core_1.ArvoOpenTelemetry.getInstance().startActiveSpan({
171
- name: name,
172
- disableSpanManagement: true,
173
- fn: fn,
174
- })];
175
- case 3: return [2 /*return*/, _c.sent()];
122
+ catch (error) {
123
+ span?.setStatus({
124
+ code: api_1.SpanStatusCode.ERROR,
125
+ message: error.message,
126
+ });
127
+ throw error;
176
128
  }
177
- });
178
- });
179
- };
180
- PostgressMachineMemoryV1.prototype.read = function (id) {
181
- return __awaiter(this, void 0, void 0, function () {
182
- var _this = this;
183
- return __generator(this, function (_a) {
184
- switch (_a.label) {
185
- case 0: return [4 /*yield*/, this.otel({
186
- name: 'PostgresMachineMemory.v1.read',
187
- fn: function (span) { return __awaiter(_this, void 0, void 0, function () {
188
- var client, result, error_1;
189
- var _a;
190
- return __generator(this, function (_b) {
191
- switch (_b.label) {
192
- case 0:
193
- span === null || span === void 0 ? void 0 : span.setStatus({ code: api_1.SpanStatusCode.OK });
194
- span === null || span === void 0 ? void 0 : span.setAttribute('subject', id);
195
- return [4 /*yield*/, this.pool.connect()];
196
- case 1:
197
- client = _b.sent();
198
- _b.label = 2;
199
- case 2:
200
- _b.trys.push([2, 4, 5, 6]);
201
- return [4 /*yield*/, client.query((0, pg_format_1.default)('SELECT data, version FROM %I WHERE subject = $1', this.tables.state), [id])];
202
- case 3:
203
- result = _b.sent();
204
- if (!result.rows.length) {
205
- span === null || span === void 0 ? void 0 : span.setAttribute('available', 0);
206
- return [2 /*return*/, null];
207
- }
208
- span === null || span === void 0 ? void 0 : span.setAttribute('available', 1);
209
- return [2 /*return*/, __assign(__assign({}, ((_a = result.rows[0].data) !== null && _a !== void 0 ? _a : {})), { __postgres_version_counter_data_$$__: result.rows[0].version })];
210
- case 4:
211
- error_1 = _b.sent();
212
- span === null || span === void 0 ? void 0 : span.setStatus({
213
- code: api_1.SpanStatusCode.ERROR,
214
- message: error_1.message,
215
- });
216
- throw error_1;
217
- case 5:
218
- client.release();
219
- span === null || span === void 0 ? void 0 : span.end();
220
- return [7 /*endfinally*/];
221
- case 6: return [2 /*return*/];
222
- }
223
- });
224
- }); },
225
- })];
226
- case 1: return [2 /*return*/, _a.sent()];
129
+ finally {
130
+ client.release();
131
+ span?.end();
227
132
  }
228
- });
133
+ },
229
134
  });
230
- };
231
- PostgressMachineMemoryV1.prototype.write = function (id_1, data_1, prevData_1, _a) {
232
- return __awaiter(this, arguments, void 0, function (id, data, prevData, _b) {
233
- var _this = this;
234
- var source = _b.source, initiator = _b.initiator;
235
- return __generator(this, function (_c) {
236
- switch (_c.label) {
237
- case 0: return [4 /*yield*/, this.otel({
238
- name: 'PostgresMachineMemory.v1.write',
239
- fn: function (span) { return __awaiter(_this, void 0, void 0, function () {
240
- var client, resolvedExectionStatus, resolvedParentSubject, resolvedInitiator, rootSubject, parentResult, error_2, currentVersion, newVersion, result, error, error_3;
241
- var _a, _b, _c, _d;
242
- return __generator(this, function (_e) {
243
- switch (_e.label) {
244
- case 0:
245
- span === null || span === void 0 ? void 0 : span.setStatus({ code: api_1.SpanStatusCode.OK });
246
- span === null || span === void 0 ? void 0 : span.setAttribute('subject', id);
247
- span === null || span === void 0 ? void 0 : span.setAttribute('isNew', prevData === null ? 1 : 0);
248
- return [4 /*yield*/, this.pool.connect()];
249
- case 1:
250
- client = _e.sent();
251
- resolvedExectionStatus = (_a = data.executionStatus) !== null && _a !== void 0 ? _a : 'unknown';
252
- _e.label = 2;
253
- case 2:
254
- _e.trys.push([2, 15, 16, 17]);
255
- if (!(prevData === null)) return [3 /*break*/, 13];
256
- _e.label = 3;
257
- case 3:
258
- _e.trys.push([3, 11, , 13]);
259
- return [4 /*yield*/, client.query('BEGIN')];
260
- case 4:
261
- _e.sent();
262
- resolvedParentSubject = (_b = data.parentSubject) !== null && _b !== void 0 ? _b : null;
263
- resolvedInitiator = arvo_event_handler_1.Materialized.isResolved(initiator) ? initiator.value : null;
264
- return [4 /*yield*/, client.query((0, pg_format_1.default)('INSERT INTO %I (subject, data, version, execution_status, parent_subject, initiator, source, created_at, updated_at) VALUES ($1, $2, 1, $3, $4, $5, $6, NOW(), NOW())', this.tables.state), [
265
- id,
266
- JSON.stringify(data),
267
- resolvedExectionStatus,
268
- resolvedParentSubject,
269
- resolvedInitiator,
270
- source,
271
- ])];
272
- case 5:
273
- _e.sent();
274
- rootSubject = void 0;
275
- if (!(resolvedParentSubject === null)) return [3 /*break*/, 6];
276
- rootSubject = id;
277
- return [3 /*break*/, 8];
278
- case 6: return [4 /*yield*/, client.query((0, pg_format_1.default)('SELECT root_subject FROM %I WHERE subject = $1', this.tables.hierarchy), [resolvedParentSubject])];
279
- case 7:
280
- parentResult = _e.sent();
281
- rootSubject = (_d = (_c = parentResult.rows[0]) === null || _c === void 0 ? void 0 : _c.root_subject) !== null && _d !== void 0 ? _d : id;
282
- _e.label = 8;
283
- case 8: return [4 /*yield*/, client.query((0, pg_format_1.default)('INSERT INTO %I (subject, parent_subject, root_subject, created_at) VALUES ($1, $2, $3, NOW())', this.tables.hierarchy), [id, resolvedParentSubject, rootSubject])];
284
- case 9:
285
- _e.sent();
286
- return [4 /*yield*/, client.query('COMMIT')];
287
- case 10:
288
- _e.sent();
289
- return [2 /*return*/];
290
- case 11:
291
- error_2 = _e.sent();
292
- return [4 /*yield*/, client.query('ROLLBACK')];
293
- case 12:
294
- _e.sent();
295
- span === null || span === void 0 ? void 0 : span.setStatus({
296
- code: api_1.SpanStatusCode.ERROR,
297
- message: error_2.message,
298
- });
299
- throw error_2;
300
- case 13:
301
- currentVersion = prevData.__postgres_version_counter_data_$$__;
302
- newVersion = currentVersion + 1;
303
- span === null || span === void 0 ? void 0 : span.setAttribute('version', newVersion);
304
- return [4 /*yield*/, client.query((0, pg_format_1.default)('UPDATE %I SET data = $1, version = $2, execution_status = $3, updated_at = NOW() WHERE subject = $4 AND version = $5', this.tables.state), [JSON.stringify(data), newVersion, resolvedExectionStatus, id, currentVersion])];
305
- case 14:
306
- result = _e.sent();
307
- if (result.rowCount === 0) {
308
- error = new Error("Data is corrupted due to version mismatch for subject '".concat(id, "'. Expected version ").concat(currentVersion, " but state has been modified."));
309
- span === null || span === void 0 ? void 0 : span.setStatus({
310
- code: api_1.SpanStatusCode.ERROR,
311
- message: error.message,
312
- });
313
- throw error;
314
- }
315
- return [3 /*break*/, 17];
316
- case 15:
317
- error_3 = _e.sent();
318
- span === null || span === void 0 ? void 0 : span.setStatus({
319
- code: api_1.SpanStatusCode.ERROR,
320
- message: error_3.message,
321
- });
322
- throw error_3;
323
- case 16:
324
- client.release();
325
- span === null || span === void 0 ? void 0 : span.end();
326
- return [7 /*endfinally*/];
327
- case 17: return [2 /*return*/];
328
- }
329
- });
330
- }); },
331
- })];
332
- case 1: return [2 /*return*/, _c.sent()];
135
+ }
136
+ async write(id, data, prevData, { source, initiator }) {
137
+ return await this.otel({
138
+ name: 'PostgresMachineMemory.v1.write',
139
+ fn: async (span) => {
140
+ span?.setStatus({ code: api_1.SpanStatusCode.OK });
141
+ span?.setAttribute('subject', id);
142
+ span?.setAttribute('isNew', prevData === null ? 1 : 0);
143
+ const client = await this.pool.connect();
144
+ const resolvedExectionStatus = data.executionStatus ?? 'unknown';
145
+ try {
146
+ if (prevData === null) {
147
+ try {
148
+ await client.query('BEGIN');
149
+ const resolvedParentSubject = data.parentSubject ?? null;
150
+ const resolvedInitiator = arvo_event_handler_1.Materialized.isResolved(initiator) ? initiator.value : null;
151
+ await client.query((0, pg_format_1.default)('INSERT INTO %I.%I (subject, data, version, execution_status, parent_subject, initiator, source, created_at, updated_at) VALUES ($1, $2, 1, $3, $4, $5, $6, NOW(), NOW())', this.dbSchemaName, this.tables.state), [
152
+ id,
153
+ JSON.stringify(data),
154
+ resolvedExectionStatus,
155
+ resolvedParentSubject,
156
+ resolvedInitiator,
157
+ source,
158
+ ]);
159
+ let rootSubject;
160
+ if (resolvedParentSubject === null) {
161
+ rootSubject = id;
162
+ }
163
+ else {
164
+ const parentResult = await client.query((0, pg_format_1.default)('SELECT root_subject FROM %I.%I WHERE subject = $1', this.dbSchemaName, this.tables.hierarchy), [resolvedParentSubject]);
165
+ rootSubject = parentResult.rows[0]?.root_subject ?? id;
166
+ }
167
+ await client.query((0, pg_format_1.default)('INSERT INTO %I.%I (subject, parent_subject, root_subject, created_at) VALUES ($1, $2, $3, NOW())', this.dbSchemaName, this.tables.hierarchy), [id, resolvedParentSubject, rootSubject]);
168
+ await client.query('COMMIT');
169
+ return;
170
+ }
171
+ catch (error) {
172
+ await client.query('ROLLBACK');
173
+ span?.setStatus({
174
+ code: api_1.SpanStatusCode.ERROR,
175
+ message: error.message,
176
+ });
177
+ throw error;
178
+ }
179
+ }
180
+ const currentVersion = prevData.__postgres_version_counter_data_$$__;
181
+ const newVersion = currentVersion + 1;
182
+ span?.setAttribute('version', newVersion);
183
+ const result = await client.query((0, pg_format_1.default)('UPDATE %I.%I SET data = $1, version = $2, execution_status = $3, updated_at = NOW() WHERE subject = $4 AND version = $5', this.dbSchemaName, this.tables.state), [JSON.stringify(data), newVersion, resolvedExectionStatus, id, currentVersion]);
184
+ if (result.rowCount === 0) {
185
+ const error = new Error(`Data is corrupted due to version mismatch for subject '${id}'. Expected version ${currentVersion} but state has been modified.`);
186
+ span?.setStatus({
187
+ code: api_1.SpanStatusCode.ERROR,
188
+ message: error.message,
189
+ });
190
+ throw error;
191
+ }
192
+ }
193
+ catch (error) {
194
+ span?.setStatus({
195
+ code: api_1.SpanStatusCode.ERROR,
196
+ message: error.message,
197
+ });
198
+ throw error;
333
199
  }
334
- });
200
+ finally {
201
+ client.release();
202
+ span?.end();
203
+ }
204
+ },
335
205
  });
336
- };
337
- PostgressMachineMemoryV1.prototype.lock = function (id) {
338
- return __awaiter(this, void 0, void 0, function () {
339
- var _this = this;
340
- return __generator(this, function (_a) {
341
- switch (_a.label) {
342
- case 0: return [4 /*yield*/, this.otel({
343
- name: 'PostgresMachineMemory.v1.lock',
344
- fn: function (span) { return __awaiter(_this, void 0, void 0, function () {
345
- var client, attempt, result, delayMs, error_4, error_5;
346
- return __generator(this, function (_a) {
347
- switch (_a.label) {
348
- case 0:
349
- span === null || span === void 0 ? void 0 : span.setStatus({ code: api_1.SpanStatusCode.OK });
350
- span === null || span === void 0 ? void 0 : span.setAttribute('subject', id);
351
- return [4 /*yield*/, this.pool.connect()];
352
- case 1:
353
- client = _a.sent();
354
- _a.label = 2;
355
- case 2:
356
- _a.trys.push([2, 11, 12, 13]);
357
- attempt = 0;
358
- _a.label = 3;
359
- case 3:
360
- if (!(attempt <= this.lockConfig.maxRetries)) return [3 /*break*/, 10];
361
- _a.label = 4;
362
- case 4:
363
- _a.trys.push([4, 8, , 9]);
364
- return [4 /*yield*/, client.query((0, pg_format_1.default)("WITH arvo_lock_time AS (SELECT NOW() as now)\n INSERT INTO %I (subject, locked_at, expires_at, created_at)\n SELECT $1, now, now + ($2 || ' milliseconds')::INTERVAL, now FROM arvo_lock_time\n ON CONFLICT (subject)\n DO UPDATE SET\n locked_at = (SELECT now FROM arvo_lock_time),\n expires_at = (SELECT now FROM arvo_lock_time) + ($2 || ' milliseconds')::INTERVAL\n WHERE %I.expires_at < (SELECT now FROM arvo_lock_time)\n RETURNING subject", this.tables.lock, this.tables.lock), [id, this.lockConfig.ttlMs])];
365
- case 5:
366
- result = _a.sent();
367
- if (result.rowCount && result.rowCount > 0) {
368
- span === null || span === void 0 ? void 0 : span.setAttribute('acquired', 1);
369
- span === null || span === void 0 ? void 0 : span.setAttribute('attempts', attempt + 1);
370
- return [2 /*return*/, true];
371
- }
372
- if (!(attempt < this.lockConfig.maxRetries)) return [3 /*break*/, 7];
373
- delayMs = this.lockConfig.initialDelayMs * Math.pow(this.lockConfig.backoffExponent, attempt);
374
- return [4 /*yield*/, this.delay(delayMs)];
375
- case 6:
376
- _a.sent();
377
- _a.label = 7;
378
- case 7: return [3 /*break*/, 9];
379
- case 8:
380
- error_4 = _a.sent();
381
- span === null || span === void 0 ? void 0 : span.setStatus({
382
- code: api_1.SpanStatusCode.ERROR,
383
- message: error_4.message,
384
- });
385
- throw error_4;
386
- case 9:
387
- attempt++;
388
- return [3 /*break*/, 3];
389
- case 10:
390
- span === null || span === void 0 ? void 0 : span.setAttribute('acquired', 0);
391
- span === null || span === void 0 ? void 0 : span.setAttribute('attempts', this.lockConfig.maxRetries + 1);
392
- return [2 /*return*/, false];
393
- case 11:
394
- error_5 = _a.sent();
395
- span === null || span === void 0 ? void 0 : span.setStatus({
396
- code: api_1.SpanStatusCode.ERROR,
397
- message: error_5.message,
398
- });
399
- throw error_5;
400
- case 12:
401
- client.release();
402
- span === null || span === void 0 ? void 0 : span.end();
403
- return [7 /*endfinally*/];
404
- case 13: return [2 /*return*/];
405
- }
406
- });
407
- }); },
408
- })];
409
- case 1: return [2 /*return*/, _a.sent()];
206
+ }
207
+ async lock(id) {
208
+ return await this.otel({
209
+ name: 'PostgresMachineMemory.v1.lock',
210
+ fn: async (span) => {
211
+ span?.setStatus({ code: api_1.SpanStatusCode.OK });
212
+ span?.setAttribute('subject', id);
213
+ const client = await this.pool.connect();
214
+ try {
215
+ for (let attempt = 0; attempt <= this.lockConfig.maxRetries; attempt++) {
216
+ try {
217
+ const result = await client.query((0, pg_format_1.default)(`WITH arvo_lock_time AS (SELECT NOW() as now)
218
+ INSERT INTO %I.%I (subject, locked_at, expires_at, created_at)
219
+ SELECT $1, now, now + ($2 || ' milliseconds')::INTERVAL, now FROM arvo_lock_time
220
+ ON CONFLICT (subject)
221
+ DO UPDATE SET
222
+ locked_at = (SELECT now FROM arvo_lock_time),
223
+ expires_at = (SELECT now FROM arvo_lock_time) + ($2 || ' milliseconds')::INTERVAL
224
+ WHERE %I.%I.expires_at < (SELECT now FROM arvo_lock_time)
225
+ RETURNING subject`, this.dbSchemaName, this.tables.lock, this.dbSchemaName, this.tables.lock), [id, this.lockConfig.ttlMs]);
226
+ if (result.rowCount && result.rowCount > 0) {
227
+ span?.setAttribute('acquired', 1);
228
+ span?.setAttribute('attempts', attempt + 1);
229
+ return true;
230
+ }
231
+ if (attempt < this.lockConfig.maxRetries) {
232
+ const delayMs = this.lockConfig.initialDelayMs * this.lockConfig.backoffExponent ** attempt;
233
+ await this.delay(delayMs);
234
+ }
235
+ }
236
+ catch (error) {
237
+ span?.setStatus({
238
+ code: api_1.SpanStatusCode.ERROR,
239
+ message: error.message,
240
+ });
241
+ throw error;
242
+ }
243
+ }
244
+ span?.setAttribute('acquired', 0);
245
+ span?.setAttribute('attempts', this.lockConfig.maxRetries + 1);
246
+ return false;
247
+ }
248
+ catch (error) {
249
+ span?.setStatus({
250
+ code: api_1.SpanStatusCode.ERROR,
251
+ message: error.message,
252
+ });
253
+ throw error;
410
254
  }
411
- });
255
+ finally {
256
+ client.release();
257
+ span?.end();
258
+ }
259
+ },
412
260
  });
413
- };
414
- PostgressMachineMemoryV1.prototype.unlock = function (id) {
415
- return __awaiter(this, void 0, void 0, function () {
416
- var _this = this;
417
- return __generator(this, function (_a) {
418
- switch (_a.label) {
419
- case 0: return [4 /*yield*/, this.otel({
420
- name: 'PostgresMachineMemory.v1.unlock',
421
- fn: function (span) { return __awaiter(_this, void 0, void 0, function () {
422
- var client, error_6;
423
- return __generator(this, function (_a) {
424
- switch (_a.label) {
425
- case 0:
426
- span === null || span === void 0 ? void 0 : span.setStatus({ code: api_1.SpanStatusCode.OK });
427
- span === null || span === void 0 ? void 0 : span.setAttribute('subject', id);
428
- return [4 /*yield*/, this.pool.connect()];
429
- case 1:
430
- client = _a.sent();
431
- _a.label = 2;
432
- case 2:
433
- _a.trys.push([2, 4, 5, 6]);
434
- return [4 /*yield*/, client.query((0, pg_format_1.default)('DELETE FROM %I WHERE subject = $1', this.tables.lock), [id])];
435
- case 3:
436
- _a.sent();
437
- return [2 /*return*/, true];
438
- case 4:
439
- error_6 = _a.sent();
440
- span === null || span === void 0 ? void 0 : span.setStatus({
441
- code: api_1.SpanStatusCode.ERROR,
442
- message: error_6.message,
443
- });
444
- return [2 /*return*/, true];
445
- case 5:
446
- client.release();
447
- span === null || span === void 0 ? void 0 : span.end();
448
- return [7 /*endfinally*/];
449
- case 6: return [2 /*return*/];
450
- }
451
- });
452
- }); },
453
- })];
454
- case 1: return [2 /*return*/, _a.sent()];
261
+ }
262
+ async unlock(id) {
263
+ return await this.otel({
264
+ name: 'PostgresMachineMemory.v1.unlock',
265
+ fn: async (span) => {
266
+ span?.setStatus({ code: api_1.SpanStatusCode.OK });
267
+ span?.setAttribute('subject', id);
268
+ const client = await this.pool.connect();
269
+ try {
270
+ await client.query((0, pg_format_1.default)('DELETE FROM %I.%I WHERE subject = $1', this.dbSchemaName, this.tables.lock), [id]);
271
+ return true;
455
272
  }
456
- });
273
+ catch (error) {
274
+ span?.setStatus({
275
+ code: api_1.SpanStatusCode.ERROR,
276
+ message: error.message,
277
+ });
278
+ return true;
279
+ }
280
+ finally {
281
+ client.release();
282
+ span?.end();
283
+ }
284
+ },
457
285
  });
458
- };
459
- PostgressMachineMemoryV1.prototype.cleanup = function (id) {
460
- return __awaiter(this, void 0, void 0, function () {
461
- var _this = this;
462
- return __generator(this, function (_a) {
463
- switch (_a.label) {
464
- case 0: return [4 /*yield*/, this.otel({
465
- name: 'PostgresMachineMemory.v1.cleanup',
466
- fn: function (span) { return __awaiter(_this, void 0, void 0, function () {
467
- var client, error_7;
468
- return __generator(this, function (_a) {
469
- switch (_a.label) {
470
- case 0:
471
- span === null || span === void 0 ? void 0 : span.setStatus({ code: api_1.SpanStatusCode.OK });
472
- span === null || span === void 0 ? void 0 : span.setAttribute('subject', id);
473
- if (!this.enableCleanup) {
474
- span === null || span === void 0 ? void 0 : span.setAttribute('skipped', 1);
475
- span === null || span === void 0 ? void 0 : span.end();
476
- return [2 /*return*/];
477
- }
478
- span === null || span === void 0 ? void 0 : span.setAttribute('skipped', 0);
479
- return [4 /*yield*/, this.pool.connect()];
480
- case 1:
481
- client = _a.sent();
482
- _a.label = 2;
483
- case 2:
484
- _a.trys.push([2, 6, 8, 9]);
485
- return [4 /*yield*/, client.query('BEGIN')];
486
- case 3:
487
- _a.sent();
488
- return [4 /*yield*/, Promise.all([
489
- client.query((0, pg_format_1.default)('DELETE FROM %I WHERE subject = $1', this.tables.state), [id]),
490
- client.query((0, pg_format_1.default)('DELETE FROM %I WHERE subject = $1', this.tables.lock), [id]),
491
- client.query((0, pg_format_1.default)('DELETE FROM %I WHERE subject = $1', this.tables.hierarchy), [id]),
492
- ])];
493
- case 4:
494
- _a.sent();
495
- return [4 /*yield*/, client.query('COMMIT')];
496
- case 5:
497
- _a.sent();
498
- return [3 /*break*/, 9];
499
- case 6:
500
- error_7 = _a.sent();
501
- return [4 /*yield*/, client.query('ROLLBACK')];
502
- case 7:
503
- _a.sent();
504
- span === null || span === void 0 ? void 0 : span.setStatus({
505
- code: api_1.SpanStatusCode.ERROR,
506
- message: error_7.message,
507
- });
508
- throw error_7;
509
- case 8:
510
- client.release();
511
- span === null || span === void 0 ? void 0 : span.end();
512
- return [7 /*endfinally*/];
513
- case 9: return [2 /*return*/];
514
- }
515
- });
516
- }); },
517
- })];
518
- case 1: return [2 /*return*/, _a.sent()];
286
+ }
287
+ async cleanup(id) {
288
+ return await this.otel({
289
+ name: 'PostgresMachineMemory.v1.cleanup',
290
+ fn: async (span) => {
291
+ span?.setStatus({ code: api_1.SpanStatusCode.OK });
292
+ span?.setAttribute('subject', id);
293
+ if (!this.enableCleanup) {
294
+ span?.setAttribute('skipped', 1);
295
+ span?.end();
296
+ return;
297
+ }
298
+ span?.setAttribute('skipped', 0);
299
+ const client = await this.pool.connect();
300
+ try {
301
+ await client.query('BEGIN');
302
+ await Promise.all([
303
+ client.query((0, pg_format_1.default)('DELETE FROM %I.%I WHERE subject = $1', this.dbSchemaName, this.tables.state), [id]),
304
+ client.query((0, pg_format_1.default)('DELETE FROM %I.%I WHERE subject = $1', this.dbSchemaName, this.tables.lock), [id]),
305
+ client.query((0, pg_format_1.default)('DELETE FROM %I.%I WHERE subject = $1', this.dbSchemaName, this.tables.hierarchy), [id]),
306
+ ]);
307
+ await client.query('COMMIT');
519
308
  }
520
- });
309
+ catch (error) {
310
+ await client.query('ROLLBACK');
311
+ span?.setStatus({
312
+ code: api_1.SpanStatusCode.ERROR,
313
+ message: error.message,
314
+ });
315
+ throw error;
316
+ }
317
+ finally {
318
+ client.release();
319
+ span?.end();
320
+ }
321
+ },
521
322
  });
522
- };
323
+ }
523
324
  /**
524
325
  * Retrieves all child workflow subjects belonging to a specific root workflow.
525
326
  *
@@ -536,55 +337,35 @@ var PostgressMachineMemoryV1 = /** @class */ (function () {
536
337
  * console.log(`Found ${children.length} child workflows subjects`);
537
338
  * ```
538
339
  */
539
- PostgressMachineMemoryV1.prototype.getSubjectsByRoot = function (rootSubject) {
540
- return __awaiter(this, void 0, void 0, function () {
541
- var _this = this;
542
- return __generator(this, function (_a) {
543
- switch (_a.label) {
544
- case 0: return [4 /*yield*/, this.otel({
545
- name: 'PostgresMachineMemory.v1.getSubjectsByRoot',
546
- fn: function (span) { return __awaiter(_this, void 0, void 0, function () {
547
- var client, result, subjects, error_8;
548
- return __generator(this, function (_a) {
549
- switch (_a.label) {
550
- case 0:
551
- span === null || span === void 0 ? void 0 : span.setStatus({ code: api_1.SpanStatusCode.OK });
552
- span === null || span === void 0 ? void 0 : span.setAttribute('rootSubject', rootSubject);
553
- return [4 /*yield*/, this.pool.connect()];
554
- case 1:
555
- client = _a.sent();
556
- _a.label = 2;
557
- case 2:
558
- _a.trys.push([2, 4, 5, 6]);
559
- return [4 /*yield*/, client.query((0, pg_format_1.default)('SELECT subject FROM %I WHERE root_subject = $1', this.tables.hierarchy), [rootSubject])];
560
- case 3:
561
- result = _a.sent();
562
- subjects = result.rows
563
- .map(function (row) { return row.subject; })
564
- .filter(function (item) { return item !== rootSubject; });
565
- span === null || span === void 0 ? void 0 : span.setAttribute('count', subjects.length);
566
- return [2 /*return*/, subjects];
567
- case 4:
568
- error_8 = _a.sent();
569
- span === null || span === void 0 ? void 0 : span.setStatus({
570
- code: api_1.SpanStatusCode.ERROR,
571
- message: error_8.message,
572
- });
573
- throw error_8;
574
- case 5:
575
- client.release();
576
- span === null || span === void 0 ? void 0 : span.end();
577
- return [7 /*endfinally*/];
578
- case 6: return [2 /*return*/];
579
- }
580
- });
581
- }); },
582
- })];
583
- case 1: return [2 /*return*/, _a.sent()];
340
+ async getSubjectsByRoot(rootSubject) {
341
+ return await this.otel({
342
+ name: 'PostgresMachineMemory.v1.getSubjectsByRoot',
343
+ fn: async (span) => {
344
+ span?.setStatus({ code: api_1.SpanStatusCode.OK });
345
+ span?.setAttribute('rootSubject', rootSubject);
346
+ const client = await this.pool.connect();
347
+ try {
348
+ const result = await client.query((0, pg_format_1.default)('SELECT subject FROM %I.%I WHERE root_subject = $1', this.dbSchemaName, this.tables.hierarchy), [rootSubject]);
349
+ const subjects = result.rows
350
+ .map((row) => row.subject)
351
+ .filter((item) => item !== rootSubject);
352
+ span?.setAttribute('count', subjects.length);
353
+ return subjects;
354
+ }
355
+ catch (error) {
356
+ span?.setStatus({
357
+ code: api_1.SpanStatusCode.ERROR,
358
+ message: error.message,
359
+ });
360
+ throw error;
361
+ }
362
+ finally {
363
+ client.release();
364
+ span?.end();
584
365
  }
585
- });
366
+ },
586
367
  });
587
- };
368
+ }
588
369
  /**
589
370
  * Retrieves the root workflow subject for a given workflow instance.
590
371
  *
@@ -612,60 +393,39 @@ var PostgressMachineMemoryV1 = /** @class */ (function () {
612
393
  * }
613
394
  * ```
614
395
  */
615
- PostgressMachineMemoryV1.prototype.getRootSubject = function (subject) {
616
- return __awaiter(this, void 0, void 0, function () {
617
- var _this = this;
618
- return __generator(this, function (_a) {
619
- switch (_a.label) {
620
- case 0: return [4 /*yield*/, this.otel({
621
- name: 'PostgresMachineMemory.v1.getRootSubject',
622
- fn: function (span) { return __awaiter(_this, void 0, void 0, function () {
623
- var client, result, rootSubject, error_9;
624
- return __generator(this, function (_a) {
625
- switch (_a.label) {
626
- case 0:
627
- span === null || span === void 0 ? void 0 : span.setStatus({ code: api_1.SpanStatusCode.OK });
628
- span === null || span === void 0 ? void 0 : span.setAttribute('subject', subject);
629
- return [4 /*yield*/, this.pool.connect()];
630
- case 1:
631
- client = _a.sent();
632
- _a.label = 2;
633
- case 2:
634
- _a.trys.push([2, 4, 5, 6]);
635
- return [4 /*yield*/, client.query((0, pg_format_1.default)('SELECT root_subject FROM %I WHERE subject = $1', this.tables.hierarchy), [subject])];
636
- case 3:
637
- result = _a.sent();
638
- if (!result.rows.length) {
639
- span === null || span === void 0 ? void 0 : span.setAttribute('found', 0);
640
- return [2 /*return*/, null];
641
- }
642
- rootSubject = result.rows[0].root_subject;
643
- span === null || span === void 0 ? void 0 : span.setAttribute('found', 1);
644
- span === null || span === void 0 ? void 0 : span.setAttribute('isRoot', 0);
645
- span === null || span === void 0 ? void 0 : span.setAttribute('rootSubject', rootSubject);
646
- return [2 /*return*/, rootSubject];
647
- case 4:
648
- error_9 = _a.sent();
649
- span === null || span === void 0 ? void 0 : span.setStatus({
650
- code: api_1.SpanStatusCode.ERROR,
651
- message: error_9.message,
652
- });
653
- throw error_9;
654
- case 5:
655
- client.release();
656
- span === null || span === void 0 ? void 0 : span.end();
657
- return [7 /*endfinally*/];
658
- case 6: return [2 /*return*/];
659
- }
660
- });
661
- }); },
662
- })];
663
- case 1: return [2 /*return*/, _a.sent()];
396
+ async getRootSubject(subject) {
397
+ return await this.otel({
398
+ name: 'PostgresMachineMemory.v1.getRootSubject',
399
+ fn: async (span) => {
400
+ span?.setStatus({ code: api_1.SpanStatusCode.OK });
401
+ span?.setAttribute('subject', subject);
402
+ const client = await this.pool.connect();
403
+ try {
404
+ const result = await client.query((0, pg_format_1.default)('SELECT root_subject FROM %I.%I WHERE subject = $1', this.dbSchemaName, this.tables.hierarchy), [subject]);
405
+ if (!result.rows.length) {
406
+ span?.setAttribute('found', 0);
407
+ return null;
408
+ }
409
+ const rootSubject = result.rows[0].root_subject;
410
+ span?.setAttribute('found', 1);
411
+ span?.setAttribute('isRoot', 0);
412
+ span?.setAttribute('rootSubject', rootSubject);
413
+ return rootSubject;
414
+ }
415
+ catch (error) {
416
+ span?.setStatus({
417
+ code: api_1.SpanStatusCode.ERROR,
418
+ message: error.message,
419
+ });
420
+ throw error;
664
421
  }
665
- });
422
+ finally {
423
+ client.release();
424
+ span?.end();
425
+ }
426
+ },
666
427
  });
667
- };
668
- return PostgressMachineMemoryV1;
669
- }());
428
+ }
429
+ }
670
430
  exports.PostgressMachineMemoryV1 = PostgressMachineMemoryV1;
671
431
  //# sourceMappingURL=index.js.map