@flowcore/data-pump 0.3.5 → 0.4.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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0](https://github.com/flowcore-io/data-pump/compare/v0.3.5...v0.4.0) (2025-03-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * poller notifier and failedHandler ([e93cf5b](https://github.com/flowcore-io/data-pump/commit/e93cf5ba37f5236d21a7fc9722795fa8f563f97b))
9
+
3
10
  ## [0.3.5](https://github.com/flowcore-io/data-pump/compare/v0.3.4...v0.3.5) (2025-03-26)
4
11
 
5
12
 
@@ -1,5 +1,20 @@
1
1
  import type { FlowcoreEvent } from "../deps/jsr.io/@flowcore/sdk/1.21.1/src/mod.js";
2
2
  import type { FlowcoreDataPumpAuth, FlowcoreDataPumpDataSource, FlowcoreDataPumpProcessor, FlowcoreDataPumpState, FlowcoreDataPumpStateManager, FlowcoreLogger } from "./types.js";
3
+ interface FlowcoreDataPumpNotifierNatsOptions {
4
+ type: "nats";
5
+ servers: string[];
6
+ }
7
+ interface FlowcoreDataPumpNotifierWebsocketOptions {
8
+ type: "websocket";
9
+ }
10
+ interface FlowcoreDataPumpNotifierPollerOptions {
11
+ type: "poller";
12
+ /**
13
+ * The interval in milliseconds to poll the data pump state (min 1000 ms)
14
+ */
15
+ intervalMs: number;
16
+ }
17
+ type FlowcoreDataPumpNotifierOptions = FlowcoreDataPumpNotifierNatsOptions | FlowcoreDataPumpNotifierWebsocketOptions | FlowcoreDataPumpNotifierPollerOptions;
3
18
  export interface FlowcoreDataPumpOptions {
4
19
  auth: FlowcoreDataPumpAuth;
5
20
  dataSource: FlowcoreDataPumpDataSource;
@@ -8,7 +23,7 @@ export interface FlowcoreDataPumpOptions {
8
23
  maxRedeliveryCount?: number;
9
24
  achknowledgeTimeoutMs?: number;
10
25
  processor?: FlowcoreDataPumpProcessor;
11
- natsServers?: string[];
26
+ notifier?: FlowcoreDataPumpNotifierOptions;
12
27
  logger?: FlowcoreLogger;
13
28
  stopAt?: Date;
14
29
  }
@@ -45,4 +60,5 @@ export declare class FlowcoreDataPump {
45
60
  private waiterBufferEmpty?;
46
61
  private waitForBufferEmpty;
47
62
  }
63
+ export {};
48
64
  //# sourceMappingURL=data-pump.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-pump.d.ts","sourceRoot":"","sources":["../../src/data-pump/data-pump.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAMnF,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,EAC5B,cAAc,EACf,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,UAAU,EAAE,0BAA0B,CAAA;IACtC,YAAY,EAAE,4BAA4B,CAAA;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,yBAAyB,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAkBD,qBAAa,gBAAgB;IASzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAZ1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAC,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAC,CAAuB;IAE3C,OAAO;IAaP,IAAW,SAAS,IAAI,OAAO,CAE9B;WAEa,MAAM,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB;IA2B3D,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAyC9D,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAQjE,IAAI,CAAC,SAAS,UAAQ,GAAG,IAAI;IAWpC,OAAO,CAAC,WAAW;YAaL,IAAI;IAmEL,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAoCjD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE;YA0B7B,MAAM;YAgDN,WAAW;IAiBzB,OAAO,CAAC,mBAAmB;IA4D3B,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,YAAY,CAAC,CAAY;YACnB,aAAa;IAO3B,OAAO,CAAC,qBAAqB,CAAC,CAAY;YAC5B,sBAAsB;IAOpC,OAAO,CAAC,iBAAiB,CAAC,CAAY;YACxB,kBAAkB;CAWjC"}
1
+ {"version":3,"file":"data-pump.d.ts","sourceRoot":"","sources":["../../src/data-pump/data-pump.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAMnF,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,EAC5B,cAAc,EACf,MAAM,YAAY,CAAA;AAEnB,UAAU,mCAAmC;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,UAAU,wCAAwC;IAChD,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,UAAU,qCAAqC;IAC7C,IAAI,EAAE,QAAQ,CAAA;IACd;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,KAAK,+BAA+B,GAChC,mCAAmC,GACnC,wCAAwC,GACxC,qCAAqC,CAAA;AAEzC,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,UAAU,EAAE,0BAA0B,CAAA;IACtC,YAAY,EAAE,4BAA4B,CAAA;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,yBAAyB,CAAA;IACrC,QAAQ,CAAC,EAAE,+BAA+B,CAAA;IAC1C,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAkBD,qBAAa,gBAAgB;IASzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAZ1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAC,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAC,CAAuB;IAE3C,OAAO;IAaP,IAAW,SAAS,IAAI,OAAO,CAE9B;WAEa,MAAM,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB;IA4B3D,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAyC9D,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAQjE,IAAI,CAAC,SAAS,UAAQ,GAAG,IAAI;IAWpC,OAAO,CAAC,WAAW;YAaL,IAAI;IAmEL,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAoCjD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE;YA0B7B,MAAM;YAiDN,WAAW;IAiBzB,OAAO,CAAC,mBAAmB;IA4D3B,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,YAAY,CAAC,CAAY;YACnB,aAAa;IAO3B,OAAO,CAAC,qBAAqB,CAAC,CAAY;YAC5B,sBAAsB;IAOpC,OAAO,CAAC,iBAAiB,CAAC,CAAY;YACxB,kBAAkB;CAWjC"}
@@ -108,7 +108,8 @@ export class FlowcoreDataPump {
108
108
  const notifier = new FlowcoreNotifier({
109
109
  auth: options.auth,
110
110
  dataSource: options.dataSource,
111
- natsServers: options.natsServers,
111
+ natsServers: options.notifier?.type === "nats" ? options.notifier.servers : undefined,
112
+ pollerIntervalMs: options.notifier?.type === "poller" ? options.notifier.intervalMs : undefined,
112
113
  logger: options.logger,
113
114
  });
114
115
  return new FlowcoreDataPump(dataSource, notifier, options.stateManager, {
@@ -218,7 +219,7 @@ export class FlowcoreDataPump {
218
219
  const previousTimeBucket = this.bufferState.timeBucket;
219
220
  this.bufferState.timeBucket = format(startOfHour(utc(new Date())), "yyyyMMddHH0000");
220
221
  if (previousTimeBucket === this.bufferState.timeBucket && !events.length) {
221
- this.logger?.info("Going live...");
222
+ this.logger?.debug("Going live...");
222
223
  this.abortController = new AbortController();
223
224
  await this.notifier.wait(this.abortController.signal);
224
225
  }
@@ -314,6 +315,7 @@ export class FlowcoreDataPump {
314
315
  return;
315
316
  }
316
317
  this.logger?.info(`Failed ${failedEvents.length} events`);
318
+ void this.options.processor?.failedHandler?.(failedEvents);
317
319
  if (this.buffer.length <= this.options.bufferSize - this.options.bufferThreshold) {
318
320
  this.waiterBufferThreshold?.();
319
321
  }
@@ -329,11 +331,11 @@ export class FlowcoreDataPump {
329
331
  try {
330
332
  const events = await this.reserve(this.options.processor?.concurrency ?? 1);
331
333
  await this.options.processor?.handler(events);
332
- this.logger?.debug(`Processed ${events.length} events`);
333
334
  await this.acknowledge(events.map((event) => event.eventId));
334
335
  }
335
336
  catch (error) {
336
- this.logger?.error(error);
337
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
338
+ this.logger?.error(`Failed to process events: ${errorMessage}`);
337
339
  }
338
340
  }
339
341
  }
@@ -1,8 +1,9 @@
1
1
  import type { FlowcoreDataPumpAuth, FlowcoreDataPumpDataSource, FlowcoreLogger } from "./types.js";
2
2
  export interface FlowcoreNotifierOptions {
3
- auth: FlowcoreDataPumpAuth;
4
3
  dataSource: FlowcoreDataPumpDataSource;
4
+ auth: FlowcoreDataPumpAuth;
5
5
  natsServers?: string[];
6
+ pollerIntervalMs?: number;
6
7
  timeoutMs?: number;
7
8
  logger?: FlowcoreLogger;
8
9
  }
@@ -16,6 +17,7 @@ export declare class FlowcoreNotifier {
16
17
  private timer?;
17
18
  constructor(options: FlowcoreNotifierOptions);
18
19
  wait(signal?: AbortSignal): Promise<void>;
20
+ private waitPoller;
19
21
  private waitNats;
20
22
  private onWebSocketEvent;
21
23
  private waitWebSocket;
@@ -1 +1 @@
1
- {"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,UAAU,EAAE,0BAA0B,CAAA;IACtC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAC,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAOtD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YAOlB,QAAQ;IAuCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;IAmC3B,OAAO,CAAC,aAAa;CAgBtB"}
1
+ {"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,0BAA0B,CAAA;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAC,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAOtD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YASlB,UAAU;YAUV,QAAQ;IAuCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;IAmC3B,OAAO,CAAC,aAAa;CAgBtB"}
@@ -58,10 +58,22 @@ export class FlowcoreNotifier {
58
58
  if (this.options.natsServers) {
59
59
  return this.waitNats();
60
60
  }
61
+ else if (this.options.pollerIntervalMs) {
62
+ return this.waitPoller(this.options.pollerIntervalMs, signal);
63
+ }
61
64
  return this.waitWebSocket(signal);
62
65
  }
66
+ async waitPoller(intervalMs, signal) {
67
+ this.options.logger?.debug("Waiting for poller");
68
+ const promise = new Promise((resolve) => {
69
+ this.eventResolver = resolve;
70
+ });
71
+ signal?.addEventListener("abort", () => this.eventResolver?.());
72
+ setTimeout(() => this.eventResolver?.(), Math.min(intervalMs, 1000));
73
+ await promise;
74
+ }
63
75
  async waitNats(signal) {
64
- this.options.logger?.info("Waiting for nats");
76
+ this.options.logger?.debug("Waiting for nats");
65
77
  if (!this.nats) {
66
78
  this.nats = await Nats.connect({ servers: this.options.natsServers });
67
79
  }
@@ -28,5 +28,6 @@ export interface FlowcoreLogger {
28
28
  export interface FlowcoreDataPumpProcessor {
29
29
  concurrency?: number;
30
30
  handler: (events: FlowcoreEvent[]) => Promise<void>;
31
+ failedHandler?: (events: FlowcoreEvent[]) => void | Promise<void>;
31
32
  }
32
33
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data-pump/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAEnF,MAAM,MAAM,oBAAoB,GAC5B;IACA,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB,GACC;IACA,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACtC,CAAA;AAEH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,qBAAqB,GAAG,IAAI,CAAA;IACpF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAClE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CAC7E;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data-pump/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAEnF,MAAM,MAAM,oBAAoB,GAC5B;IACA,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB,GACC;IACA,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACtC,CAAA;AAEH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,qBAAqB,GAAG,IAAI,CAAA;IACpF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAClE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CAC7E;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowcore/data-pump",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "description": "Flowcore Data Pump",
5
5
  "homepage": "https://github.com/flowcore-io/flowcore-data-pump#readme",
6
6
  "repository": {
@@ -1,5 +1,20 @@
1
1
  import type { FlowcoreEvent } from "../deps/jsr.io/@flowcore/sdk/1.21.1/src/mod.js";
2
2
  import type { FlowcoreDataPumpAuth, FlowcoreDataPumpDataSource, FlowcoreDataPumpProcessor, FlowcoreDataPumpState, FlowcoreDataPumpStateManager, FlowcoreLogger } from "./types.js";
3
+ interface FlowcoreDataPumpNotifierNatsOptions {
4
+ type: "nats";
5
+ servers: string[];
6
+ }
7
+ interface FlowcoreDataPumpNotifierWebsocketOptions {
8
+ type: "websocket";
9
+ }
10
+ interface FlowcoreDataPumpNotifierPollerOptions {
11
+ type: "poller";
12
+ /**
13
+ * The interval in milliseconds to poll the data pump state (min 1000 ms)
14
+ */
15
+ intervalMs: number;
16
+ }
17
+ type FlowcoreDataPumpNotifierOptions = FlowcoreDataPumpNotifierNatsOptions | FlowcoreDataPumpNotifierWebsocketOptions | FlowcoreDataPumpNotifierPollerOptions;
3
18
  export interface FlowcoreDataPumpOptions {
4
19
  auth: FlowcoreDataPumpAuth;
5
20
  dataSource: FlowcoreDataPumpDataSource;
@@ -8,7 +23,7 @@ export interface FlowcoreDataPumpOptions {
8
23
  maxRedeliveryCount?: number;
9
24
  achknowledgeTimeoutMs?: number;
10
25
  processor?: FlowcoreDataPumpProcessor;
11
- natsServers?: string[];
26
+ notifier?: FlowcoreDataPumpNotifierOptions;
12
27
  logger?: FlowcoreLogger;
13
28
  stopAt?: Date;
14
29
  }
@@ -45,4 +60,5 @@ export declare class FlowcoreDataPump {
45
60
  private waiterBufferEmpty?;
46
61
  private waitForBufferEmpty;
47
62
  }
63
+ export {};
48
64
  //# sourceMappingURL=data-pump.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-pump.d.ts","sourceRoot":"","sources":["../../src/data-pump/data-pump.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAMnF,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,EAC5B,cAAc,EACf,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,UAAU,EAAE,0BAA0B,CAAA;IACtC,YAAY,EAAE,4BAA4B,CAAA;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,yBAAyB,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAkBD,qBAAa,gBAAgB;IASzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAZ1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAC,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAC,CAAuB;IAE3C,OAAO;IAaP,IAAW,SAAS,IAAI,OAAO,CAE9B;WAEa,MAAM,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB;IA2B3D,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAyC9D,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAQjE,IAAI,CAAC,SAAS,UAAQ,GAAG,IAAI;IAWpC,OAAO,CAAC,WAAW;YAaL,IAAI;IAmEL,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAoCjD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE;YA0B7B,MAAM;YAgDN,WAAW;IAiBzB,OAAO,CAAC,mBAAmB;IA4D3B,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,YAAY,CAAC,CAAY;YACnB,aAAa;IAO3B,OAAO,CAAC,qBAAqB,CAAC,CAAY;YAC5B,sBAAsB;IAOpC,OAAO,CAAC,iBAAiB,CAAC,CAAY;YACxB,kBAAkB;CAWjC"}
1
+ {"version":3,"file":"data-pump.d.ts","sourceRoot":"","sources":["../../src/data-pump/data-pump.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAMnF,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,EAC5B,cAAc,EACf,MAAM,YAAY,CAAA;AAEnB,UAAU,mCAAmC;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,UAAU,wCAAwC;IAChD,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,UAAU,qCAAqC;IAC7C,IAAI,EAAE,QAAQ,CAAA;IACd;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,KAAK,+BAA+B,GAChC,mCAAmC,GACnC,wCAAwC,GACxC,qCAAqC,CAAA;AAEzC,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,UAAU,EAAE,0BAA0B,CAAA;IACtC,YAAY,EAAE,4BAA4B,CAAA;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,yBAAyB,CAAA;IACrC,QAAQ,CAAC,EAAE,+BAA+B,CAAA;IAC1C,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAkBD,qBAAa,gBAAgB;IASzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAZ1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAC,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAC,CAAuB;IAE3C,OAAO;IAaP,IAAW,SAAS,IAAI,OAAO,CAE9B;WAEa,MAAM,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB;IA4B3D,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAyC9D,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAQjE,IAAI,CAAC,SAAS,UAAQ,GAAG,IAAI;IAWpC,OAAO,CAAC,WAAW;YAaL,IAAI;IAmEL,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAoCjD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE;YA0B7B,MAAM;YAiDN,WAAW;IAiBzB,OAAO,CAAC,mBAAmB;IA4D3B,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,YAAY,CAAC,CAAY;YACnB,aAAa;IAO3B,OAAO,CAAC,qBAAqB,CAAC,CAAY;YAC5B,sBAAsB;IAOpC,OAAO,CAAC,iBAAiB,CAAC,CAAY;YACxB,kBAAkB;CAWjC"}
@@ -111,7 +111,8 @@ class FlowcoreDataPump {
111
111
  const notifier = new notifier_js_1.FlowcoreNotifier({
112
112
  auth: options.auth,
113
113
  dataSource: options.dataSource,
114
- natsServers: options.natsServers,
114
+ natsServers: options.notifier?.type === "nats" ? options.notifier.servers : undefined,
115
+ pollerIntervalMs: options.notifier?.type === "poller" ? options.notifier.intervalMs : undefined,
115
116
  logger: options.logger,
116
117
  });
117
118
  return new FlowcoreDataPump(dataSource, notifier, options.stateManager, {
@@ -221,7 +222,7 @@ class FlowcoreDataPump {
221
222
  const previousTimeBucket = this.bufferState.timeBucket;
222
223
  this.bufferState.timeBucket = (0, date_fns_1.format)((0, date_fns_1.startOfHour)((0, utc_1.utc)(new Date())), "yyyyMMddHH0000");
223
224
  if (previousTimeBucket === this.bufferState.timeBucket && !events.length) {
224
- this.logger?.info("Going live...");
225
+ this.logger?.debug("Going live...");
225
226
  this.abortController = new AbortController();
226
227
  await this.notifier.wait(this.abortController.signal);
227
228
  }
@@ -317,6 +318,7 @@ class FlowcoreDataPump {
317
318
  return;
318
319
  }
319
320
  this.logger?.info(`Failed ${failedEvents.length} events`);
321
+ void this.options.processor?.failedHandler?.(failedEvents);
320
322
  if (this.buffer.length <= this.options.bufferSize - this.options.bufferThreshold) {
321
323
  this.waiterBufferThreshold?.();
322
324
  }
@@ -332,11 +334,11 @@ class FlowcoreDataPump {
332
334
  try {
333
335
  const events = await this.reserve(this.options.processor?.concurrency ?? 1);
334
336
  await this.options.processor?.handler(events);
335
- this.logger?.debug(`Processed ${events.length} events`);
336
337
  await this.acknowledge(events.map((event) => event.eventId));
337
338
  }
338
339
  catch (error) {
339
- this.logger?.error(error);
340
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
341
+ this.logger?.error(`Failed to process events: ${errorMessage}`);
340
342
  }
341
343
  }
342
344
  }
@@ -1,8 +1,9 @@
1
1
  import type { FlowcoreDataPumpAuth, FlowcoreDataPumpDataSource, FlowcoreLogger } from "./types.js";
2
2
  export interface FlowcoreNotifierOptions {
3
- auth: FlowcoreDataPumpAuth;
4
3
  dataSource: FlowcoreDataPumpDataSource;
4
+ auth: FlowcoreDataPumpAuth;
5
5
  natsServers?: string[];
6
+ pollerIntervalMs?: number;
6
7
  timeoutMs?: number;
7
8
  logger?: FlowcoreLogger;
8
9
  }
@@ -16,6 +17,7 @@ export declare class FlowcoreNotifier {
16
17
  private timer?;
17
18
  constructor(options: FlowcoreNotifierOptions);
18
19
  wait(signal?: AbortSignal): Promise<void>;
20
+ private waitPoller;
19
21
  private waitNats;
20
22
  private onWebSocketEvent;
21
23
  private waitWebSocket;
@@ -1 +1 @@
1
- {"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,UAAU,EAAE,0BAA0B,CAAA;IACtC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAC,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAOtD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YAOlB,QAAQ;IAuCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;IAmC3B,OAAO,CAAC,aAAa;CAgBtB"}
1
+ {"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,0BAA0B,CAAA;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAC,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAOtD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YASlB,UAAU;YAUV,QAAQ;IAuCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;IAmC3B,OAAO,CAAC,aAAa;CAgBtB"}
@@ -84,10 +84,22 @@ class FlowcoreNotifier {
84
84
  if (this.options.natsServers) {
85
85
  return this.waitNats();
86
86
  }
87
+ else if (this.options.pollerIntervalMs) {
88
+ return this.waitPoller(this.options.pollerIntervalMs, signal);
89
+ }
87
90
  return this.waitWebSocket(signal);
88
91
  }
92
+ async waitPoller(intervalMs, signal) {
93
+ this.options.logger?.debug("Waiting for poller");
94
+ const promise = new Promise((resolve) => {
95
+ this.eventResolver = resolve;
96
+ });
97
+ signal?.addEventListener("abort", () => this.eventResolver?.());
98
+ setTimeout(() => this.eventResolver?.(), Math.min(intervalMs, 1000));
99
+ await promise;
100
+ }
89
101
  async waitNats(signal) {
90
- this.options.logger?.info("Waiting for nats");
102
+ this.options.logger?.debug("Waiting for nats");
91
103
  if (!this.nats) {
92
104
  this.nats = await Nats.connect({ servers: this.options.natsServers });
93
105
  }
@@ -28,5 +28,6 @@ export interface FlowcoreLogger {
28
28
  export interface FlowcoreDataPumpProcessor {
29
29
  concurrency?: number;
30
30
  handler: (events: FlowcoreEvent[]) => Promise<void>;
31
+ failedHandler?: (events: FlowcoreEvent[]) => void | Promise<void>;
31
32
  }
32
33
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data-pump/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAEnF,MAAM,MAAM,oBAAoB,GAC5B;IACA,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB,GACC;IACA,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACtC,CAAA;AAEH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,qBAAqB,GAAG,IAAI,CAAA;IACpF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAClE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CAC7E;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data-pump/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAEnF,MAAM,MAAM,oBAAoB,GAC5B;IACA,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB,GACC;IACA,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACtC,CAAA;AAEH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,qBAAqB,GAAG,IAAI,CAAA;IACpF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAClE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACnE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CAC7E;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClE"}