@flowcore/data-pump 0.11.0 → 0.12.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/esm/data-pump/data-pump.d.ts +1 -0
  3. package/esm/data-pump/data-pump.d.ts.map +1 -1
  4. package/esm/data-pump/data-pump.js +11 -0
  5. package/esm/data-pump/no-op-logger.d.ts +3 -0
  6. package/esm/data-pump/no-op-logger.d.ts.map +1 -0
  7. package/esm/data-pump/no-op-logger.js +6 -0
  8. package/esm/data-pump/notifier.js +1 -1
  9. package/esm/mod.d.ts +1 -2
  10. package/esm/mod.d.ts.map +1 -1
  11. package/esm/mod.js +1 -2
  12. package/package.json +1 -1
  13. package/script/data-pump/data-pump.d.ts +1 -0
  14. package/script/data-pump/data-pump.d.ts.map +1 -1
  15. package/script/data-pump/data-pump.js +11 -0
  16. package/script/data-pump/no-op-logger.d.ts +3 -0
  17. package/script/data-pump/no-op-logger.d.ts.map +1 -0
  18. package/script/data-pump/no-op-logger.js +9 -0
  19. package/script/data-pump/notifier.js +2 -2
  20. package/script/mod.d.ts +1 -2
  21. package/script/mod.d.ts.map +1 -1
  22. package/script/mod.js +1 -2
  23. package/esm/lib/data-pump-create.d.ts +0 -46
  24. package/esm/lib/data-pump-create.d.ts.map +0 -1
  25. package/esm/lib/data-pump-create.js +0 -64
  26. package/esm/lib/data-pump.d.ts +0 -80
  27. package/esm/lib/data-pump.d.ts.map +0 -1
  28. package/esm/lib/data-pump.js +0 -437
  29. package/esm/lib/nats-notifier.d.ts +0 -18
  30. package/esm/lib/nats-notifier.d.ts.map +0 -1
  31. package/esm/lib/nats-notifier.js +0 -88
  32. package/esm/lib/ws-notifier.d.ts +0 -37
  33. package/esm/lib/ws-notifier.d.ts.map +0 -1
  34. package/esm/lib/ws-notifier.js +0 -86
  35. package/script/lib/data-pump-create.d.ts +0 -46
  36. package/script/lib/data-pump-create.d.ts.map +0 -1
  37. package/script/lib/data-pump-create.js +0 -68
  38. package/script/lib/data-pump.d.ts +0 -80
  39. package/script/lib/data-pump.d.ts.map +0 -1
  40. package/script/lib/data-pump.js +0 -441
  41. package/script/lib/nats-notifier.d.ts +0 -18
  42. package/script/lib/nats-notifier.d.ts.map +0 -1
  43. package/script/lib/nats-notifier.js +0 -115
  44. package/script/lib/ws-notifier.d.ts +0 -37
  45. package/script/lib/ws-notifier.d.ts.map +0 -1
  46. package/script/lib/ws-notifier.js +0 -90
@@ -1,46 +0,0 @@
1
- import { type FlowcoreEvent } from "../deps/jsr.io/@flowcore/sdk/1.26.3/src/mod.js";
2
- import { DataPump, type DataPumpStateManager, type Logger } from "./data-pump.js";
3
- export declare const noOpLogger: Logger;
4
- interface DataPumpClientOptionsAuthOidcClient {
5
- oidcClient: {
6
- getToken: () => Promise<{
7
- accessToken: string;
8
- }>;
9
- };
10
- }
11
- interface DataPumpClientOptionsAuthApiKey {
12
- apiKey: string;
13
- apiKeyId: string;
14
- }
15
- type DataPumpClientOptionsAuth = DataPumpClientOptionsAuthOidcClient | DataPumpClientOptionsAuthApiKey;
16
- /**
17
- * Create data pump client options
18
- */
19
- export interface DataPumpClientOptions {
20
- logger?: Logger;
21
- auth: DataPumpClientOptionsAuth;
22
- dataSource: {
23
- tenant: string;
24
- dataCore: string;
25
- flowType: string;
26
- eventTypes: string[];
27
- };
28
- buffer?: {
29
- size?: number;
30
- threshold?: number;
31
- maxRedeliveryCount?: number;
32
- achknowledgeTimeoutMs?: number;
33
- };
34
- stateManager?: DataPumpStateManager;
35
- processor?: {
36
- concurrency?: number;
37
- onEvents: (events: FlowcoreEvent[]) => Promise<boolean> | boolean;
38
- onFailedEvents?: (events: FlowcoreEvent[]) => Promise<void> | void;
39
- onDone?: () => Promise<void> | void;
40
- };
41
- stopAt?: Date;
42
- natsServers?: string[];
43
- }
44
- export declare function createDataPump(options: DataPumpClientOptions): DataPump;
45
- export {};
46
- //# sourceMappingURL=data-pump-create.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-pump-create.d.ts","sourceRoot":"","sources":["../../src/lib/data-pump-create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,gDAAgD,CAAA;AACnG,OAAO,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAIjF,eAAO,MAAM,UAAU,EAAE,MAKxB,CAAA;AAED,UAAU,mCAAmC;IAC3C,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,OAAO,CAAC;YAAE,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KACjD,CAAA;CACF;AAED,UAAU,+BAA+B;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,KAAK,yBAAyB,GAAG,mCAAmC,GAAG,+BAA+B,CAAA;AAEtG;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,yBAAyB,CAAA;IAC/B,UAAU,EAAE;QACV,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,EAAE,CAAA;KACrB,CAAA;IACD,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;KAC/B,CAAA;IACD,YAAY,CAAC,EAAE,oBAAoB,CAAA;IACnC,SAAS,CAAC,EAAE;QACV,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;QACjE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;QAClE,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;KACpC,CAAA;IACD,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,QAAQ,CA0DvE"}
@@ -1,68 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noOpLogger = void 0;
4
- exports.createDataPump = createDataPump;
5
- const mod_js_1 = require("../deps/jsr.io/@flowcore/sdk/1.26.3/src/mod.js");
6
- const data_pump_js_1 = require("./data-pump.js");
7
- const ws_notifier_js_1 = require("./ws-notifier.js");
8
- const nats_notifier_js_1 = require("./nats-notifier.js");
9
- exports.noOpLogger = {
10
- debug: () => { },
11
- info: () => { },
12
- warn: () => { },
13
- error: console.error,
14
- };
15
- function createDataPump(options) {
16
- let flowcoreClient;
17
- if ("oidcClient" in options.auth) {
18
- const authClient = options.auth.oidcClient;
19
- flowcoreClient = new mod_js_1.FlowcoreClient({
20
- getBearerToken: async () => (await authClient.getToken()).accessToken ?? null,
21
- });
22
- }
23
- else {
24
- flowcoreClient = new mod_js_1.FlowcoreClient({
25
- apiKey: options.auth.apiKey,
26
- apiKeyId: options.auth.apiKeyId,
27
- });
28
- }
29
- const stateManager = options.stateManager ?? {
30
- getState: () => null,
31
- setState: () => { },
32
- };
33
- const notifier = options.natsServers
34
- ? new nats_notifier_js_1.NatsNotifier({
35
- servers: options.natsServers,
36
- })
37
- : new ws_notifier_js_1.WebSocketNotifier({
38
- auth: options.auth,
39
- dataSource: options.dataSource,
40
- logger: options.logger,
41
- });
42
- const bufferSize = options.buffer?.size ?? 1000;
43
- const buffer = {
44
- size: bufferSize,
45
- threshold: options.buffer?.threshold ?? Math.round(bufferSize * 0.1),
46
- maxRedeliveryCount: options.buffer?.maxRedeliveryCount ?? 3,
47
- achknowledgeTimeoutMs: options.buffer?.achknowledgeTimeoutMs ?? 10_000,
48
- };
49
- const processor = options.processor
50
- ? {
51
- concurrency: options.processor.concurrency ?? 1,
52
- onEvents: options.processor.onEvents,
53
- onFailedEvents: options.processor.onFailedEvents,
54
- onDone: options.processor.onDone,
55
- }
56
- : undefined;
57
- const dataPump = new data_pump_js_1.DataPump({
58
- flowcoreClient,
59
- stateManager,
60
- dataSource: options.dataSource,
61
- buffer,
62
- processor,
63
- notifier: notifier.getNotifier(),
64
- logger: options.logger,
65
- stopAt: options.stopAt,
66
- });
67
- return dataPump;
68
- }
@@ -1,80 +0,0 @@
1
- import { type FlowcoreClient, type FlowcoreEvent } from "../deps/jsr.io/@flowcore/sdk/1.26.3/src/mod.js";
2
- export interface Logger {
3
- debug(message: string, ...meta: unknown[]): void;
4
- info(message: string, ...meta: unknown[]): void;
5
- warn(message: string, ...meta: unknown[]): void;
6
- error(message: string | Error, ...meta: unknown[]): void;
7
- }
8
- interface DataPumpOptions {
9
- flowcoreClient: FlowcoreClient;
10
- stateManager: DataPumpStateManager;
11
- logger?: Logger;
12
- notifier: DataPumpNotifier;
13
- dataSource: {
14
- tenant: string;
15
- dataCore: string;
16
- flowType: string;
17
- eventTypes: string[];
18
- };
19
- buffer: {
20
- size: number;
21
- threshold: number;
22
- maxRedeliveryCount: number;
23
- achknowledgeTimeoutMs: number;
24
- };
25
- processor?: {
26
- concurrency: number;
27
- onEvents: (events: FlowcoreEvent[]) => Promise<boolean> | boolean;
28
- onFailedEvents?: (events: FlowcoreEvent[]) => Promise<void> | void;
29
- onDone?: () => Promise<void> | void;
30
- };
31
- stopAt?: Date;
32
- }
33
- export interface DataPumpState {
34
- timeBucket: string;
35
- eventId?: string;
36
- }
37
- export interface DataPumpStateManager {
38
- getState: () => Promise<DataPumpState | null> | DataPumpState | null;
39
- setState?: (state: DataPumpState) => Promise<void> | void;
40
- stopAt?: () => Date;
41
- }
42
- export interface DataPumpNotifier {
43
- wait(dataSource: DataPumpOptions["dataSource"] & {
44
- dataCoreId: string;
45
- }, signal?: AbortSignal): Promise<void>;
46
- }
47
- export declare class DataPump {
48
- private options;
49
- private logger?;
50
- private state;
51
- private _timeBuckets;
52
- private buffer;
53
- private bufferWaiter;
54
- private waiter;
55
- private running;
56
- private notifierAbortController?;
57
- private dataCoreId?;
58
- private stopAt?;
59
- constructor(options: DataPumpOptions);
60
- start(): Promise<void>;
61
- stop(): void;
62
- private proceccor;
63
- private eventBufferLoop;
64
- private reOpen;
65
- private updateState;
66
- private get timeBuckets();
67
- private getClosestTimeBucket;
68
- private updateTimeBuckets;
69
- private pullInner;
70
- private acknowledgeInner;
71
- private waitForNotifier;
72
- private waitForEvents;
73
- private waitForBufferThreshold;
74
- private getNowTimeBucket;
75
- private getDataCoreId;
76
- pull(amount: number): Promise<FlowcoreEvent[]>;
77
- acknowledge(eventIds: string[]): Promise<void>;
78
- }
79
- export {};
80
- //# sourceMappingURL=data-pump.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-pump.d.ts","sourceRoot":"","sources":["../../src/lib/data-pump.ts"],"names":[],"mappings":"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"}
@@ -1,441 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DataPump = void 0;
4
- const mod_js_1 = require("../deps/jsr.io/@flowcore/sdk/1.26.3/src/mod.js");
5
- const mod_js_2 = require("../deps/jsr.io/@flowcore/time-uuid/0.1.2/src/mod.js");
6
- const date_fns_1 = require("date-fns");
7
- const utc_1 = require("@date-fns/utc");
8
- var FlowcoreBufferEventStatus;
9
- (function (FlowcoreBufferEventStatus) {
10
- FlowcoreBufferEventStatus["OPEN"] = "open";
11
- FlowcoreBufferEventStatus["DELIVERED"] = "delivered";
12
- })(FlowcoreBufferEventStatus || (FlowcoreBufferEventStatus = {}));
13
- class DataPump {
14
- constructor(options) {
15
- Object.defineProperty(this, "options", {
16
- enumerable: true,
17
- configurable: true,
18
- writable: true,
19
- value: options
20
- });
21
- Object.defineProperty(this, "logger", {
22
- enumerable: true,
23
- configurable: true,
24
- writable: true,
25
- value: void 0
26
- });
27
- Object.defineProperty(this, "state", {
28
- enumerable: true,
29
- configurable: true,
30
- writable: true,
31
- value: void 0
32
- });
33
- Object.defineProperty(this, "_timeBuckets", {
34
- enumerable: true,
35
- configurable: true,
36
- writable: true,
37
- value: []
38
- });
39
- Object.defineProperty(this, "buffer", {
40
- enumerable: true,
41
- configurable: true,
42
- writable: true,
43
- value: []
44
- });
45
- Object.defineProperty(this, "bufferWaiter", {
46
- enumerable: true,
47
- configurable: true,
48
- writable: true,
49
- value: null
50
- });
51
- Object.defineProperty(this, "waiter", {
52
- enumerable: true,
53
- configurable: true,
54
- writable: true,
55
- value: null
56
- });
57
- Object.defineProperty(this, "running", {
58
- enumerable: true,
59
- configurable: true,
60
- writable: true,
61
- value: false
62
- });
63
- Object.defineProperty(this, "notifierAbortController", {
64
- enumerable: true,
65
- configurable: true,
66
- writable: true,
67
- value: void 0
68
- });
69
- Object.defineProperty(this, "dataCoreId", {
70
- enumerable: true,
71
- configurable: true,
72
- writable: true,
73
- value: void 0
74
- });
75
- Object.defineProperty(this, "stopAt", {
76
- enumerable: true,
77
- configurable: true,
78
- writable: true,
79
- value: void 0
80
- });
81
- this.state = {
82
- timeBucket: this.getNowTimeBucket(),
83
- };
84
- this.logger = options.logger ?? undefined;
85
- }
86
- async start() {
87
- if (this.running) {
88
- return;
89
- }
90
- await this.updateTimeBuckets();
91
- if (this.options.stopAt) {
92
- const timeBucket = (0, date_fns_1.format)((0, date_fns_1.startOfHour)((0, utc_1.utc)(this.options.stopAt)), "yyyyMMddHH0000");
93
- const lastTimeBucket = this.getClosestTimeBucket(timeBucket, true);
94
- const lastEventId = mod_js_2.TimeUuid.fromDate(this.options.stopAt).toString();
95
- this.stopAt = {
96
- timeBucket: lastTimeBucket,
97
- eventId: lastEventId,
98
- eventBufferReached: false,
99
- };
100
- this.logger?.debug("stop at", `${this.stopAt.timeBucket} @ ${this.stopAt.eventId}`);
101
- }
102
- const newState = await this.options.stateManager.getState();
103
- if (!newState) {
104
- this.state.timeBucket = this.getClosestTimeBucket(this.getNowTimeBucket());
105
- this.state.eventId = mod_js_2.TimeUuid.now().toString();
106
- }
107
- else {
108
- this.state.timeBucket = this.getClosestTimeBucket(newState.timeBucket);
109
- this.state.eventId = newState.eventId;
110
- }
111
- if (this.stopAt?.timeBucket && this.state.timeBucket > this.stopAt.timeBucket) {
112
- throw new Error("Stop at time is lower than current state");
113
- }
114
- this.running = true;
115
- this.logger?.debug("Starting event buffer loop");
116
- this.eventBufferLoop()
117
- .then(() => this.logger?.debug("Event buffer loop stopped"))
118
- .catch((error) => this.logger?.error("Error in event buffer loop", { error }))
119
- .finally(() => this.stop());
120
- if (this.options.processor) {
121
- this.logger?.debug("Starting processor");
122
- this.proceccor()
123
- .then(() => this.logger?.debug("Processor stopped"))
124
- .catch((error) => this.logger?.error("Error in processor", { error }))
125
- .finally(() => this.stop());
126
- }
127
- }
128
- stop() {
129
- if (!this.running) {
130
- return;
131
- }
132
- this.logger?.debug("Stopping data pump");
133
- this.running = false;
134
- this.notifierAbortController?.abort("stopping");
135
- this.bufferWaiter?.(true);
136
- this.waiter?.(true);
137
- }
138
- async proceccor() {
139
- if (!this.options.processor) {
140
- throw new Error("Processor not set");
141
- }
142
- while (this.running) {
143
- try {
144
- const events = await this.pullInner(this.options.processor.concurrency);
145
- if (!this.running) {
146
- break;
147
- }
148
- const success = await this.options.processor.onEvents(events);
149
- if (success) {
150
- await this.acknowledgeInner(events.map((event) => event.eventId));
151
- }
152
- }
153
- catch (error) {
154
- this.logger?.error("Error in processor", { error });
155
- await this.stop();
156
- }
157
- }
158
- }
159
- async eventBufferLoop() {
160
- // Stop buffer loop if we are not running
161
- if (!this.running) {
162
- return;
163
- }
164
- if (this.stopAt?.eventBufferReached) {
165
- await new Promise((resolve) => setTimeout(resolve, 10_000));
166
- return this.eventBufferLoop();
167
- }
168
- // Buffer is full, wait for some space
169
- if (this.buffer.length >= this.options.buffer.size - this.options.buffer.threshold && this.running) {
170
- this.logger?.debug("Buffer is full, waiting for some space");
171
- await this.waitForBufferThreshold();
172
- }
173
- // Stop buffer loop if we are not running
174
- if (!this.running) {
175
- return;
176
- }
177
- // How many events should we fetch
178
- const eventsToFetch = this.options.buffer.size - this.buffer.length;
179
- this.logger?.info(`fetching events from ${this.state.timeBucket} @ ${this.state.eventId ?? "-"}`);
180
- const timeStart = Date.now();
181
- const command = new mod_js_1.EventsFetchCommand({
182
- tenant: this.options.dataSource.tenant,
183
- dataCoreId: await this.getDataCoreId(),
184
- flowType: this.options.dataSource.flowType,
185
- eventTypes: this.options.dataSource.eventTypes,
186
- timeBucket: this.state.timeBucket,
187
- afterEventId: this.state.eventId,
188
- pageSize: eventsToFetch,
189
- toEventId: this.stopAt?.eventId,
190
- });
191
- const result = await this.options.flowcoreClient.execute(command);
192
- const time = Date.now() - timeStart;
193
- // Stop buffer loop if we are not running
194
- if (!this.running) {
195
- return;
196
- }
197
- const events = result.events.map((event) => ({
198
- event,
199
- status: FlowcoreBufferEventStatus.OPEN,
200
- deliveryCount: 0,
201
- deliveryTime: 0,
202
- deliveryId: "",
203
- }));
204
- this.buffer.push(...events);
205
- // Check if we have a waiter and if we have events, notify the waiter
206
- events.length && this.waiter?.();
207
- this.logger?.info(`Got ${result.events.length} events from ${this.state.timeBucket} @ ${this.state.eventId ?? "-"} in ${time}ms. Buffer size ${this.buffer.length}`);
208
- // Update buffer state
209
- this.state.eventId = result.events[result.events.length - 1]?.eventId ?? this.state.eventId;
210
- // If we don't have a next cursor move to next time bucket
211
- if (!result.nextCursor) {
212
- // Check if we reached the stop at
213
- if (this.state.timeBucket === this.stopAt?.timeBucket) {
214
- this.stopAt.eventBufferReached = true;
215
- this.logger?.debug("Reached stop at");
216
- this.waiter?.();
217
- return this.eventBufferLoop();
218
- }
219
- // Get next time bucket
220
- const nextTimeBucketIndex = this.timeBuckets.indexOf(this.state.timeBucket) + 1;
221
- // There is no next time bucket
222
- if (!this.timeBuckets[nextTimeBucketIndex]) {
223
- if (result.events.length) {
224
- // If we got events, we can try to get more one more time
225
- this.logger?.debug("Try to get more events");
226
- }
227
- else {
228
- // If we didn't get events, we wait for notifier
229
- await this.waitForNotifier();
230
- }
231
- }
232
- else {
233
- // Set next time bucket
234
- this.state.timeBucket = this.timeBuckets[nextTimeBucketIndex];
235
- }
236
- }
237
- return this.eventBufferLoop();
238
- }
239
- async reOpen(eventIds, deliveryId) {
240
- if (!eventIds.length) {
241
- return;
242
- }
243
- const failedEvents = [];
244
- const reopenedEvents = [];
245
- let lastEvent;
246
- this.buffer = this.buffer.filter((event) => {
247
- if (event.deliveryId === deliveryId && this.options.buffer.maxRedeliveryCount > -1 &&
248
- event.deliveryCount > this.options.buffer.maxRedeliveryCount) {
249
- failedEvents.push(event.event);
250
- lastEvent = event.event;
251
- return false;
252
- }
253
- if (event.deliveryId === deliveryId && eventIds.includes(event.event.eventId)) {
254
- event.status = FlowcoreBufferEventStatus.OPEN;
255
- event.deliveryId = "";
256
- reopenedEvents.push(event.event);
257
- }
258
- return true;
259
- });
260
- if (reopenedEvents.length) {
261
- this.waiter?.();
262
- }
263
- if (this.bufferWaiter && this.buffer.length <= this.options.buffer.size - this.options.buffer.threshold) {
264
- this.bufferWaiter();
265
- }
266
- if (failedEvents.length) {
267
- await this.options.processor?.onFailedEvents?.(failedEvents);
268
- await this.updateState(lastEvent?.eventId);
269
- }
270
- }
271
- updateState(eventId) {
272
- const firstEvent = this.buffer[0];
273
- if (!firstEvent) {
274
- if (eventId) {
275
- const date = mod_js_2.TimeUuid.fromString(eventId).getDate();
276
- const timeBucket = (0, date_fns_1.format)((0, date_fns_1.startOfHour)((0, utc_1.utc)(date)), "yyyyMMddHH0000");
277
- return this.options.stateManager.setState?.({ timeBucket, eventId });
278
- }
279
- return;
280
- }
281
- const timeUuid = mod_js_2.TimeUuid.fromString(firstEvent.event.eventId);
282
- const timeBucket = firstEvent.event.timeBucket;
283
- return this.options.stateManager.setState?.({ timeBucket, eventId: timeUuid.getBefore().toString() });
284
- }
285
- get timeBuckets() {
286
- const timeBucketNow = this.getNowTimeBucket();
287
- if (this._timeBuckets[this._timeBuckets.length - 1] !== timeBucketNow) {
288
- return [...this._timeBuckets, timeBucketNow];
289
- }
290
- return this._timeBuckets;
291
- }
292
- getClosestTimeBucket(timeBucket, getBefore = false) {
293
- if (!timeBucket.match(/^\d{14}$/)) {
294
- throw new Error(`Invalid timebucket: ${timeBucket}`);
295
- }
296
- if (getBefore) {
297
- return (this.timeBuckets.findLast((t) => Number.parseFloat(t) <= Number.parseFloat(timeBucket)) ??
298
- this.timeBuckets[this.timeBuckets.length - 1]);
299
- }
300
- return (this.timeBuckets.find((t) => Number.parseFloat(t) >= Number.parseFloat(timeBucket)) ??
301
- this.timeBuckets[this.timeBuckets.length - 1]);
302
- }
303
- async updateTimeBuckets() {
304
- this._timeBuckets = [];
305
- let first = true;
306
- let cursor;
307
- while (cursor !== undefined || first) {
308
- first = false;
309
- const command = new mod_js_1.EventsFetchTimeBucketsByNamesCommand({
310
- tenant: this.options.dataSource.tenant,
311
- dataCoreId: await this.getDataCoreId(),
312
- flowType: this.options.dataSource.flowType,
313
- eventTypes: this.options.dataSource.eventTypes,
314
- pageSize: 10_000,
315
- });
316
- // sdkCommandCount.labels("EventsFetchTimeBucketsByNamesCommand").inc(1)
317
- const result = await this.options.flowcoreClient.execute(command);
318
- this._timeBuckets.push(...result.timeBuckets);
319
- cursor = result.nextCursor;
320
- }
321
- }
322
- async pullInner(amount) {
323
- if (!this.running) {
324
- throw new Error("Data pump not running");
325
- }
326
- if (this.stopAt?.eventBufferReached && this.buffer.length === 0) {
327
- await this.options.processor?.onDone?.();
328
- await this.stop();
329
- return [];
330
- }
331
- const deliveryId = crypto.randomUUID();
332
- const events = [];
333
- for (const event of this.buffer) {
334
- if (event.status === FlowcoreBufferEventStatus.OPEN) {
335
- event.status = FlowcoreBufferEventStatus.DELIVERED;
336
- event.deliveryCount++;
337
- event.deliveryId = deliveryId;
338
- events.push(event.event);
339
- if (events.length >= amount) {
340
- break;
341
- }
342
- }
343
- }
344
- if (!events.length) {
345
- await this.waitForEvents();
346
- if (!this.running) {
347
- return [];
348
- }
349
- return this.pullInner(amount);
350
- }
351
- setTimeout(() => {
352
- this.reOpen(events.map((event) => event.eventId), deliveryId);
353
- }, this.options.buffer.achknowledgeTimeoutMs);
354
- return events;
355
- }
356
- async acknowledgeInner(eventIds) {
357
- if (!eventIds.length) {
358
- return;
359
- }
360
- // this.logger.info("Acknowledging events", { events: eventIds.length })
361
- const lastEventInBuffer = this.buffer[this.buffer.length - 1];
362
- this.buffer = this.buffer.filter((event) => {
363
- if (eventIds.includes(event.event.eventId)) {
364
- return false;
365
- }
366
- return true;
367
- });
368
- if (this.bufferWaiter && this.buffer.length <= this.options.buffer.size - this.options.buffer.threshold) {
369
- this.bufferWaiter();
370
- }
371
- if (!this.buffer.length) {
372
- await this.updateState(lastEventInBuffer?.event.eventId);
373
- }
374
- else {
375
- await this.updateState();
376
- }
377
- if (!this.buffer.length && this.stopAt?.eventBufferReached) {
378
- await this.options.processor?.onDone?.();
379
- await this.stop();
380
- }
381
- }
382
- async waitForNotifier() {
383
- this.logger?.info("No more events, waiting for notifier...");
384
- this.notifierAbortController = new AbortController();
385
- await this.options.notifier.wait({ ...this.options.dataSource, dataCoreId: await this.getDataCoreId() }, this.notifierAbortController.signal);
386
- this.notifierAbortController = undefined;
387
- }
388
- async waitForEvents() {
389
- this.logger?.debug("No events, waiting for events");
390
- await new Promise((resolve) => {
391
- this.waiter = (stopping) => {
392
- if (!stopping) {
393
- this.logger?.debug("Notifying waiter that we have events");
394
- }
395
- resolve();
396
- };
397
- });
398
- this.waiter = null;
399
- }
400
- async waitForBufferThreshold() {
401
- if (this.buffer.length < this.options.buffer.size - this.options.buffer.threshold) {
402
- return;
403
- }
404
- await new Promise((resolve) => {
405
- this.bufferWaiter = (stopping) => {
406
- if (!stopping) {
407
- this.logger?.debug("Notifying buffer waiter that we are under threshold");
408
- }
409
- resolve();
410
- };
411
- });
412
- this.bufferWaiter = null;
413
- }
414
- getNowTimeBucket() {
415
- return (0, date_fns_1.format)((0, date_fns_1.startOfHour)((0, utc_1.utc)(new Date())), "yyyyMMddHH0000");
416
- }
417
- async getDataCoreId() {
418
- if (this.dataCoreId) {
419
- return this.dataCoreId;
420
- }
421
- const dataCore = await this.options.flowcoreClient.execute(new mod_js_1.DataCoreFetchCommand({
422
- dataCore: this.options.dataSource.dataCore,
423
- tenant: this.options.dataSource.tenant,
424
- }));
425
- this.dataCoreId = dataCore.id;
426
- return this.dataCoreId;
427
- }
428
- pull(amount) {
429
- if (this.options.processor) {
430
- throw new Error("Pull is not supported when processor is set");
431
- }
432
- return this.pullInner(amount);
433
- }
434
- acknowledge(eventIds) {
435
- if (this.options.processor) {
436
- throw new Error("Acknowledge is not supported when processor is set");
437
- }
438
- return this.acknowledgeInner(eventIds);
439
- }
440
- }
441
- exports.DataPump = DataPump;
@@ -1,18 +0,0 @@
1
- import type { DataPumpNotifier } from "./data-pump.js";
2
- interface NatsClientOptions {
3
- servers: string[];
4
- timeoutMs?: number;
5
- }
6
- export declare class NatsNotifier {
7
- private readonly options;
8
- private nats;
9
- private timeoutMs;
10
- constructor(options: NatsClientOptions);
11
- private start;
12
- private stop;
13
- private awaitMessage;
14
- private getSubscription;
15
- getNotifier(): DataPumpNotifier;
16
- }
17
- export {};
18
- //# sourceMappingURL=nats-notifier.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nats-notifier.d.ts","sourceRoot":"","sources":["../../src/lib/nats-notifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,YAAY;IAGX,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,SAAS,CAAQ;gBACI,OAAO,EAAE,iBAAiB;YAIzC,KAAK;YAOL,IAAI;IAOlB,OAAO,CAAC,YAAY;IAoCpB,OAAO,CAAC,eAAe;IAgBhB,WAAW,IAAI,gBAAgB;CAavC"}