@event-driven-io/emmett-esdb 0.36.0 → 0.38.0-alpha.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.
package/dist/index.js CHANGED
@@ -24,13 +24,14 @@ var ConcurrencyError = class _ConcurrencyError extends EmmettError {
24
24
  };
25
25
 
26
26
  // ../emmett/dist/index.js
27
- import { v4 as uuid3 } from "uuid";
27
+ import { v4 as uuid5 } from "uuid";
28
28
  import { TransformStream } from "web-streams-polyfill";
29
29
  import { v4 as uuid2 } from "uuid";
30
30
  import { v4 as uuid } from "uuid";
31
31
  import { TransformStream as TransformStream2 } from "web-streams-polyfill";
32
+ import { v7 as uuid3 } from "uuid";
32
33
  import retry from "async-retry";
33
- import { v7 as uuid4 } from "uuid";
34
+ import { v4 as uuid4 } from "uuid";
34
35
  import { ReadableStream } from "web-streams-polyfill";
35
36
  import "web-streams-polyfill";
36
37
  import { TransformStream as TransformStream3 } from "web-streams-polyfill";
@@ -102,12 +103,39 @@ var NotifyAboutNoActiveReadersStream = class extends TransformStream2 {
102
103
  }
103
104
  }
104
105
  };
106
+ var ParseError = class extends Error {
107
+ constructor(text) {
108
+ super(`Cannot parse! ${text}`);
109
+ }
110
+ };
111
+ var JSONParser = {
112
+ stringify: (value, options) => {
113
+ return JSON.stringify(
114
+ options?.map ? options.map(value) : value,
115
+ //TODO: Consider adding support to DateTime and adding specific format to mark that's a bigint
116
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
117
+ (_, v) => typeof v === "bigint" ? v.toString() : v
118
+ );
119
+ },
120
+ parse: (text, options) => {
121
+ const parsed = JSON.parse(text, options?.reviver);
122
+ if (options?.typeCheck && !options?.typeCheck(parsed))
123
+ throw new ParseError(text);
124
+ return options?.map ? options.map(parsed) : parsed;
125
+ }
126
+ };
105
127
  var asyncRetry = async (fn, opts) => {
106
128
  if (opts === void 0 || opts.retries === 0) return fn();
107
129
  return retry(
108
130
  async (bail) => {
109
131
  try {
110
- return await fn();
132
+ const result = await fn();
133
+ if (opts?.shouldRetryResult && opts.shouldRetryResult(result)) {
134
+ throw new EmmettError(
135
+ `Retrying because of result: ${JSONParser.stringify(result)}`
136
+ );
137
+ }
138
+ return result;
111
139
  } catch (error2) {
112
140
  if (opts?.shouldRetryError && !opts.shouldRetryError(error2)) {
113
141
  bail(error2);
@@ -266,7 +294,7 @@ import {
266
294
  } from "@eventstore/db-client";
267
295
 
268
296
  // src/eventStore/consumers/eventStoreDBEventStoreProcessor.ts
269
- import { v7 as uuid5 } from "uuid";
297
+ import { v7 as uuid6 } from "uuid";
270
298
  var EventStoreDBEventStoreProcessor = {
271
299
  result: {
272
300
  skip: (options) => ({
@@ -282,7 +310,7 @@ var EventStoreDBEventStoreProcessor = {
282
310
  var eventStoreDBEventStoreProcessor = (options) => {
283
311
  const { eachMessage } = options;
284
312
  let isActive = true;
285
- options.processorId = options.processorId ?? uuid5();
313
+ options.processorId = options.processorId ?? uuid6();
286
314
  return {
287
315
  id: options.processorId,
288
316
  start: (_client) => {
@@ -495,40 +523,66 @@ var subscribe = (client, from, options) => from == void 0 || from.stream == $all
495
523
  fromRevision: toStreamPosition(options.startFrom),
496
524
  ...from.options ?? {}
497
525
  });
526
+ var isDatabaseUnavailableError = (error) => error instanceof Error && "type" in error && error.type === "unavailable" && "code" in error && error.code === 14;
527
+ var EventStoreDBResubscribeDefaultOptions = {
528
+ forever: true,
529
+ minTimeout: 100,
530
+ factor: 1.5,
531
+ shouldRetryError: (error) => !isDatabaseUnavailableError(error)
532
+ };
498
533
  var eventStoreDBSubscription = ({
499
534
  client,
500
535
  from,
501
536
  //batchSize,
502
- eachBatch
537
+ eachBatch,
538
+ resilience
503
539
  }) => {
504
540
  let isRunning = false;
505
541
  let start;
506
542
  let subscription;
507
- const pullMessages = async (options) => {
543
+ const resubscribeOptions = resilience?.resubscribeOptions ?? {
544
+ ...EventStoreDBResubscribeDefaultOptions,
545
+ shouldRetryResult: () => isRunning,
546
+ shouldRetryError: (error) => isRunning && EventStoreDBResubscribeDefaultOptions.shouldRetryError(error)
547
+ };
548
+ const pipeMessages = (options) => {
508
549
  subscription = subscribe(client, from, options);
509
- return new Promise((resolve, reject) => {
510
- finished(
511
- subscription.on("data", async (resolvedEvent) => {
512
- if (!resolvedEvent.event) return;
513
- const event = mapFromESDBEvent(
514
- resolvedEvent.event
515
- );
516
- const result = await eachBatch({ messages: [event] });
517
- if (result && result.type === "STOP") {
518
- await subscription.unsubscribe();
519
- }
520
- }),
521
- (error) => {
522
- if (!error) {
550
+ return asyncRetry(
551
+ () => new Promise((resolve, reject) => {
552
+ finished(
553
+ subscription.on("data", async (resolvedEvent) => {
554
+ if (!resolvedEvent.event) return;
555
+ const event = mapFromESDBEvent(
556
+ resolvedEvent.event
557
+ );
558
+ const result = await eachBatch({ messages: [event] });
559
+ if (result && result.type === "STOP") {
560
+ isRunning = false;
561
+ await subscription.unsubscribe();
562
+ }
563
+ from = {
564
+ stream: from?.stream ?? $all,
565
+ options: {
566
+ ...from?.options ?? {},
567
+ ...!from || from?.stream === $all ? {
568
+ fromPosition: resolvedEvent.event.position
569
+ } : { fromRevision: resolvedEvent.event.revision }
570
+ }
571
+ };
572
+ }),
573
+ (error) => {
574
+ if (error) {
575
+ console.error(`Received error: ${JSON.stringify(error)}.`);
576
+ reject(error);
577
+ return;
578
+ }
523
579
  console.info(`Stopping subscription.`);
524
580
  resolve();
525
- return;
526
581
  }
527
- console.error(`Received error: ${JSON.stringify(error)}.`);
528
- reject(error);
529
- }
530
- );
531
- });
582
+ );
583
+ }),
584
+ resubscribeOptions
585
+ );
532
586
  };
533
587
  return {
534
588
  get isRunning() {
@@ -538,7 +592,7 @@ var eventStoreDBSubscription = ({
538
592
  if (isRunning) return start;
539
593
  start = (async () => {
540
594
  isRunning = true;
541
- return pullMessages(options);
595
+ return pipeMessages(options);
542
596
  })();
543
597
  return start;
544
598
  },
@@ -588,7 +642,8 @@ var eventStoreDBEventStoreConsumer = (options) => {
588
642
  client,
589
643
  from: options.from,
590
644
  eachBatch,
591
- batchSize: pulling?.batchSize ?? DefaultEventStoreDBEventStoreProcessorBatchSize
645
+ batchSize: pulling?.batchSize ?? DefaultEventStoreDBEventStoreProcessorBatchSize,
646
+ resilience: options.resilience
592
647
  });
593
648
  const stop = async () => {
594
649
  if (!isRunning) return;
@@ -638,10 +693,12 @@ export {
638
693
  DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs,
639
694
  EventStoreDBEventStoreDefaultStreamVersion,
640
695
  EventStoreDBEventStoreProcessor,
696
+ EventStoreDBResubscribeDefaultOptions,
641
697
  eventStoreDBEventStoreConsumer,
642
698
  eventStoreDBEventStoreProcessor,
643
699
  eventStoreDBSubscription,
644
700
  getEventStoreDBEventStore,
701
+ isDatabaseUnavailableError,
645
702
  mapFromESDBEvent,
646
703
  zipEventStoreDBEventStoreMessageBatchPullerStartFrom
647
704
  };