@event-driven-io/emmett-postgresql 0.38.0-alpha.3 → 0.38.0-alpha.5

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/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  var _dumbo = require('@event-driven-io/dumbo');
5
5
 
6
- // ../emmett/dist/chunk-BQYVGGNE.js
6
+ // ../emmett/dist/chunk-SJ7ERGWB.js
7
7
  var isNumber = (val) => typeof val === "number" && val === val;
8
8
  var isString = (val) => typeof val === "string";
9
9
  var isErrorConstructor = (expect) => {
@@ -34,12 +34,12 @@ var ConcurrencyError = class _ConcurrencyError extends EmmettError {
34
34
 
35
35
  // ../emmett/dist/index.js
36
36
  var _uuid = require('uuid');
37
- var _webstreamspolyfill = require('web-streams-polyfill');
38
37
 
38
+ var _asyncretry = require('async-retry'); var _asyncretry2 = _interopRequireDefault(_asyncretry);
39
39
 
40
+ var _webstreamspolyfill = require('web-streams-polyfill');
40
41
 
41
42
 
42
- var _asyncretry = require('async-retry'); var _asyncretry2 = _interopRequireDefault(_asyncretry);
43
43
 
44
44
 
45
45
 
@@ -74,44 +74,6 @@ var ExpectedVersionConflictError = class _ExpectedVersionConflictError extends C
74
74
  Object.setPrototypeOf(this, _ExpectedVersionConflictError.prototype);
75
75
  }
76
76
  };
77
- var notifyAboutNoActiveReadersStream = (onNoActiveReaderCallback, options = {}) => new NotifyAboutNoActiveReadersStream(onNoActiveReaderCallback, options);
78
- var NotifyAboutNoActiveReadersStream = (_class = class extends _webstreamspolyfill.TransformStream {
79
- constructor(onNoActiveReaderCallback, options = {}) {
80
- super({
81
- cancel: (reason) => {
82
- console.log("Stream was canceled. Reason:", reason);
83
- this.stopChecking();
84
- }
85
- });_class.prototype.__init.call(this);_class.prototype.__init2.call(this);;
86
- this.onNoActiveReaderCallback = onNoActiveReaderCallback;
87
- this.streamId = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _8 => _8.streamId]), () => ( _uuid.v4.call(void 0, )));
88
- this.onNoActiveReaderCallback = onNoActiveReaderCallback;
89
- this.startChecking(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _9 => _9.intervalCheckInMs]), () => ( 20)));
90
- }
91
- __init() {this.checkInterval = null}
92
-
93
- __init2() {this._isStopped = false}
94
- get hasActiveSubscribers() {
95
- return !this._isStopped;
96
- }
97
- startChecking(interval) {
98
- this.checkInterval = setInterval(() => {
99
- this.checkNoActiveReader();
100
- }, interval);
101
- }
102
- stopChecking() {
103
- if (!this.checkInterval) return;
104
- clearInterval(this.checkInterval);
105
- this.checkInterval = null;
106
- this._isStopped = true;
107
- this.onNoActiveReaderCallback(this);
108
- }
109
- checkNoActiveReader() {
110
- if (!this.readable.locked && !this._isStopped) {
111
- this.stopChecking();
112
- }
113
- }
114
- }, _class);
115
77
  var deepEquals = (left, right) => {
116
78
  if (isEquatable(left)) {
117
79
  return left.equals(right);
@@ -148,17 +110,17 @@ var ParseError = class extends Error {
148
110
  var JSONParser = {
149
111
  stringify: (value, options) => {
150
112
  return JSON.stringify(
151
- _optionalChain([options, 'optionalAccess', _10 => _10.map]) ? options.map(value) : value,
113
+ _optionalChain([options, 'optionalAccess', _8 => _8.map]) ? options.map(value) : value,
152
114
  //TODO: Consider adding support to DateTime and adding specific format to mark that's a bigint
153
115
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
154
116
  (_, v) => typeof v === "bigint" ? v.toString() : v
155
117
  );
156
118
  },
157
119
  parse: (text, options) => {
158
- const parsed = JSON.parse(text, _optionalChain([options, 'optionalAccess', _11 => _11.reviver]));
159
- if (_optionalChain([options, 'optionalAccess', _12 => _12.typeCheck]) && !_optionalChain([options, 'optionalAccess', _13 => _13.typeCheck, 'call', _14 => _14(parsed)]))
120
+ const parsed = JSON.parse(text, _optionalChain([options, 'optionalAccess', _9 => _9.reviver]));
121
+ if (_optionalChain([options, 'optionalAccess', _10 => _10.typeCheck]) && !_optionalChain([options, 'optionalAccess', _11 => _11.typeCheck, 'call', _12 => _12(parsed)]))
160
122
  throw new ParseError(text);
161
- return _optionalChain([options, 'optionalAccess', _15 => _15.map]) ? options.map(parsed) : parsed;
123
+ return _optionalChain([options, 'optionalAccess', _13 => _13.map]) ? options.map(parsed) : parsed;
162
124
  }
163
125
  };
164
126
  var asyncRetry = async (fn, opts) => {
@@ -167,14 +129,14 @@ var asyncRetry = async (fn, opts) => {
167
129
  async (bail) => {
168
130
  try {
169
131
  const result = await fn();
170
- if (_optionalChain([opts, 'optionalAccess', _16 => _16.shouldRetryResult]) && opts.shouldRetryResult(result)) {
132
+ if (_optionalChain([opts, 'optionalAccess', _14 => _14.shouldRetryResult]) && opts.shouldRetryResult(result)) {
171
133
  throw new EmmettError(
172
134
  `Retrying because of result: ${JSONParser.stringify(result)}`
173
135
  );
174
136
  }
175
137
  return result;
176
138
  } catch (error2) {
177
- if (_optionalChain([opts, 'optionalAccess', _17 => _17.shouldRetryError]) && !opts.shouldRetryError(error2)) {
139
+ if (_optionalChain([opts, 'optionalAccess', _15 => _15.shouldRetryError]) && !opts.shouldRetryError(error2)) {
178
140
  bail(error2);
179
141
  }
180
142
  throw error2;
@@ -298,6 +260,44 @@ var assertThatArray = (array) => {
298
260
  }
299
261
  };
300
262
  };
263
+ var notifyAboutNoActiveReadersStream = (onNoActiveReaderCallback, options = {}) => new NotifyAboutNoActiveReadersStream(onNoActiveReaderCallback, options);
264
+ var NotifyAboutNoActiveReadersStream = (_class = class extends _webstreamspolyfill.TransformStream {
265
+ constructor(onNoActiveReaderCallback, options = {}) {
266
+ super({
267
+ cancel: (reason) => {
268
+ console.log("Stream was canceled. Reason:", reason);
269
+ this.stopChecking();
270
+ }
271
+ });_class.prototype.__init.call(this);_class.prototype.__init2.call(this);;
272
+ this.onNoActiveReaderCallback = onNoActiveReaderCallback;
273
+ this.streamId = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _16 => _16.streamId]), () => ( _uuid.v4.call(void 0, )));
274
+ this.onNoActiveReaderCallback = onNoActiveReaderCallback;
275
+ this.startChecking(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _17 => _17.intervalCheckInMs]), () => ( 20)));
276
+ }
277
+ __init() {this.checkInterval = null}
278
+
279
+ __init2() {this._isStopped = false}
280
+ get hasActiveSubscribers() {
281
+ return !this._isStopped;
282
+ }
283
+ startChecking(interval) {
284
+ this.checkInterval = setInterval(() => {
285
+ this.checkNoActiveReader();
286
+ }, interval);
287
+ }
288
+ stopChecking() {
289
+ if (!this.checkInterval) return;
290
+ clearInterval(this.checkInterval);
291
+ this.checkInterval = null;
292
+ this._isStopped = true;
293
+ this.onNoActiveReaderCallback(this);
294
+ }
295
+ checkNoActiveReader() {
296
+ if (!this.readable.locked && !this._isStopped) {
297
+ this.stopChecking();
298
+ }
299
+ }
300
+ }, _class);
301
301
  var MessageProcessorType = {
302
302
  PROJECTOR: "projector",
303
303
  REACTOR: "reactor"
@@ -308,26 +308,30 @@ var reactor = (options) => {
308
308
  let isActive = true;
309
309
  const { checkpoints, processorId, partition } = options;
310
310
  const processingScope = _nullishCoalesce(options.processingScope, () => ( defaultProcessingMessageProcessingScope));
311
+ let lastCheckpoint = null;
311
312
  return {
312
313
  id: options.processorId,
313
314
  type: _nullishCoalesce(options.type, () => ( MessageProcessorType.REACTOR)),
314
315
  close: () => _optionalChain([options, 'access', _18 => _18.hooks, 'optionalAccess', _19 => _19.onClose]) ? _optionalChain([options, 'access', _20 => _20.hooks, 'optionalAccess', _21 => _21.onClose, 'call', _22 => _22()]) : Promise.resolve(),
315
316
  start: async (startOptions) => {
316
317
  isActive = true;
318
+ if (lastCheckpoint !== null)
319
+ return {
320
+ lastCheckpoint
321
+ };
317
322
  return await processingScope(async (context) => {
318
323
  if (_optionalChain([options, 'access', _23 => _23.hooks, 'optionalAccess', _24 => _24.onStart])) {
319
324
  await _optionalChain([options, 'access', _25 => _25.hooks, 'optionalAccess', _26 => _26.onStart, 'call', _27 => _27(context)]);
320
325
  }
321
326
  if (options.startFrom !== "CURRENT" && options.startFrom)
322
327
  return options.startFrom;
323
- let lastCheckpoint = null;
324
328
  if (checkpoints) {
325
329
  const readResult = await _optionalChain([checkpoints, 'optionalAccess', _28 => _28.read, 'call', _29 => _29(
326
330
  {
327
331
  processorId,
328
332
  partition
329
333
  },
330
- startOptions
334
+ { ...startOptions, ...context }
331
335
  )]);
332
336
  lastCheckpoint = readResult.lastCheckpoint;
333
337
  }
@@ -344,7 +348,6 @@ var reactor = (options) => {
344
348
  if (!isActive) return Promise.resolve();
345
349
  return await processingScope(async (context) => {
346
350
  let result = void 0;
347
- let lastCheckpoint = null;
348
351
  for (const message2 of messages) {
349
352
  const messageProcessingResult = await eachMessage(message2, context);
350
353
  if (checkpoints) {
@@ -755,7 +758,7 @@ var appendToStreamSQL = _dumbo.rawSql.call(void 0,
755
758
  ) RETURNS TABLE (
756
759
  success boolean,
757
760
  next_stream_position bigint,
758
- last_global_position bigint,
761
+ global_positions bigint[],
759
762
  transaction_id xid8
760
763
  ) LANGUAGE plpgsql
761
764
  AS $$
@@ -764,7 +767,7 @@ var appendToStreamSQL = _dumbo.rawSql.call(void 0,
764
767
  v_position bigint;
765
768
  v_updated_rows int;
766
769
  v_transaction_id xid8;
767
- v_last_global_position bigint;
770
+ v_global_positions bigint[];
768
771
  BEGIN
769
772
  v_transaction_id := pg_current_xact_id();
770
773
 
@@ -789,7 +792,7 @@ var appendToStreamSQL = _dumbo.rawSql.call(void 0,
789
792
  get diagnostics v_updated_rows = row_count;
790
793
 
791
794
  IF v_updated_rows = 0 THEN
792
- RETURN QUERY SELECT FALSE, NULL::bigint, NULL::bigint, NULL::xid8;
795
+ RETURN QUERY SELECT FALSE, NULL::bigint, NULL::bigint[], NULL::xid8;
793
796
  RETURN;
794
797
  END IF;
795
798
  END IF;
@@ -818,11 +821,11 @@ var appendToStreamSQL = _dumbo.rawSql.call(void 0,
818
821
  RETURNING global_position
819
822
  )
820
823
  SELECT
821
- max(global_position) INTO v_last_global_position
824
+ array_agg(global_position ORDER BY global_position) INTO v_global_positions
822
825
  FROM
823
826
  all_messages_insert;
824
827
 
825
- RETURN QUERY SELECT TRUE, v_next_stream_position, v_last_global_position, v_transaction_id;
828
+ RETURN QUERY SELECT TRUE, v_next_stream_position, v_global_positions, v_transaction_id;
826
829
  END;
827
830
  $$;
828
831
  `
@@ -831,22 +834,24 @@ var appendToStream = (pool, streamName, streamType, messages, options) => pool.w
831
834
  const { execute } = transaction;
832
835
  if (messages.length === 0)
833
836
  return { success: false, result: { success: false } };
834
- let appendResult;
835
837
  try {
836
838
  const expectedStreamVersion = toExpectedVersion(
837
839
  _optionalChain([options, 'optionalAccess', _42 => _42.expectedStreamVersion])
838
840
  );
839
- const messagesToAppend = messages.map((e, i) => ({
841
+ const messagesToAppend = messages.map((e) => ({
840
842
  ...e,
841
843
  kind: _nullishCoalesce(e.kind, () => ( "Event")),
842
844
  metadata: {
843
- streamName,
844
845
  messageId: _uuid.v4.call(void 0, ),
845
- streamPosition: BigInt(i),
846
846
  ..."metadata" in e ? _nullishCoalesce(e.metadata, () => ( {})) : {}
847
847
  }
848
848
  }));
849
- appendResult = await appendEventsRaw(
849
+ const {
850
+ success,
851
+ next_stream_position,
852
+ global_positions,
853
+ transaction_id
854
+ } = await appendEventsRaw(
850
855
  execute,
851
856
  streamName,
852
857
  streamType,
@@ -855,32 +860,40 @@ var appendToStream = (pool, streamName, streamType, messages, options) => pool.w
855
860
  expectedStreamVersion
856
861
  }
857
862
  );
863
+ if (!success || next_stream_position === null || global_positions === null || global_positions.length === 0 || transaction_id == null) {
864
+ return {
865
+ success: false,
866
+ result: { success: false }
867
+ };
868
+ }
869
+ const nextStreamPosition = BigInt(next_stream_position);
870
+ const globalPositions = global_positions.map(BigInt);
871
+ globalPositions.forEach((globalPosition, index) => {
872
+ messagesToAppend[index].metadata = {
873
+ ...messagesToAppend[index].metadata,
874
+ streamName,
875
+ streamPosition: nextStreamPosition - BigInt(messagesToAppend.length) + BigInt(index + 1),
876
+ globalPosition
877
+ };
878
+ });
858
879
  if (_optionalChain([options, 'optionalAccess', _43 => _43.beforeCommitHook]))
859
880
  await options.beforeCommitHook(messagesToAppend, { transaction });
881
+ return {
882
+ success: true,
883
+ result: {
884
+ success: true,
885
+ nextStreamPosition,
886
+ globalPositions,
887
+ transactionId: transaction_id
888
+ }
889
+ };
860
890
  } catch (error) {
861
891
  if (!isOptimisticConcurrencyError(error)) throw error;
862
- appendResult = {
892
+ return {
863
893
  success: false,
864
- last_global_position: null,
865
- next_stream_position: null,
866
- transaction_id: null
894
+ result: { success: false }
867
895
  };
868
896
  }
869
- const {
870
- success,
871
- next_stream_position,
872
- last_global_position,
873
- transaction_id
874
- } = appendResult;
875
- return {
876
- success,
877
- result: success && next_stream_position && last_global_position && transaction_id ? {
878
- success: true,
879
- nextStreamPosition: BigInt(next_stream_position),
880
- lastGlobalPosition: BigInt(last_global_position),
881
- transactionId: transaction_id
882
- } : { success: false }
883
- };
884
897
  });
885
898
  var toExpectedVersion = (expected) => {
886
899
  if (expected === void 0) return null;
@@ -907,7 +920,10 @@ var appendEventsRaw = (execute, streamId, streamType, messages, options) => _dum
907
920
  )`,
908
921
  messages.map((e) => _dumbo.sql.call(void 0, "%L", e.metadata.messageId)).join(","),
909
922
  messages.map((e) => _dumbo.sql.call(void 0, "%L", JSONParser.stringify(e.data))).join(","),
910
- messages.map((e) => _dumbo.sql.call(void 0, "%L", JSONParser.stringify(_nullishCoalesce(e.metadata, () => ( {}))))).join(","),
923
+ messages.map((e) => {
924
+ const { messageId: _messageId, ...rawMetadata } = e.metadata;
925
+ return _dumbo.sql.call(void 0, "%L", JSONParser.stringify(rawMetadata));
926
+ }).join(","),
911
927
  messages.map(() => `'1'`).join(","),
912
928
  messages.map((e) => _dumbo.sql.call(void 0, "%L", e.type)).join(","),
913
929
  messages.map((e) => _dumbo.sql.call(void 0, "%L", e.kind === "Event" ? "E" : "C")).join(","),
@@ -2146,7 +2162,7 @@ var getPostgreSQLEventStore = (connectionString, options = defaultPostgreSQLOpti
2146
2162
  );
2147
2163
  return {
2148
2164
  nextExpectedStreamVersion: appendResult.nextStreamPosition,
2149
- lastEventGlobalPosition: appendResult.lastGlobalPosition,
2165
+ lastEventGlobalPosition: appendResult.globalPositions[appendResult.globalPositions.length - 1],
2150
2166
  createdNewStream: appendResult.nextStreamPosition >= BigInt(events.length)
2151
2167
  };
2152
2168
  },