node-cqrs 1.2.0-beta.1 → 1.3.0-alpha.0
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 +5 -17
- package/README.md +29 -9
- package/dist/cjs/postgresql/AbstractPostgresqlAccessor.js +83 -0
- package/dist/cjs/postgresql/AbstractPostgresqlAccessor.js.map +1 -0
- package/dist/cjs/postgresql/AbstractPostgresqlObjectProjection.js +36 -0
- package/dist/cjs/postgresql/AbstractPostgresqlObjectProjection.js.map +1 -0
- package/dist/cjs/postgresql/AbstractPostgresqlView.js +53 -0
- package/dist/cjs/postgresql/AbstractPostgresqlView.js.map +1 -0
- package/dist/cjs/postgresql/IContainer.js +3 -0
- package/dist/cjs/postgresql/IContainer.js.map +1 -0
- package/dist/cjs/postgresql/PostgresqlConnection.js +3 -0
- package/dist/cjs/postgresql/PostgresqlConnection.js.map +1 -0
- package/dist/cjs/postgresql/PostgresqlEventLocker.js +127 -0
- package/dist/cjs/postgresql/PostgresqlEventLocker.js.map +1 -0
- package/dist/cjs/postgresql/PostgresqlEventStorage.js +315 -0
- package/dist/cjs/postgresql/PostgresqlEventStorage.js.map +1 -0
- package/dist/cjs/postgresql/PostgresqlObjectStorage.js +137 -0
- package/dist/cjs/postgresql/PostgresqlObjectStorage.js.map +1 -0
- package/dist/cjs/postgresql/PostgresqlObjectView.js +46 -0
- package/dist/cjs/postgresql/PostgresqlObjectView.js.map +1 -0
- package/dist/cjs/postgresql/PostgresqlProjectionDataParams.js +3 -0
- package/dist/cjs/postgresql/PostgresqlProjectionDataParams.js.map +1 -0
- package/dist/cjs/postgresql/PostgresqlViewLocker.js +151 -0
- package/dist/cjs/postgresql/PostgresqlViewLocker.js.map +1 -0
- package/dist/cjs/postgresql/index.js +29 -0
- package/dist/cjs/postgresql/index.js.map +1 -0
- package/dist/cjs/postgresql/utils/getEventId.js +14 -0
- package/dist/cjs/postgresql/utils/getEventId.js.map +1 -0
- package/dist/cjs/postgresql/utils/index.js +19 -0
- package/dist/cjs/postgresql/utils/index.js.map +1 -0
- package/dist/cjs/postgresql/utils/quoteIdentifier.js +14 -0
- package/dist/cjs/postgresql/utils/quoteIdentifier.js.map +1 -0
- package/dist/cjs/sqlite/SqliteEventStorage.js +66 -36
- package/dist/cjs/sqlite/SqliteEventStorage.js.map +1 -1
- package/dist/esm/postgresql/AbstractPostgresqlAccessor.js +79 -0
- package/dist/esm/postgresql/AbstractPostgresqlAccessor.js.map +1 -0
- package/dist/esm/postgresql/AbstractPostgresqlObjectProjection.js +32 -0
- package/dist/esm/postgresql/AbstractPostgresqlObjectProjection.js.map +1 -0
- package/dist/esm/postgresql/AbstractPostgresqlView.js +49 -0
- package/dist/esm/postgresql/AbstractPostgresqlView.js.map +1 -0
- package/dist/esm/postgresql/IContainer.js +2 -0
- package/dist/esm/postgresql/IContainer.js.map +1 -0
- package/dist/esm/postgresql/PostgresqlConnection.js +2 -0
- package/dist/esm/postgresql/PostgresqlConnection.js.map +1 -0
- package/dist/esm/postgresql/PostgresqlEventLocker.js +123 -0
- package/dist/esm/postgresql/PostgresqlEventLocker.js.map +1 -0
- package/dist/esm/postgresql/PostgresqlEventStorage.js +311 -0
- package/dist/esm/postgresql/PostgresqlEventStorage.js.map +1 -0
- package/dist/esm/postgresql/PostgresqlObjectStorage.js +133 -0
- package/dist/esm/postgresql/PostgresqlObjectStorage.js.map +1 -0
- package/dist/esm/postgresql/PostgresqlObjectView.js +42 -0
- package/dist/esm/postgresql/PostgresqlObjectView.js.map +1 -0
- package/dist/esm/postgresql/PostgresqlProjectionDataParams.js +2 -0
- package/dist/esm/postgresql/PostgresqlProjectionDataParams.js.map +1 -0
- package/dist/esm/postgresql/PostgresqlViewLocker.js +147 -0
- package/dist/esm/postgresql/PostgresqlViewLocker.js.map +1 -0
- package/dist/esm/postgresql/index.js +13 -0
- package/dist/esm/postgresql/index.js.map +1 -0
- package/dist/esm/postgresql/utils/getEventId.js +10 -0
- package/dist/esm/postgresql/utils/getEventId.js.map +1 -0
- package/dist/esm/postgresql/utils/index.js +3 -0
- package/dist/esm/postgresql/utils/index.js.map +1 -0
- package/dist/esm/postgresql/utils/quoteIdentifier.js +11 -0
- package/dist/esm/postgresql/utils/quoteIdentifier.js.map +1 -0
- package/dist/esm/sqlite/SqliteEventStorage.js +66 -36
- package/dist/esm/sqlite/SqliteEventStorage.js.map +1 -1
- package/dist/types/postgresql/AbstractPostgresqlAccessor.d.ts +29 -0
- package/dist/types/postgresql/AbstractPostgresqlObjectProjection.d.ts +12 -0
- package/dist/types/postgresql/AbstractPostgresqlView.d.ts +23 -0
- package/dist/types/postgresql/IContainer.d.ts +12 -0
- package/dist/types/postgresql/PostgresqlConnection.d.ts +7 -0
- package/dist/types/postgresql/PostgresqlEventLocker.d.ts +39 -0
- package/dist/types/postgresql/PostgresqlEventStorage.d.ts +23 -0
- package/dist/types/postgresql/PostgresqlObjectStorage.d.ts +29 -0
- package/dist/types/postgresql/PostgresqlObjectView.d.ts +19 -0
- package/dist/types/postgresql/PostgresqlProjectionDataParams.d.ts +14 -0
- package/dist/types/postgresql/PostgresqlViewLocker.d.ts +41 -0
- package/dist/types/postgresql/index.d.ts +12 -0
- package/dist/types/postgresql/utils/getEventId.d.ts +5 -0
- package/dist/types/postgresql/utils/index.d.ts +2 -0
- package/dist/types/postgresql/utils/quoteIdentifier.d.ts +1 -0
- package/package.json +20 -5
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresqlEventStorage = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const index_ts_1 = require("../errors/index.js");
|
|
6
|
+
const index_ts_2 = require("../utils/index.js");
|
|
7
|
+
const AbstractPostgresqlAccessor_ts_1 = require("./AbstractPostgresqlAccessor.js");
|
|
8
|
+
const index_ts_3 = require("./utils/index.js");
|
|
9
|
+
function extractMeta(envelope) {
|
|
10
|
+
const { event: _event, ignoreConcurrencyError: _ignore, ...rest } = envelope;
|
|
11
|
+
if (Object.keys(rest).length === 0)
|
|
12
|
+
return null;
|
|
13
|
+
return rest;
|
|
14
|
+
}
|
|
15
|
+
function parseJson(value) {
|
|
16
|
+
if (typeof value !== 'string')
|
|
17
|
+
return value;
|
|
18
|
+
return JSON.parse(value);
|
|
19
|
+
}
|
|
20
|
+
function indexPrefix(tableName) {
|
|
21
|
+
return tableName.replaceAll('"', '').replaceAll('.', '_');
|
|
22
|
+
}
|
|
23
|
+
function reconstructEvent(row) {
|
|
24
|
+
const data = parseJson(row.data);
|
|
25
|
+
const event = {
|
|
26
|
+
id: row.id,
|
|
27
|
+
...data
|
|
28
|
+
};
|
|
29
|
+
if (row.saga_origins)
|
|
30
|
+
event.sagaOrigins = parseJson(row.saga_origins);
|
|
31
|
+
return event;
|
|
32
|
+
}
|
|
33
|
+
class PostgresqlEventStorage extends AbstractPostgresqlAccessor_ts_1.AbstractPostgresqlAccessor {
|
|
34
|
+
static EVENTS_TABLE = 'tbl_events';
|
|
35
|
+
static EVENT_SAGAS_TABLE = 'tbl_event_sagas';
|
|
36
|
+
#eventsTableName;
|
|
37
|
+
#eventSagasTableName;
|
|
38
|
+
#aggregateVersionIndexName;
|
|
39
|
+
constructor({ postgresqlEventStorageConfig, viewModelPostgresqlDb, viewModelPostgresqlDbFactory }) {
|
|
40
|
+
super({ viewModelPostgresqlDb, viewModelPostgresqlDbFactory });
|
|
41
|
+
const eventsTableName = postgresqlEventStorageConfig?.eventsTableName ?? PostgresqlEventStorage.EVENTS_TABLE;
|
|
42
|
+
const eventSagasTableName = postgresqlEventStorageConfig?.eventSagasTableName ??
|
|
43
|
+
PostgresqlEventStorage.EVENT_SAGAS_TABLE;
|
|
44
|
+
(0, index_ts_2.assertString)(eventsTableName, 'postgresqlEventStorageConfig.eventsTableName');
|
|
45
|
+
(0, index_ts_2.assertString)(eventSagasTableName, 'postgresqlEventStorageConfig.eventSagasTableName');
|
|
46
|
+
this.#eventsTableName = (0, index_ts_3.quoteIdentifier)(eventsTableName);
|
|
47
|
+
this.#eventSagasTableName = (0, index_ts_3.quoteIdentifier)(eventSagasTableName);
|
|
48
|
+
this.#aggregateVersionIndexName = `${indexPrefix(this.#eventsTableName)}_aggregate_version_unique_idx`;
|
|
49
|
+
}
|
|
50
|
+
async initialize(db) {
|
|
51
|
+
await db.query(`
|
|
52
|
+
CREATE TABLE IF NOT EXISTS ${this.#eventsTableName} (
|
|
53
|
+
position BIGSERIAL PRIMARY KEY,
|
|
54
|
+
id TEXT NOT NULL UNIQUE,
|
|
55
|
+
aggregate_id TEXT,
|
|
56
|
+
aggregate_version INTEGER,
|
|
57
|
+
type TEXT NOT NULL,
|
|
58
|
+
data JSONB NOT NULL,
|
|
59
|
+
meta JSONB,
|
|
60
|
+
check_concurrency BOOLEAN NOT NULL DEFAULT TRUE
|
|
61
|
+
)
|
|
62
|
+
`);
|
|
63
|
+
await db.query(`
|
|
64
|
+
CREATE TABLE IF NOT EXISTS ${this.#eventSagasTableName} (
|
|
65
|
+
saga_descriptor TEXT NOT NULL,
|
|
66
|
+
origin_id TEXT NOT NULL,
|
|
67
|
+
event_id TEXT NOT NULL,
|
|
68
|
+
PRIMARY KEY (saga_descriptor, origin_id, event_id),
|
|
69
|
+
FOREIGN KEY (event_id) REFERENCES ${this.#eventsTableName}(id) ON DELETE CASCADE
|
|
70
|
+
)
|
|
71
|
+
`);
|
|
72
|
+
const eventsIndexPrefix = indexPrefix(this.#eventsTableName);
|
|
73
|
+
const sagasIndexPrefix = indexPrefix(this.#eventSagasTableName);
|
|
74
|
+
await db.query(`
|
|
75
|
+
CREATE INDEX IF NOT EXISTS "${eventsIndexPrefix}_aggregate_id_idx"
|
|
76
|
+
ON ${this.#eventsTableName} (aggregate_id, aggregate_version)
|
|
77
|
+
`);
|
|
78
|
+
// Only checked rows participate in aggregate-version uniqueness, so ignoreConcurrencyError can opt out.
|
|
79
|
+
await db.query(`
|
|
80
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "${this.#aggregateVersionIndexName}"
|
|
81
|
+
ON ${this.#eventsTableName} (aggregate_id, aggregate_version)
|
|
82
|
+
WHERE check_concurrency
|
|
83
|
+
AND aggregate_id IS NOT NULL
|
|
84
|
+
AND aggregate_version IS NOT NULL
|
|
85
|
+
`);
|
|
86
|
+
await db.query(`
|
|
87
|
+
CREATE INDEX IF NOT EXISTS "${eventsIndexPrefix}_type_position_idx"
|
|
88
|
+
ON ${this.#eventsTableName} (type, position)
|
|
89
|
+
`);
|
|
90
|
+
await db.query(`
|
|
91
|
+
CREATE INDEX IF NOT EXISTS "${sagasIndexPrefix}_event_id_idx"
|
|
92
|
+
ON ${this.#eventSagasTableName} (event_id)
|
|
93
|
+
`);
|
|
94
|
+
}
|
|
95
|
+
// eslint-disable-next-line class-methods-use-this
|
|
96
|
+
getNewId() {
|
|
97
|
+
return (0, node_crypto_1.randomUUID)().replaceAll('-', '');
|
|
98
|
+
}
|
|
99
|
+
async commitEvents(events, options) {
|
|
100
|
+
try {
|
|
101
|
+
await this.runInTransaction(async () => {
|
|
102
|
+
const metaJson = options?.meta ? JSON.stringify(options.meta) : null;
|
|
103
|
+
for (const event of events) {
|
|
104
|
+
const { sagaOrigins, id, ...eventData } = event;
|
|
105
|
+
const eventId = id ?? this.getNewId();
|
|
106
|
+
(0, index_ts_2.assertString)(eventId, 'event.id');
|
|
107
|
+
event.id = eventId;
|
|
108
|
+
await this.connection.query(`
|
|
109
|
+
INSERT INTO ${this.#eventsTableName} (
|
|
110
|
+
id,
|
|
111
|
+
aggregate_id,
|
|
112
|
+
aggregate_version,
|
|
113
|
+
type,
|
|
114
|
+
data,
|
|
115
|
+
meta,
|
|
116
|
+
check_concurrency
|
|
117
|
+
)
|
|
118
|
+
VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7)
|
|
119
|
+
`, [
|
|
120
|
+
eventId,
|
|
121
|
+
event.aggregateId !== undefined ? String(event.aggregateId) : null,
|
|
122
|
+
event.aggregateVersion ?? null,
|
|
123
|
+
event.type,
|
|
124
|
+
JSON.stringify(eventData),
|
|
125
|
+
metaJson,
|
|
126
|
+
!options?.ignoreConcurrencyError
|
|
127
|
+
]);
|
|
128
|
+
if (sagaOrigins) {
|
|
129
|
+
for (const [descriptor, originId] of Object.entries(sagaOrigins)) {
|
|
130
|
+
await this.connection.query(`
|
|
131
|
+
INSERT INTO ${this.#eventSagasTableName} (
|
|
132
|
+
saga_descriptor,
|
|
133
|
+
origin_id,
|
|
134
|
+
event_id
|
|
135
|
+
)
|
|
136
|
+
VALUES ($1, $2, $3)
|
|
137
|
+
`, [descriptor, String(originId), eventId]);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (this.isAggregateVersionUniqueViolation(error))
|
|
145
|
+
throw new index_ts_1.ConcurrencyError('Concurrency conflict: duplicate event version', { cause: error });
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
return events;
|
|
149
|
+
}
|
|
150
|
+
async *getAggregateEvents(aggregateId, options) {
|
|
151
|
+
await this.assertConnection();
|
|
152
|
+
const rows = await this.connection.query(`
|
|
153
|
+
WITH tail AS (
|
|
154
|
+
SELECT id AS tail_id
|
|
155
|
+
FROM ${this.#eventsTableName}
|
|
156
|
+
WHERE aggregate_id = $1
|
|
157
|
+
AND ($2::integer IS NULL OR aggregate_version > $2)
|
|
158
|
+
ORDER BY position DESC
|
|
159
|
+
LIMIT 1
|
|
160
|
+
)
|
|
161
|
+
SELECT
|
|
162
|
+
e.id,
|
|
163
|
+
e.aggregate_id,
|
|
164
|
+
e.aggregate_version,
|
|
165
|
+
e.type,
|
|
166
|
+
e.data,
|
|
167
|
+
e.meta,
|
|
168
|
+
e.position,
|
|
169
|
+
jsonb_object_agg(sr.saga_descriptor, sr.origin_id)
|
|
170
|
+
FILTER (WHERE sr.saga_descriptor IS NOT NULL) AS saga_origins
|
|
171
|
+
FROM ${this.#eventsTableName} e
|
|
172
|
+
LEFT JOIN tail ON TRUE
|
|
173
|
+
LEFT JOIN ${this.#eventSagasTableName} sr
|
|
174
|
+
ON sr.event_id = e.id
|
|
175
|
+
WHERE e.aggregate_id = $1
|
|
176
|
+
AND ($2::integer IS NULL OR e.aggregate_version > $2)
|
|
177
|
+
AND (
|
|
178
|
+
$3::text[] IS NULL
|
|
179
|
+
OR e.type = ANY($3::text[])
|
|
180
|
+
OR ($4 = 'last' AND e.id = tail.tail_id)
|
|
181
|
+
)
|
|
182
|
+
GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.position
|
|
183
|
+
ORDER BY e.position
|
|
184
|
+
`, [
|
|
185
|
+
String(aggregateId),
|
|
186
|
+
options?.snapshot?.aggregateVersion ?? null,
|
|
187
|
+
options?.eventTypes ?? null,
|
|
188
|
+
options?.tail ?? null
|
|
189
|
+
]);
|
|
190
|
+
for (const row of rows.rows)
|
|
191
|
+
yield reconstructEvent(row);
|
|
192
|
+
}
|
|
193
|
+
async *getSagaEvents(sagaId, { beforeEvent }) {
|
|
194
|
+
await this.assertConnection();
|
|
195
|
+
(0, index_ts_2.assertString)(beforeEvent?.id, 'beforeEvent.id');
|
|
196
|
+
const { sagaDescriptor, originEventId } = (0, index_ts_2.parseSagaId)(sagaId);
|
|
197
|
+
if (beforeEvent.sagaOrigins?.[sagaDescriptor] !== originEventId)
|
|
198
|
+
throw new TypeError('beforeEvent.sagaOrigins does not match sagaId');
|
|
199
|
+
const rows = await this.connection.query(`
|
|
200
|
+
WITH bounds AS (
|
|
201
|
+
SELECT
|
|
202
|
+
(SELECT position FROM ${this.#eventsTableName} WHERE id = $2) AS origin_position,
|
|
203
|
+
(SELECT position FROM ${this.#eventsTableName} WHERE id = $3) AS before_position
|
|
204
|
+
)
|
|
205
|
+
SELECT
|
|
206
|
+
b.origin_position,
|
|
207
|
+
b.before_position,
|
|
208
|
+
e.id,
|
|
209
|
+
e.aggregate_id,
|
|
210
|
+
e.aggregate_version,
|
|
211
|
+
e.type,
|
|
212
|
+
e.data,
|
|
213
|
+
e.meta,
|
|
214
|
+
e.position,
|
|
215
|
+
e.saga_origins
|
|
216
|
+
FROM bounds b
|
|
217
|
+
LEFT JOIN LATERAL (
|
|
218
|
+
SELECT
|
|
219
|
+
e.id,
|
|
220
|
+
e.aggregate_id,
|
|
221
|
+
e.aggregate_version,
|
|
222
|
+
e.type,
|
|
223
|
+
e.data,
|
|
224
|
+
e.meta,
|
|
225
|
+
e.position,
|
|
226
|
+
jsonb_object_agg(sr.saga_descriptor, sr.origin_id)
|
|
227
|
+
FILTER (WHERE sr.saga_descriptor IS NOT NULL) AS saga_origins
|
|
228
|
+
FROM ${this.#eventsTableName} e
|
|
229
|
+
LEFT JOIN ${this.#eventSagasTableName} filter_sr
|
|
230
|
+
ON filter_sr.event_id = e.id
|
|
231
|
+
AND filter_sr.saga_descriptor = $1
|
|
232
|
+
AND filter_sr.origin_id = $2
|
|
233
|
+
LEFT JOIN ${this.#eventSagasTableName} sr
|
|
234
|
+
ON sr.event_id = e.id
|
|
235
|
+
WHERE b.origin_position IS NOT NULL
|
|
236
|
+
AND b.before_position IS NOT NULL
|
|
237
|
+
AND e.position >= b.origin_position
|
|
238
|
+
AND e.position < b.before_position
|
|
239
|
+
AND (e.id = $2 OR filter_sr.event_id IS NOT NULL)
|
|
240
|
+
GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.position
|
|
241
|
+
ORDER BY e.position
|
|
242
|
+
) e ON TRUE
|
|
243
|
+
ORDER BY e.position
|
|
244
|
+
`, [sagaDescriptor, originEventId, beforeEvent.id]);
|
|
245
|
+
const bounds = rows.rows[0];
|
|
246
|
+
if (!bounds?.origin_position)
|
|
247
|
+
throw new Error(`origin event ${originEventId} not found`);
|
|
248
|
+
if (!bounds.before_position)
|
|
249
|
+
throw new Error(`beforeEvent ${beforeEvent.id} not found`);
|
|
250
|
+
for (const row of rows.rows) {
|
|
251
|
+
if (row.id)
|
|
252
|
+
yield reconstructEvent(row);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async *getEventsByTypes(eventTypes, options) {
|
|
256
|
+
await this.assertConnection();
|
|
257
|
+
const lastEventId = options?.afterEvent?.id;
|
|
258
|
+
if (options?.afterEvent)
|
|
259
|
+
(0, index_ts_2.assertString)(options.afterEvent.id, 'options.afterEvent.id');
|
|
260
|
+
let afterPosition = 0;
|
|
261
|
+
if (lastEventId) {
|
|
262
|
+
const row = await this.connection.query(`
|
|
263
|
+
SELECT position
|
|
264
|
+
FROM ${this.#eventsTableName}
|
|
265
|
+
WHERE id = $1
|
|
266
|
+
`, [lastEventId]);
|
|
267
|
+
if (!row.rows.length)
|
|
268
|
+
return;
|
|
269
|
+
afterPosition = row.rows[0].position;
|
|
270
|
+
}
|
|
271
|
+
const rows = await this.connection.query(`
|
|
272
|
+
SELECT
|
|
273
|
+
e.id,
|
|
274
|
+
e.aggregate_id,
|
|
275
|
+
e.aggregate_version,
|
|
276
|
+
e.type,
|
|
277
|
+
e.data,
|
|
278
|
+
e.meta,
|
|
279
|
+
e.position,
|
|
280
|
+
jsonb_object_agg(sr.saga_descriptor, sr.origin_id)
|
|
281
|
+
FILTER (WHERE sr.saga_descriptor IS NOT NULL) AS saga_origins
|
|
282
|
+
FROM ${this.#eventsTableName} e
|
|
283
|
+
LEFT JOIN ${this.#eventSagasTableName} sr
|
|
284
|
+
ON sr.event_id = e.id
|
|
285
|
+
WHERE e.position > $1
|
|
286
|
+
AND e.type = ANY($2::text[])
|
|
287
|
+
GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.position
|
|
288
|
+
ORDER BY e.position
|
|
289
|
+
`, [afterPosition, eventTypes]);
|
|
290
|
+
for (const row of rows.rows)
|
|
291
|
+
yield reconstructEvent(row);
|
|
292
|
+
}
|
|
293
|
+
async process(batch) {
|
|
294
|
+
const events = [];
|
|
295
|
+
for (const item of batch) {
|
|
296
|
+
if (!item.event)
|
|
297
|
+
throw new Error('Event batch does not contain `event`');
|
|
298
|
+
events.push(item.event);
|
|
299
|
+
}
|
|
300
|
+
await this.commitEvents(events, {
|
|
301
|
+
ignoreConcurrencyError: batch[0]?.ignoreConcurrencyError,
|
|
302
|
+
meta: extractMeta(batch[0])
|
|
303
|
+
});
|
|
304
|
+
return batch;
|
|
305
|
+
}
|
|
306
|
+
isAggregateVersionUniqueViolation(error) {
|
|
307
|
+
return typeof error === 'object' &&
|
|
308
|
+
error !== null &&
|
|
309
|
+
'code' in error &&
|
|
310
|
+
error.code === '23505' &&
|
|
311
|
+
error.constraint === this.#aggregateVersionIndexName;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
exports.PostgresqlEventStorage = PostgresqlEventStorage;
|
|
315
|
+
//# sourceMappingURL=PostgresqlEventStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresqlEventStorage.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlEventStorage.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAezC,iDAAsD;AACtD,gDAA8D;AAC9D,mFAA6E;AAE7E,+CAAmD;AAmCnD,SAAS,WAAW,CAAC,QAAkC;IACtD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;IAC7E,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QACjC,OAAO,IAAI,CAAC;IAEb,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAChC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAC5B,OAAO,KAAK,CAAC;IAEd,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,WAAW,CAAC,SAAiB;IACrC,OAAO,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAa;IACtC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAuC,CAAC;IACvE,MAAM,KAAK,GAAW;QACrB,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,GAAG,IAAI;KACP,CAAC;IAEF,IAAI,GAAG,CAAC,YAAY;QACnB,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,YAAY,CAA2B,CAAC;IAE3E,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAa,sBAAuB,SAAQ,0DAA0B;IAKrE,MAAM,CAAU,YAAY,GAAG,YAAY,CAAC;IAC5C,MAAM,CAAU,iBAAiB,GAAG,iBAAiB,CAAC;IAE7C,gBAAgB,CAAS;IACzB,oBAAoB,CAAS;IAC7B,0BAA0B,CAAS;IAE5C,YAAY,EACX,4BAA4B,EAC5B,qBAAqB,EACrB,4BAA4B,EAM3B;QACD,KAAK,CAAC,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,CAAC,CAAC;QAE/D,MAAM,eAAe,GAAG,4BAA4B,EAAE,eAAe,IAAI,sBAAsB,CAAC,YAAY,CAAC;QAC7G,MAAM,mBAAmB,GAAG,4BAA4B,EAAE,mBAAmB;YAC5E,sBAAsB,CAAC,iBAAiB,CAAC;QAC1C,IAAA,uBAAY,EAAC,eAAe,EAAE,8CAA8C,CAAC,CAAC;QAC9E,IAAA,uBAAY,EAAC,mBAAmB,EAAE,kDAAkD,CAAC,CAAC;QAEtF,IAAI,CAAC,gBAAgB,GAAG,IAAA,0BAAe,EAAC,eAAe,CAAC,CAAC;QACzD,IAAI,CAAC,oBAAoB,GAAG,IAAA,0BAAe,EAAC,mBAAmB,CAAC,CAAC;QACjE,IAAI,CAAC,0BAA0B,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,+BAA+B,CAAC;IACxG,CAAC;IAEkB,KAAK,CAAC,UAAU,CAAC,EAAwB;QAC3D,MAAM,EAAE,CAAC,KAAK,CAAC;gCACe,IAAI,CAAC,gBAAgB;;;;;;;;;;GAUlD,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,KAAK,CAAC;gCACe,IAAI,CAAC,oBAAoB;;;;;wCAKjB,IAAI,CAAC,gBAAgB;;GAE1D,CAAC,CAAC;QAEH,MAAM,iBAAiB,GAAG,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,gBAAgB,GAAG,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAEhE,MAAM,EAAE,CAAC,KAAK,CAAC;iCACgB,iBAAiB;QAC1C,IAAI,CAAC,gBAAgB;GAC1B,CAAC,CAAC;QAEH,wGAAwG;QACxG,MAAM,EAAE,CAAC,KAAK,CAAC;wCACuB,IAAI,CAAC,0BAA0B;QAC/D,IAAI,CAAC,gBAAgB;;;;GAI1B,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,KAAK,CAAC;iCACgB,iBAAiB;QAC1C,IAAI,CAAC,gBAAgB;GAC1B,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,KAAK,CAAC;iCACgB,gBAAgB;QACzC,IAAI,CAAC,oBAAoB;GAC9B,CAAC,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,QAAQ;QACP,OAAO,IAAA,wBAAU,GAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAiB,EAAE,OAGrC;QACA,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,IAAI,EAAE;gBACtC,MAAM,QAAQ,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBACrE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC5B,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,CAAC;oBAChD,MAAM,OAAO,GAAG,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACtC,IAAA,uBAAY,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;oBACjC,KAAgB,CAAC,EAAE,GAAG,OAAO,CAAC;oBAE/B,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;oBACb,IAAI,CAAC,gBAAgB;;;;;;;;;;MAUnC,EAAE;wBACF,OAAO;wBACP,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI;wBAClE,KAAK,CAAC,gBAAgB,IAAI,IAAI;wBAC9B,KAAK,CAAC,IAAI;wBACV,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;wBACzB,QAAQ;wBACR,CAAC,OAAO,EAAE,sBAAsB;qBAChC,CAAC,CAAC;oBAEH,IAAI,WAAW,EAAE,CAAC;wBACjB,KAAK,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;4BAClE,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;sBACb,IAAI,CAAC,oBAAoB;;;;;;QAMvC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;wBAC7C,CAAC;oBACF,CAAC;gBACF,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,iCAAiC,CAAC,KAAK,CAAC;gBAChD,MAAM,IAAI,2BAAgB,CAAC,+CAA+C,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YAE/F,MAAM,KAAK,CAAC;QACb,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAED,KAAK,CAAA,CAAE,kBAAkB,CAAC,WAAuB,EAAE,OAAoC;QACtF,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAW;;;WAG1C,IAAI,CAAC,gBAAgB;;;;;;;;;;;;;;;;UAgBtB,IAAI,CAAC,gBAAgB;;eAEhB,IAAI,CAAC,oBAAoB;;;;;;;;;;;GAWrC,EAAE;YACF,MAAM,CAAC,WAAW,CAAC;YACnB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,IAAI,IAAI;YAC3C,OAAO,EAAE,UAAU,IAAI,IAAI;YAC3B,OAAO,EAAE,IAAI,IAAI,IAAI;SACrB,CAAC,CAAC;QAEH,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI;YAC1B,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAA,CAAE,aAAa,CAAC,MAAkB,EAAE,EAAE,WAAW,EAA2B;QAChF,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,IAAA,uBAAY,EAAC,WAAW,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAEhD,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,IAAA,sBAAW,EAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC,cAAc,CAAC,KAAK,aAAa;YAC9D,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAC;QAEtE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAe;;;6BAG5B,IAAI,CAAC,gBAAgB;6BACrB,IAAI,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;WAyBvC,IAAI,CAAC,gBAAgB;gBAChB,IAAI,CAAC,oBAAoB;;;;gBAIzB,IAAI,CAAC,oBAAoB;;;;;;;;;;;GAWtC,EAAE,CAAC,cAAc,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;QAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE,eAAe;YAC3B,MAAM,IAAI,KAAK,CAAC,gBAAgB,aAAa,YAAY,CAAC,CAAC;QAE5D,IAAI,CAAC,MAAM,CAAC,eAAe;YAC1B,MAAM,IAAI,KAAK,CAAC,eAAe,WAAW,CAAC,EAAE,YAAY,CAAC,CAAC;QAE5D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7B,IAAI,GAAG,CAAC,EAAE;gBACT,MAAM,gBAAgB,CAAC,GAAe,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,KAAK,CAAA,CAAE,gBAAgB,CAAC,UAA8B,EAAE,OAAyB;QAChF,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,MAAM,WAAW,GAAG,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC;QAC5C,IAAI,OAAO,EAAE,UAAU;YACtB,IAAA,uBAAY,EAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,uBAAuB,CAAC,CAAC;QAE9D,IAAI,aAAa,GAAoB,CAAC,CAAC;QACvC,IAAI,WAAW,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAc;;WAE7C,IAAI,CAAC,gBAAgB;;IAE5B,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;YAElB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM;gBACnB,OAAO;YAER,aAAa,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAW;;;;;;;;;;;UAW3C,IAAI,CAAC,gBAAgB;eAChB,IAAI,CAAC,oBAAoB;;;;;;GAMrC,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC;QAEhC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI;YAC1B,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAA4B;QACzC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,KAAK;gBACd,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAEzD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;QAED,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;YAC/B,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,sBAAsB;YACxD,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3B,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACd,CAAC;IAEO,iCAAiC,CAAC,KAAc;QACvD,OAAO,OAAO,KAAK,KAAK,QAAQ;YAC/B,KAAK,KAAK,IAAI;YACd,MAAM,IAAI,KAAK;YACd,KAAyB,CAAC,IAAI,KAAK,OAAO;YAC1C,KAAyB,CAAC,UAAU,KAAK,IAAI,CAAC,0BAA0B,CAAC;IAC5E,CAAC;;AA9UF,wDA+UC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresqlObjectStorage = void 0;
|
|
4
|
+
const assert_ts_1 = require("../utils/assert.js");
|
|
5
|
+
const AbstractPostgresqlAccessor_ts_1 = require("./AbstractPostgresqlAccessor.js");
|
|
6
|
+
const index_ts_1 = require("./utils/index.js");
|
|
7
|
+
/**
|
|
8
|
+
* PostgreSQL-backed implementation of IObjectStorage.
|
|
9
|
+
*
|
|
10
|
+
* Each record is stored as a row `{ id, data, version }`.
|
|
11
|
+
* The version field enables optimistic concurrency control: `update` and
|
|
12
|
+
* `updateEnforcingNew` re-read the record after the user callback runs and
|
|
13
|
+
* atomically commit only when the version still matches.
|
|
14
|
+
* On mismatch the operation retries up to `maxRetries` times.
|
|
15
|
+
*/
|
|
16
|
+
class PostgresqlObjectStorage extends AbstractPostgresqlAccessor_ts_1.AbstractPostgresqlAccessor {
|
|
17
|
+
#tableName;
|
|
18
|
+
#maxRetries;
|
|
19
|
+
constructor(o) {
|
|
20
|
+
super(o);
|
|
21
|
+
(0, assert_ts_1.assertString)(o.tableName, 'tableName');
|
|
22
|
+
if (o.maxRetries !== undefined)
|
|
23
|
+
(0, assert_ts_1.assertNonNegativeInteger)(o.maxRetries, 'maxRetries');
|
|
24
|
+
this.#tableName = (0, index_ts_1.quoteIdentifier)(o.tableName);
|
|
25
|
+
this.#maxRetries = o.maxRetries ?? 100;
|
|
26
|
+
}
|
|
27
|
+
async initialize(db) {
|
|
28
|
+
await db.query(`
|
|
29
|
+
CREATE TABLE IF NOT EXISTS ${this.#tableName} (
|
|
30
|
+
id text PRIMARY KEY,
|
|
31
|
+
version integer NOT NULL DEFAULT 1,
|
|
32
|
+
data jsonb NOT NULL
|
|
33
|
+
)
|
|
34
|
+
`);
|
|
35
|
+
}
|
|
36
|
+
async get(id) {
|
|
37
|
+
(0, assert_ts_1.assertDefined)(id, 'id');
|
|
38
|
+
await this.assertConnection();
|
|
39
|
+
const result = await this.connection.query(`
|
|
40
|
+
SELECT data, version
|
|
41
|
+
FROM ${this.#tableName}
|
|
42
|
+
WHERE id = $1
|
|
43
|
+
`, [String(id)]);
|
|
44
|
+
const row = result.rows[0];
|
|
45
|
+
if (!row)
|
|
46
|
+
return undefined;
|
|
47
|
+
return PostgresqlObjectStorage.parseData(row.data);
|
|
48
|
+
}
|
|
49
|
+
async create(id, data) {
|
|
50
|
+
(0, assert_ts_1.assertDefined)(id, 'id');
|
|
51
|
+
await this.assertConnection();
|
|
52
|
+
const result = await this.connection.query(`
|
|
53
|
+
INSERT INTO ${this.#tableName} (id, data)
|
|
54
|
+
VALUES ($1, $2::jsonb)
|
|
55
|
+
ON CONFLICT (id) DO NOTHING
|
|
56
|
+
`, [String(id), JSON.stringify(data)]);
|
|
57
|
+
if (result.rowCount !== 1)
|
|
58
|
+
throw new Error(`Record '${id}' could not be created`);
|
|
59
|
+
}
|
|
60
|
+
async update(id, update) {
|
|
61
|
+
(0, assert_ts_1.assertDefined)(id, 'id');
|
|
62
|
+
(0, assert_ts_1.assertFunction)(update, 'update');
|
|
63
|
+
await this.assertConnection();
|
|
64
|
+
for (let attempt = 0; attempt <= this.#maxRetries; attempt++) {
|
|
65
|
+
const row = await this.getRow(id);
|
|
66
|
+
if (!row)
|
|
67
|
+
throw new Error(`Record '${id}' does not exist`);
|
|
68
|
+
const updatedData = update(PostgresqlObjectStorage.parseData(row.data));
|
|
69
|
+
const result = await this.updateByVersion(id, row.version, updatedData);
|
|
70
|
+
if (result.rowCount === 1)
|
|
71
|
+
return;
|
|
72
|
+
// version mismatch - retry
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`Record '${id}' could not be updated after ${this.#maxRetries} retries`);
|
|
75
|
+
}
|
|
76
|
+
async updateEnforcingNew(id, update) {
|
|
77
|
+
(0, assert_ts_1.assertDefined)(id, 'id');
|
|
78
|
+
(0, assert_ts_1.assertFunction)(update, 'update');
|
|
79
|
+
await this.assertConnection();
|
|
80
|
+
for (let attempt = 0; attempt <= this.#maxRetries; attempt++) {
|
|
81
|
+
const row = await this.getRow(id);
|
|
82
|
+
if (row) {
|
|
83
|
+
const updatedData = update(PostgresqlObjectStorage.parseData(row.data));
|
|
84
|
+
const result = await this.updateByVersion(id, row.version, updatedData);
|
|
85
|
+
if (result.rowCount === 1)
|
|
86
|
+
return;
|
|
87
|
+
// version mismatch - retry
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const result = await this.connection.query(`
|
|
91
|
+
INSERT INTO ${this.#tableName} (id, data)
|
|
92
|
+
VALUES ($1, $2::jsonb)
|
|
93
|
+
ON CONFLICT (id) DO NOTHING
|
|
94
|
+
`, [String(id), JSON.stringify(update(undefined))]);
|
|
95
|
+
if (result.rowCount === 1)
|
|
96
|
+
return;
|
|
97
|
+
// Another process inserted first - retry
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
throw new Error(`Record '${id}' could not be upserted after ${this.#maxRetries} retries`);
|
|
101
|
+
}
|
|
102
|
+
async delete(id) {
|
|
103
|
+
(0, assert_ts_1.assertDefined)(id, 'id');
|
|
104
|
+
await this.assertConnection();
|
|
105
|
+
const result = await this.connection.query(`
|
|
106
|
+
DELETE FROM ${this.#tableName}
|
|
107
|
+
WHERE id = $1
|
|
108
|
+
`, [String(id)]);
|
|
109
|
+
return result.rowCount === 1;
|
|
110
|
+
}
|
|
111
|
+
async getRow(id) {
|
|
112
|
+
const result = await this.connection.query(`
|
|
113
|
+
SELECT data, version
|
|
114
|
+
FROM ${this.#tableName}
|
|
115
|
+
WHERE id = $1
|
|
116
|
+
`, [String(id)]);
|
|
117
|
+
return result.rows[0];
|
|
118
|
+
}
|
|
119
|
+
updateByVersion(id, version, data) {
|
|
120
|
+
return this.connection.query(`
|
|
121
|
+
UPDATE ${this.#tableName}
|
|
122
|
+
SET
|
|
123
|
+
data = $1::jsonb,
|
|
124
|
+
version = version + 1
|
|
125
|
+
WHERE
|
|
126
|
+
id = $2
|
|
127
|
+
AND version = $3
|
|
128
|
+
`, [JSON.stringify(data), String(id), version]);
|
|
129
|
+
}
|
|
130
|
+
static parseData(data) {
|
|
131
|
+
if (typeof data === 'string')
|
|
132
|
+
return JSON.parse(data);
|
|
133
|
+
return data;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.PostgresqlObjectStorage = PostgresqlObjectStorage;
|
|
137
|
+
//# sourceMappingURL=PostgresqlObjectStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresqlObjectStorage.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlObjectStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresqlObjectView = void 0;
|
|
4
|
+
const assert_ts_1 = require("../utils/assert.js");
|
|
5
|
+
const AbstractPostgresqlView_ts_1 = require("./AbstractPostgresqlView.js");
|
|
6
|
+
const PostgresqlObjectStorage_ts_1 = require("./PostgresqlObjectStorage.js");
|
|
7
|
+
/**
|
|
8
|
+
* PostgreSQL-backed object view with restore locking and last-processed-event tracking.
|
|
9
|
+
*/
|
|
10
|
+
class PostgresqlObjectView extends AbstractPostgresqlView_ts_1.AbstractPostgresqlView {
|
|
11
|
+
#postgresqlObjectStorage;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
(0, assert_ts_1.assertString)(options?.tableNamePrefix, 'tableNamePrefix');
|
|
14
|
+
(0, assert_ts_1.assertString)(options?.schemaVersion, 'schemaVersion');
|
|
15
|
+
super(options);
|
|
16
|
+
this.#postgresqlObjectStorage = new PostgresqlObjectStorage_ts_1.PostgresqlObjectStorage({
|
|
17
|
+
viewModelPostgresqlDb: options.viewModelPostgresqlDb,
|
|
18
|
+
viewModelPostgresqlDbFactory: options.viewModelPostgresqlDbFactory,
|
|
19
|
+
tableName: `${options.tableNamePrefix}_${options.schemaVersion}`,
|
|
20
|
+
maxRetries: options.postgresqlObjectStorageMaxRetries
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// eslint-disable-next-line class-methods-use-this
|
|
24
|
+
initialize(_db) {
|
|
25
|
+
// No need to initialize the table here, it's done in PostgresqlObjectStorage
|
|
26
|
+
}
|
|
27
|
+
async get(id) {
|
|
28
|
+
if (!this.ready)
|
|
29
|
+
await this.once('ready');
|
|
30
|
+
return this.#postgresqlObjectStorage.get(id);
|
|
31
|
+
}
|
|
32
|
+
async create(id, data) {
|
|
33
|
+
await this.#postgresqlObjectStorage.create(id, data);
|
|
34
|
+
}
|
|
35
|
+
async update(id, update) {
|
|
36
|
+
await this.#postgresqlObjectStorage.update(id, update);
|
|
37
|
+
}
|
|
38
|
+
async updateEnforcingNew(id, update) {
|
|
39
|
+
await this.#postgresqlObjectStorage.updateEnforcingNew(id, update);
|
|
40
|
+
}
|
|
41
|
+
async delete(id) {
|
|
42
|
+
return this.#postgresqlObjectStorage.delete(id);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.PostgresqlObjectView = PostgresqlObjectView;
|
|
46
|
+
//# sourceMappingURL=PostgresqlObjectView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresqlObjectView.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlObjectView.ts"],"names":[],"mappings":";;;AACA,kDAAkD;AAClD,2EAAqE;AACrE,6EAAuE;AAGvE;;GAEG;AACH,MAAa,oBACZ,SAAQ,kDAAsB;IAGrB,wBAAwB,CAAmC;IAEpE,YAAY,OAGX;QACA,IAAA,wBAAY,EAAC,OAAO,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;QAC1D,IAAA,wBAAY,EAAC,OAAO,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC;QAEtD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,wBAAwB,GAAG,IAAI,oDAAuB,CAAU;YACpE,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;YACpD,4BAA4B,EAAE,OAAO,CAAC,4BAA4B;YAClE,SAAS,EAAE,GAAG,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,aAAa,EAAE;YAChE,UAAU,EAAE,OAAO,CAAC,iCAAiC;SACrD,CAAC,CAAC;IACJ,CAAC;IAED,kDAAkD;IACxC,UAAU,CAAC,GAAyB;QAC7C,6EAA6E;IAC9E,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAc;QACvB,IAAI,CAAC,IAAI,CAAC,KAAK;YACd,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE1B,OAAO,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAc,EAAE,IAAa;QACzC,MAAM,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAc,EAAE,MAA+B;QAC3D,MAAM,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,EAAc,EAAE,MAAgC;QACxE,MAAM,IAAI,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAc;QAC1B,OAAO,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;CACD;AAlDD,oDAkDC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresqlProjectionDataParams.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlProjectionDataParams.ts"],"names":[],"mappings":""}
|