@hatchet-dev/typescript-sdk 1.16.0 → 1.17.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.
Files changed (97) hide show
  1. package/README.md +14 -2
  2. package/clients/admin/admin-client.d.ts +2 -2
  3. package/clients/dispatcher/action-listener.d.ts +3 -6
  4. package/clients/dispatcher/action-listener.js +12 -17
  5. package/clients/listeners/durable-listener/durable-listener-client.d.ts +116 -15
  6. package/clients/listeners/durable-listener/durable-listener-client.js +770 -19
  7. package/clients/listeners/durable-listener/pooled-durable-listener-client.js +1 -14
  8. package/clients/listeners/run-listener/pooled-child-listener-client.js +1 -14
  9. package/clients/rest/generated/Api.d.ts +5 -1
  10. package/clients/rest/generated/data-contracts.d.ts +16 -2
  11. package/clients/rest/generated/data-contracts.js +7 -3
  12. package/legacy/examples/affinity-workers.js +2 -2
  13. package/legacy/legacy-client.js +1 -1
  14. package/legacy/step.d.ts +2 -2
  15. package/legacy/step.js +3 -2
  16. package/legacy/workflow.d.ts +25 -25
  17. package/package.json +1 -1
  18. package/protoc/dispatcher/dispatcher.d.ts +20 -0
  19. package/protoc/dispatcher/dispatcher.js +535 -100
  20. package/protoc/events/events.js +54 -14
  21. package/protoc/google/protobuf/timestamp.js +1 -1
  22. package/protoc/v1/dispatcher.d.ts +169 -0
  23. package/protoc/v1/dispatcher.js +2096 -8
  24. package/protoc/v1/shared/condition.js +37 -11
  25. package/protoc/v1/shared/trigger.d.ts +89 -0
  26. package/protoc/v1/shared/trigger.js +524 -0
  27. package/protoc/v1/workflows.d.ts +34 -34
  28. package/protoc/v1/workflows.js +452 -254
  29. package/protoc/workflows/workflows.d.ts +2 -75
  30. package/protoc/workflows/workflows.js +157 -529
  31. package/util/abort-error.d.ts +10 -0
  32. package/util/abort-error.js +15 -0
  33. package/util/errors/eviction-not-supported-error.d.ts +5 -0
  34. package/util/errors/eviction-not-supported-error.js +18 -0
  35. package/util/errors/non-determinism-error.d.ts +7 -0
  36. package/util/errors/non-determinism-error.js +21 -0
  37. package/util/errors/task-run-terminated-error.d.ts +6 -0
  38. package/util/errors/task-run-terminated-error.js +15 -0
  39. package/util/hatchet-promise/hatchet-promise.d.ts +2 -1
  40. package/util/hatchet-promise/hatchet-promise.js +10 -1
  41. package/util/sleep.d.ts +3 -2
  42. package/util/sleep.js +6 -4
  43. package/v1/client/admin.d.ts +2 -2
  44. package/v1/client/client.js +1 -1
  45. package/v1/client/duration.d.ts +11 -1
  46. package/v1/client/duration.js +44 -0
  47. package/v1/client/features/runs.d.ts +16 -3
  48. package/v1/client/features/runs.js +38 -3
  49. package/v1/client/worker/context.d.ts +101 -6
  50. package/v1/client/worker/context.js +247 -21
  51. package/v1/client/worker/deprecated/index.d.ts +1 -1
  52. package/v1/client/worker/deprecated/index.js +2 -1
  53. package/v1/client/worker/deprecated/legacy-worker.d.ts +5 -0
  54. package/v1/client/worker/deprecated/legacy-worker.js +32 -23
  55. package/v1/client/worker/deprecated/pre-eviction.d.ts +12 -0
  56. package/v1/client/worker/deprecated/pre-eviction.js +37 -0
  57. package/v1/client/worker/engine-version.d.ts +5 -0
  58. package/v1/client/worker/engine-version.js +14 -0
  59. package/v1/client/worker/eviction/eviction-cache.d.ts +33 -0
  60. package/v1/client/worker/eviction/eviction-cache.js +139 -0
  61. package/v1/client/worker/eviction/eviction-manager.d.ts +42 -0
  62. package/v1/client/worker/eviction/eviction-manager.js +132 -0
  63. package/v1/client/worker/eviction/eviction-policy.d.ts +19 -0
  64. package/v1/client/worker/eviction/eviction-policy.js +8 -0
  65. package/v1/client/worker/eviction/index.d.ts +3 -0
  66. package/v1/client/worker/eviction/index.js +11 -0
  67. package/v1/client/worker/worker-internal.d.ts +23 -4
  68. package/v1/client/worker/worker-internal.js +177 -138
  69. package/v1/client/worker/worker.d.ts +1 -0
  70. package/v1/client/worker/worker.js +34 -1
  71. package/v1/conditions/sleep-condition.js +2 -1
  72. package/v1/conditions/transformer.js +2 -1
  73. package/v1/declaration.d.ts +5 -3
  74. package/v1/declaration.js +8 -0
  75. package/v1/examples/__e2e__/harness.d.ts +5 -0
  76. package/v1/examples/__e2e__/harness.js +13 -0
  77. package/v1/examples/concurrency_workflow_level/workflow.d.ts +1 -1
  78. package/v1/examples/concurrency_workflow_level/workflow.js +1 -1
  79. package/v1/examples/durable/workflow.d.ts +57 -0
  80. package/v1/examples/durable/workflow.js +162 -7
  81. package/v1/examples/durable-event/workflow.js +2 -7
  82. package/v1/examples/durable_event/workflow.d.ts +1 -0
  83. package/v1/examples/durable_event/workflow.js +4 -9
  84. package/v1/examples/durable_eviction/capacity-worker.d.ts +1 -0
  85. package/v1/examples/durable_eviction/capacity-worker.js +31 -0
  86. package/v1/examples/durable_eviction/worker.d.ts +1 -0
  87. package/v1/examples/durable_eviction/worker.js +34 -0
  88. package/v1/examples/durable_eviction/workflow.d.ts +44 -0
  89. package/v1/examples/durable_eviction/workflow.js +129 -0
  90. package/v1/examples/e2e-worker.js +42 -19
  91. package/v1/index.d.ts +5 -0
  92. package/v1/index.js +10 -0
  93. package/v1/parent-run-context-vars.d.ts +6 -0
  94. package/v1/task.d.ts +10 -2
  95. package/v1/task.js +2 -1
  96. package/version.d.ts +1 -1
  97. package/version.js +1 -1
@@ -1,38 +1,789 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
19
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
20
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
21
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
22
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
23
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
24
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
25
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
26
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
27
+ function fulfill(value) { resume("next", value); }
28
+ function reject(value) { resume("throw", value); }
29
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
30
+ };
31
+ var __importDefault = (this && this.__importDefault) || function (mod) {
32
+ return (mod && mod.__esModule) ? mod : { "default": mod };
33
+ };
2
34
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DurableListenerClient = void 0;
35
+ exports.LegacyDurableEventStreamable = exports.DurableListenerClient = void 0;
36
+ const events_1 = require("events");
37
+ const abort_controller_x_1 = require("abort-controller-x");
38
+ const hatchet_error_1 = require("../../../util/errors/hatchet-error");
4
39
  const dispatcher_1 = require("../../../protoc/v1/dispatcher");
5
- const pooled_durable_listener_client_1 = require("./pooled-durable-listener-client");
40
+ const non_determinism_error_1 = require("../../../util/errors/non-determinism-error");
41
+ const abort_error_1 = require("../../../util/abort-error");
42
+ const sleep_1 = __importDefault(require("../../../util/sleep"));
43
+ class TTLMap {
44
+ constructor(ttlMs) {
45
+ this.ttlMs = ttlMs;
46
+ this.cache = new Map();
47
+ this.timer = setInterval(() => this.evict(), ttlMs);
48
+ }
49
+ set(key, value) {
50
+ this.cache.set(key, { value, expiresAt: Date.now() + this.ttlMs });
51
+ }
52
+ get(key) {
53
+ var _a;
54
+ return (_a = this.cache.get(key)) === null || _a === void 0 ? void 0 : _a.value;
55
+ }
56
+ get size() {
57
+ return this.cache.size;
58
+ }
59
+ has(key) {
60
+ return this.cache.has(key);
61
+ }
62
+ delete(key) {
63
+ return this.cache.delete(key);
64
+ }
65
+ keys() {
66
+ return this.cache.keys();
67
+ }
68
+ pop(key) {
69
+ const entry = this.cache.get(key);
70
+ if (entry) {
71
+ this.cache.delete(key);
72
+ return entry.value;
73
+ }
74
+ return undefined;
75
+ }
76
+ clear() {
77
+ this.cache.clear();
78
+ }
79
+ destroy() {
80
+ clearInterval(this.timer);
81
+ this.cache.clear();
82
+ }
83
+ evict() {
84
+ const now = Date.now();
85
+ for (const [key, entry] of this.cache) {
86
+ if (entry.expiresAt <= now) {
87
+ this.cache.delete(key);
88
+ }
89
+ }
90
+ }
91
+ }
92
+ const DEFAULT_RECONNECT_INTERVAL = 3000;
93
+ const EVICTION_ACK_TIMEOUT_MS = 30000;
94
+ const WORKER_STATUS_POLL_INTERVAL_MS = 1000;
95
+ function eventLogEntryResultFromProto(proto) {
96
+ var _a, _b, _c, _d;
97
+ let payload;
98
+ if (proto.payload && proto.payload.length > 0) {
99
+ payload = JSON.parse(new TextDecoder().decode(proto.payload));
100
+ }
101
+ return {
102
+ durableTaskExternalId: (_b = (_a = proto.ref) === null || _a === void 0 ? void 0 : _a.durableTaskExternalId) !== null && _b !== void 0 ? _b : '',
103
+ nodeId: (_d = (_c = proto.ref) === null || _c === void 0 ? void 0 : _c.nodeId) !== null && _d !== void 0 ? _d : 0,
104
+ payload,
105
+ };
106
+ }
107
+ function ackKey(taskExtId, invocationCount) {
108
+ return `${taskExtId}:${invocationCount}`;
109
+ }
110
+ function callbackKey(taskExtId, invocationCount, branchId, nodeId) {
111
+ return `${taskExtId}:${invocationCount}:${branchId}:${nodeId}`;
112
+ }
113
+ function evictionKey(taskExtId, invocationCount) {
114
+ return `${taskExtId}:${invocationCount}`;
115
+ }
116
+ function deferred() {
117
+ let resolve;
118
+ let reject;
119
+ const promise = new Promise((res, rej) => {
120
+ resolve = res;
121
+ reject = rej;
122
+ });
123
+ return { promise, resolve, reject };
124
+ }
6
125
  class DurableListenerClient {
7
- constructor(config, channel, factory, api) {
126
+ constructor(config, channel, factory) {
127
+ this._running = false;
128
+ this._requestQueue = [];
129
+ this._pendingEventAcks = new Map();
130
+ this._pendingCallbacks = new Map();
131
+ // Completions that arrived before waitForCallback() registered a deferred
132
+ // in _pendingCallbacks. This happens when the server delivers an
133
+ // entryCompleted between the event ack and the waitForCallback call
134
+ // (e.g. an already-satisfied sleep delivered via polling).
135
+ this._bufferedCompletions = new TTLMap(10000);
136
+ this._pendingEvictionAcks = new Map();
8
137
  this.config = config;
9
138
  this.client = factory.create(dispatcher_1.V1DispatcherDefinition, channel);
10
- this.logger = config.logger(`Listener`, config.log_level);
11
- this.api = api;
139
+ this.logger = config.logger(`DurableListener`, config.log_level);
12
140
  }
13
- subscribe(request) {
14
- if (!this.pooledListener) {
15
- this.pooledListener = new pooled_durable_listener_client_1.DurableEventGrpcPooledListener(this, () => {
16
- this.pooledListener = undefined;
141
+ get workerId() {
142
+ return this._workerId;
143
+ }
144
+ start(workerId) {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ if (this._startLock) {
147
+ yield this._startLock;
148
+ return;
149
+ }
150
+ this._startLock = this._doStart(workerId);
151
+ yield this._startLock;
152
+ });
153
+ }
154
+ _doStart(workerId) {
155
+ return __awaiter(this, void 0, void 0, function* () {
156
+ if (this._running)
157
+ return;
158
+ this._workerId = workerId;
159
+ this._running = true;
160
+ yield this._connect();
161
+ this._startStatusPolling();
162
+ });
163
+ }
164
+ ensureStarted(workerId) {
165
+ return __awaiter(this, void 0, void 0, function* () {
166
+ if (!this._running) {
167
+ yield this.start(workerId);
168
+ }
169
+ });
170
+ }
171
+ stop() {
172
+ return __awaiter(this, void 0, void 0, function* () {
173
+ this._running = false;
174
+ this._startLock = undefined;
175
+ if (this._statusInterval) {
176
+ clearInterval(this._statusInterval);
177
+ this._statusInterval = undefined;
178
+ }
179
+ if (this._receiveAbort) {
180
+ this._receiveAbort.abort();
181
+ }
182
+ this._failPendingAcks(new Error('DurableListener stopped'));
183
+ this._bufferedCompletions.destroy();
184
+ });
185
+ }
186
+ _connect() {
187
+ return __awaiter(this, void 0, void 0, function* () {
188
+ this.logger.info('durable event listener connecting...');
189
+ this._requestQueue = [];
190
+ this._receiveAbort = new AbortController();
191
+ this._enqueueRequest({
192
+ registerWorker: { workerId: this._workerId },
17
193
  });
194
+ this._pollWorkerStatus();
195
+ void this._streamLoop();
196
+ this.logger.info('durable event listener connected');
197
+ });
198
+ }
199
+ _streamLoop() {
200
+ return __awaiter(this, void 0, void 0, function* () {
201
+ var _a, e_1, _b, _c;
202
+ var _d;
203
+ while (this._running) {
204
+ try {
205
+ const stream = this.client.durableTask(this._requestIterator(), {
206
+ signal: (_d = this._receiveAbort) === null || _d === void 0 ? void 0 : _d.signal,
207
+ });
208
+ try {
209
+ for (var _e = true, stream_1 = (e_1 = void 0, __asyncValues(stream)), stream_1_1; stream_1_1 = yield stream_1.next(), _a = stream_1_1.done, !_a; _e = true) {
210
+ _c = stream_1_1.value;
211
+ _e = false;
212
+ const response = _c;
213
+ this._handleResponse(response);
214
+ }
215
+ }
216
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
217
+ finally {
218
+ try {
219
+ if (!_e && !_a && (_b = stream_1.return)) yield _b.call(stream_1);
220
+ }
221
+ finally { if (e_1) throw e_1.error; }
222
+ }
223
+ if (this._running) {
224
+ this.logger.warn(`durable event listener disconnected (EOF), reconnecting in ${DEFAULT_RECONNECT_INTERVAL}ms...`);
225
+ this._failPendingAcks(new Error('durable stream disconnected'));
226
+ yield (0, sleep_1.default)(DEFAULT_RECONNECT_INTERVAL);
227
+ yield this._connect();
228
+ return;
229
+ }
230
+ }
231
+ catch (e) {
232
+ if ((0, abort_controller_x_1.isAbortError)(e)) {
233
+ this.logger.debug('durable event listener aborted');
234
+ return;
235
+ }
236
+ this.logger.error(`error in durable event listener: ${(0, hatchet_error_1.getErrorMessage)(e)}`);
237
+ if (this._running) {
238
+ this._failPendingAcks(new Error(`durable stream error: ${(0, hatchet_error_1.getErrorMessage)(e)}`));
239
+ yield (0, sleep_1.default)(DEFAULT_RECONNECT_INTERVAL);
240
+ yield this._connect();
241
+ return;
242
+ }
243
+ }
244
+ }
245
+ });
246
+ }
247
+ _requestIterator() {
248
+ return __asyncGenerator(this, arguments, function* _requestIterator_1() {
249
+ while (this._running) {
250
+ while (this._requestQueue.length > 0) {
251
+ yield yield __await(this._requestQueue.shift());
252
+ }
253
+ yield __await(new Promise((resolve) => {
254
+ this._requestNotify = resolve;
255
+ }));
256
+ this._requestNotify = undefined;
257
+ }
258
+ });
259
+ }
260
+ _enqueueRequest(request) {
261
+ this._requestQueue.push(request);
262
+ if (this._requestNotify) {
263
+ this._requestNotify();
18
264
  }
19
- return this.pooledListener.subscribe(request);
20
265
  }
21
- result(request, opts) {
22
- if (!this.pooledListener) {
23
- this.pooledListener = new pooled_durable_listener_client_1.DurableEventGrpcPooledListener(this, () => {
24
- this.pooledListener = undefined;
266
+ _startStatusPolling() {
267
+ if (this._statusInterval) {
268
+ clearInterval(this._statusInterval);
269
+ }
270
+ this._statusInterval = setInterval(() => {
271
+ this._pollWorkerStatus();
272
+ }, WORKER_STATUS_POLL_INTERVAL_MS);
273
+ }
274
+ _pollWorkerStatus() {
275
+ if (!this._workerId || this._pendingCallbacks.size === 0)
276
+ return;
277
+ const waitingEntries = [];
278
+ for (const key of this._pendingCallbacks.keys()) {
279
+ const parts = key.split(':');
280
+ waitingEntries.push({
281
+ durableTaskExternalId: parts[0],
282
+ invocationCount: parseInt(parts[1], 10),
283
+ branchId: parseInt(parts[2], 10),
284
+ nodeId: parseInt(parts[3], 10),
25
285
  });
26
286
  }
27
- return this.pooledListener.result(request, opts);
287
+ this._enqueueRequest({
288
+ workerStatus: {
289
+ workerId: this._workerId,
290
+ waitingEntries,
291
+ },
292
+ });
293
+ }
294
+ _failPendingAcks(exc) {
295
+ for (const d of this._pendingEventAcks.values()) {
296
+ d.reject(exc);
297
+ }
298
+ this._pendingEventAcks.clear();
299
+ for (const d of this._pendingEvictionAcks.values()) {
300
+ d.reject(exc);
301
+ }
302
+ this._pendingEvictionAcks.clear();
303
+ }
304
+ _failAllPending(exc) {
305
+ this._failPendingAcks(exc);
306
+ for (const d of this._pendingCallbacks.values()) {
307
+ d.reject(exc);
308
+ }
309
+ this._pendingCallbacks.clear();
310
+ this._bufferedCompletions.clear();
28
311
  }
312
+ _handleResponse(response) {
313
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
314
+ if (response.registerWorker) {
315
+ // registration acknowledged
316
+ }
317
+ else if (response.triggerRunsAck) {
318
+ const ack = response.triggerRunsAck;
319
+ const key = ackKey(ack.durableTaskExternalId, ack.invocationCount);
320
+ const pending = this._pendingEventAcks.get(key);
321
+ if (pending) {
322
+ pending.resolve({
323
+ ackType: 'run',
324
+ invocationCount: ack.invocationCount,
325
+ durableTaskExternalId: ack.durableTaskExternalId,
326
+ runEntries: (ack.runEntries || []).map((e) => ({
327
+ nodeId: e.nodeId,
328
+ branchId: e.branchId,
329
+ workflowRunExternalId: e.workflowRunExternalId,
330
+ })),
331
+ });
332
+ this._pendingEventAcks.delete(key);
333
+ }
334
+ }
335
+ else if (response.memoAck) {
336
+ const ack = response.memoAck;
337
+ const { ref } = ack;
338
+ const key = ackKey((_a = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _a !== void 0 ? _a : '', (_b = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _b !== void 0 ? _b : 0);
339
+ const pending = this._pendingEventAcks.get(key);
340
+ if (pending) {
341
+ pending.resolve({
342
+ ackType: 'memo',
343
+ invocationCount: (_c = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _c !== void 0 ? _c : 0,
344
+ durableTaskExternalId: (_d = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _d !== void 0 ? _d : '',
345
+ branchId: (_e = ref === null || ref === void 0 ? void 0 : ref.branchId) !== null && _e !== void 0 ? _e : 0,
346
+ nodeId: (_f = ref === null || ref === void 0 ? void 0 : ref.nodeId) !== null && _f !== void 0 ? _f : 0,
347
+ memoAlreadyExisted: ack.memoAlreadyExisted,
348
+ memoResultPayload: ack.memoResultPayload,
349
+ });
350
+ this._pendingEventAcks.delete(key);
351
+ }
352
+ }
353
+ else if (response.waitForAck) {
354
+ const ack = response.waitForAck;
355
+ const { ref } = ack;
356
+ const key = ackKey((_g = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _g !== void 0 ? _g : '', (_h = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _h !== void 0 ? _h : 0);
357
+ const pending = this._pendingEventAcks.get(key);
358
+ if (pending) {
359
+ pending.resolve({
360
+ ackType: 'waitFor',
361
+ invocationCount: (_j = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _j !== void 0 ? _j : 0,
362
+ durableTaskExternalId: (_k = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _k !== void 0 ? _k : '',
363
+ branchId: (_l = ref === null || ref === void 0 ? void 0 : ref.branchId) !== null && _l !== void 0 ? _l : 0,
364
+ nodeId: (_m = ref === null || ref === void 0 ? void 0 : ref.nodeId) !== null && _m !== void 0 ? _m : 0,
365
+ });
366
+ this._pendingEventAcks.delete(key);
367
+ }
368
+ }
369
+ else if (response.entryCompleted) {
370
+ const completed = response.entryCompleted;
371
+ const { ref } = completed;
372
+ const key = callbackKey((_o = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _o !== void 0 ? _o : '', (_p = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _p !== void 0 ? _p : 0, (_q = ref === null || ref === void 0 ? void 0 : ref.branchId) !== null && _q !== void 0 ? _q : 0, (_r = ref === null || ref === void 0 ? void 0 : ref.nodeId) !== null && _r !== void 0 ? _r : 0);
373
+ const result = eventLogEntryResultFromProto(completed);
374
+ const pending = this._pendingCallbacks.get(key);
375
+ if (pending) {
376
+ pending.resolve(result);
377
+ this._pendingCallbacks.delete(key);
378
+ }
379
+ else {
380
+ this._bufferedCompletions.set(key, result);
381
+ }
382
+ }
383
+ else if (response.evictionAck) {
384
+ const ack = response.evictionAck;
385
+ const key = evictionKey(ack.durableTaskExternalId, ack.invocationCount);
386
+ const pending = this._pendingEvictionAcks.get(key);
387
+ if (pending) {
388
+ pending.resolve();
389
+ this._pendingEvictionAcks.delete(key);
390
+ }
391
+ }
392
+ else if (response.serverEvict) {
393
+ const evict = response.serverEvict;
394
+ this.logger.info(`received server eviction notification for task ${evict.durableTaskExternalId} ` +
395
+ `invocation ${evict.invocationCount}: ${evict.reason}`);
396
+ this.cleanupTaskState(evict.durableTaskExternalId, evict.invocationCount);
397
+ if (this.onServerEvict) {
398
+ this.onServerEvict(evict.durableTaskExternalId, evict.invocationCount);
399
+ }
400
+ }
401
+ else if (response.error) {
402
+ const { error } = response;
403
+ const { ref } = error;
404
+ let exc;
405
+ if (error.errorType === dispatcher_1.DurableTaskErrorType.DURABLE_TASK_ERROR_TYPE_NONDETERMINISM) {
406
+ exc = new non_determinism_error_1.NonDeterminismError((_s = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _s !== void 0 ? _s : '', (_t = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _t !== void 0 ? _t : 0, (_u = ref === null || ref === void 0 ? void 0 : ref.nodeId) !== null && _u !== void 0 ? _u : 0, error.errorMessage);
407
+ }
408
+ else {
409
+ exc = new Error(`Unspecified durable task error: ${error.errorMessage} (type: ${error.errorType})`);
410
+ }
411
+ const eAckKey = ackKey((_v = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _v !== void 0 ? _v : '', (_w = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _w !== void 0 ? _w : 0);
412
+ const pendingAck = this._pendingEventAcks.get(eAckKey);
413
+ if (pendingAck) {
414
+ pendingAck.reject(exc);
415
+ this._pendingEventAcks.delete(eAckKey);
416
+ }
417
+ const eCbKey = callbackKey((_x = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _x !== void 0 ? _x : '', (_y = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _y !== void 0 ? _y : 0, (_z = ref === null || ref === void 0 ? void 0 : ref.branchId) !== null && _z !== void 0 ? _z : 0, (_0 = ref === null || ref === void 0 ? void 0 : ref.nodeId) !== null && _0 !== void 0 ? _0 : 0);
418
+ const pendingCb = this._pendingCallbacks.get(eCbKey);
419
+ if (pendingCb) {
420
+ pendingCb.reject(exc);
421
+ this._pendingCallbacks.delete(eCbKey);
422
+ }
423
+ const eEvKey = evictionKey((_1 = ref === null || ref === void 0 ? void 0 : ref.durableTaskExternalId) !== null && _1 !== void 0 ? _1 : '', (_2 = ref === null || ref === void 0 ? void 0 : ref.invocationCount) !== null && _2 !== void 0 ? _2 : 0);
424
+ const pendingEv = this._pendingEvictionAcks.get(eEvKey);
425
+ if (pendingEv) {
426
+ pendingEv.reject(exc);
427
+ this._pendingEvictionAcks.delete(eEvKey);
428
+ }
429
+ }
430
+ }
431
+ sendEvent(durableTaskExternalId, invocationCount, event) {
432
+ return __awaiter(this, void 0, void 0, function* () {
433
+ const key = ackKey(durableTaskExternalId, invocationCount);
434
+ const d = deferred();
435
+ this._pendingEventAcks.set(key, d);
436
+ let request;
437
+ switch (event.kind) {
438
+ case 'runChildren': {
439
+ const triggerRunsReq = {
440
+ invocationCount,
441
+ durableTaskExternalId,
442
+ triggerOpts: event.triggerOpts,
443
+ };
444
+ request = { triggerRuns: triggerRunsReq };
445
+ break;
446
+ }
447
+ case 'waitFor': {
448
+ const waitForReq = {
449
+ invocationCount,
450
+ durableTaskExternalId,
451
+ waitForConditions: event.waitForConditions,
452
+ };
453
+ request = { waitFor: waitForReq };
454
+ break;
455
+ }
456
+ case 'memo': {
457
+ const memoReq = {
458
+ invocationCount,
459
+ durableTaskExternalId,
460
+ key: event.memoKey,
461
+ payload: event.payload,
462
+ };
463
+ request = { memo: memoReq };
464
+ break;
465
+ }
466
+ default: {
467
+ const _ = event;
468
+ throw new Error(`Unknown durable task send event: ${_}`);
469
+ }
470
+ }
471
+ this._enqueueRequest(request);
472
+ return d.promise;
473
+ });
474
+ }
475
+ waitForCallback(durableTaskExternalId, invocationCount, branchId, nodeId, opts) {
476
+ return __awaiter(this, void 0, void 0, function* () {
477
+ const key = callbackKey(durableTaskExternalId, invocationCount, branchId, nodeId);
478
+ const early = this._bufferedCompletions.get(key);
479
+ if (early) {
480
+ this._bufferedCompletions.delete(key);
481
+ return early;
482
+ }
483
+ if (!this._pendingCallbacks.has(key)) {
484
+ this._pendingCallbacks.set(key, deferred());
485
+ this._pollWorkerStatus();
486
+ }
487
+ const d = this._pendingCallbacks.get(key);
488
+ const signal = opts === null || opts === void 0 ? void 0 : opts.signal;
489
+ if (!signal) {
490
+ return d.promise;
491
+ }
492
+ if (signal.aborted) {
493
+ return Promise.reject((0, abort_error_1.createAbortError)('Operation cancelled by AbortSignal'));
494
+ }
495
+ return new Promise((resolve, reject) => {
496
+ let settled = false;
497
+ const onAbort = () => {
498
+ if (settled)
499
+ return;
500
+ settled = true;
501
+ reject((0, abort_error_1.createAbortError)('Operation cancelled by AbortSignal'));
502
+ };
503
+ (0, abort_error_1.bindAbortSignalHandler)(signal, onAbort);
504
+ d.promise.then((value) => {
505
+ if (settled)
506
+ return;
507
+ settled = true;
508
+ signal.removeEventListener('abort', onAbort);
509
+ resolve(value);
510
+ }, (err) => {
511
+ if (settled)
512
+ return;
513
+ settled = true;
514
+ signal.removeEventListener('abort', onAbort);
515
+ reject(err);
516
+ });
517
+ });
518
+ });
519
+ }
520
+ cleanupTaskState(durableTaskExternalId, invocationCount) {
521
+ for (const [k, d] of this._pendingCallbacks) {
522
+ const parts = k.split(':');
523
+ if (parts[0] === durableTaskExternalId && parseInt(parts[1], 10) <= invocationCount) {
524
+ d.reject(new Error('task state cleaned up'));
525
+ this._pendingCallbacks.delete(k);
526
+ }
527
+ }
528
+ for (const [k, d] of this._pendingEventAcks) {
529
+ const parts = k.split(':');
530
+ if (parts[0] === durableTaskExternalId && parseInt(parts[1], 10) <= invocationCount) {
531
+ d.reject(new Error('task state cleaned up'));
532
+ this._pendingEventAcks.delete(k);
533
+ }
534
+ }
535
+ for (const k of this._bufferedCompletions.keys()) {
536
+ const parts = k.split(':');
537
+ if (parts[0] === durableTaskExternalId && parseInt(parts[1], 10) <= invocationCount) {
538
+ this._bufferedCompletions.delete(k);
539
+ }
540
+ }
541
+ }
542
+ sendEvictInvocation(durableTaskExternalId, invocationCount, reason) {
543
+ return __awaiter(this, void 0, void 0, function* () {
544
+ const key = evictionKey(durableTaskExternalId, invocationCount);
545
+ const d = deferred();
546
+ this._pendingEvictionAcks.set(key, d);
547
+ const req = {
548
+ invocationCount,
549
+ durableTaskExternalId,
550
+ reason,
551
+ };
552
+ this._enqueueRequest({ evictInvocation: req });
553
+ const timeout = (0, sleep_1.default)(EVICTION_ACK_TIMEOUT_MS).then(() => {
554
+ throw new Error(`Eviction ack timed out after ${EVICTION_ACK_TIMEOUT_MS}ms for task ${durableTaskExternalId} invocation ${invocationCount}`);
555
+ });
556
+ try {
557
+ yield Promise.race([d.promise, timeout]);
558
+ }
559
+ catch (err) {
560
+ this._pendingEvictionAcks.delete(key);
561
+ throw err;
562
+ }
563
+ });
564
+ }
565
+ sendMemoCompletedNotification(durableTaskExternalId, nodeId, branchId, invocationCount, memoKey, memoResultPayload) {
566
+ return __awaiter(this, void 0, void 0, function* () {
567
+ const ref = {
568
+ durableTaskExternalId,
569
+ invocationCount,
570
+ branchId,
571
+ nodeId,
572
+ };
573
+ const req = {
574
+ ref,
575
+ payload: memoResultPayload !== null && memoResultPayload !== void 0 ? memoResultPayload : new Uint8Array(),
576
+ memoKey,
577
+ };
578
+ this._enqueueRequest({ completeMemo: req });
579
+ });
580
+ }
581
+ /**
582
+ * @deprecated Legacy backward-compat: uses the old unary RegisterDurableEvent RPC.
583
+ */
29
584
  registerDurableEvent(request) {
30
- if (!this.pooledListener) {
31
- this.pooledListener = new pooled_durable_listener_client_1.DurableEventGrpcPooledListener(this, () => {
32
- this.pooledListener = undefined;
585
+ return __awaiter(this, void 0, void 0, function* () {
586
+ return this.client.registerDurableEvent({
587
+ taskId: request.taskId,
588
+ signalKey: request.signalKey,
589
+ conditions: {
590
+ sleepConditions: request.sleepConditions,
591
+ userEventConditions: request.userEventConditions,
592
+ },
33
593
  });
594
+ });
595
+ }
596
+ /**
597
+ * @deprecated Legacy backward-compat: uses the old streaming ListenForDurableEvent RPC.
598
+ */
599
+ subscribe(request) {
600
+ if (!this._legacyPooledListener) {
601
+ this._legacyPooledListener = new LegacyPooledListener(this);
34
602
  }
35
- return this.pooledListener.registerDurableEvent(request);
603
+ return this._legacyPooledListener.subscribe(request);
604
+ }
605
+ /**
606
+ * @deprecated Legacy backward-compat: subscribes and waits for a single result.
607
+ */
608
+ result(request, opts) {
609
+ return __awaiter(this, void 0, void 0, function* () {
610
+ const subscriber = this.subscribe(request);
611
+ return subscriber.get({ signal: opts === null || opts === void 0 ? void 0 : opts.signal });
612
+ });
36
613
  }
37
614
  }
38
615
  exports.DurableListenerClient = DurableListenerClient;
616
+ /**
617
+ * @deprecated Legacy support for the old streaming ListenForDurableEvent RPC.
618
+ */
619
+ class LegacyDurableEventStreamable {
620
+ constructor(onCleanup) {
621
+ this.responseEmitter = new events_1.EventEmitter();
622
+ this._onCleanup = onCleanup;
623
+ }
624
+ get(opts) {
625
+ return __awaiter(this, void 0, void 0, function* () {
626
+ const signal = opts === null || opts === void 0 ? void 0 : opts.signal;
627
+ return new Promise((resolve, reject) => {
628
+ let cleanedUp = false;
629
+ const cleanup = () => {
630
+ if (cleanedUp)
631
+ return;
632
+ cleanedUp = true;
633
+ this.responseEmitter.removeListener('response', onResponse);
634
+ if (signal) {
635
+ signal.removeEventListener('abort', onAbort);
636
+ }
637
+ this._onCleanup();
638
+ };
639
+ const onResponse = (event) => {
640
+ cleanup();
641
+ resolve(event);
642
+ };
643
+ const onAbort = () => {
644
+ cleanup();
645
+ reject((0, abort_error_1.createAbortError)('Operation cancelled by AbortSignal'));
646
+ };
647
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
648
+ onAbort();
649
+ return;
650
+ }
651
+ this.responseEmitter.once('response', onResponse);
652
+ if (signal) {
653
+ (0, abort_error_1.bindAbortSignalHandler)(signal, onAbort);
654
+ }
655
+ });
656
+ });
657
+ }
658
+ }
659
+ exports.LegacyDurableEventStreamable = LegacyDurableEventStreamable;
660
+ /**
661
+ * @deprecated Legacy pooled listener for old ListenForDurableEvent streaming RPC.
662
+ */
663
+ class LegacyPooledListener {
664
+ constructor(client) {
665
+ this.requestEmitter = new events_1.EventEmitter();
666
+ this.signal = new AbortController();
667
+ this.subscribers = {};
668
+ this.taskSignalKeyToSubscriptionIds = {};
669
+ this.subscriptionCounter = 0;
670
+ this.currRequester = 0;
671
+ this.client = client;
672
+ this.init();
673
+ }
674
+ init() {
675
+ return __awaiter(this, arguments, void 0, function* (retries = 0) {
676
+ var _a, e_2, _b, _c;
677
+ const MAX_RETRY_INTERVAL = 5000;
678
+ const BASE_RETRY_INTERVAL = 100;
679
+ const MAX_RETRY_COUNT = 5;
680
+ if (retries > 0) {
681
+ const backoffTime = Math.min(BASE_RETRY_INTERVAL * 2 ** (retries - 1), MAX_RETRY_INTERVAL);
682
+ yield (0, sleep_1.default)(backoffTime);
683
+ }
684
+ if (retries > MAX_RETRY_COUNT)
685
+ return;
686
+ try {
687
+ this.signal = new AbortController();
688
+ this.currRequester++;
689
+ this.listener = this.client.client.listenForDurableEvent(this.request(), {
690
+ signal: this.signal.signal,
691
+ });
692
+ try {
693
+ for (var _d = true, _e = __asyncValues(this.listener), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
694
+ _c = _f.value;
695
+ _d = false;
696
+ const event = _c;
697
+ const subscriptionKey = `${event.taskId}|${event.signalKey}`;
698
+ const subscriptionIds = this.taskSignalKeyToSubscriptionIds[subscriptionKey] || [];
699
+ for (const subId of subscriptionIds) {
700
+ const emitter = this.subscribers[subId];
701
+ if (emitter) {
702
+ emitter.responseEmitter.emit('response', event);
703
+ this.cleanupSubscription(subId);
704
+ }
705
+ }
706
+ }
707
+ }
708
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
709
+ finally {
710
+ try {
711
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
712
+ }
713
+ finally { if (e_2) throw e_2.error; }
714
+ }
715
+ }
716
+ catch (e) {
717
+ if ((0, abort_controller_x_1.isAbortError)(e))
718
+ return;
719
+ }
720
+ finally {
721
+ if (Object.keys(this.subscribers).length > 0) {
722
+ this.init(retries + 1);
723
+ }
724
+ }
725
+ });
726
+ }
727
+ cleanupSubscription(subscriptionId) {
728
+ var _a;
729
+ const emitter = this.subscribers[subscriptionId];
730
+ if (!emitter)
731
+ return;
732
+ const key = (_a = Object.entries(this.taskSignalKeyToSubscriptionIds).find(([, ids]) => ids.includes(subscriptionId))) === null || _a === void 0 ? void 0 : _a[0];
733
+ delete this.subscribers[subscriptionId];
734
+ if (key && this.taskSignalKeyToSubscriptionIds[key]) {
735
+ this.taskSignalKeyToSubscriptionIds[key] = this.taskSignalKeyToSubscriptionIds[key].filter((id) => id !== subscriptionId);
736
+ if (this.taskSignalKeyToSubscriptionIds[key].length === 0) {
737
+ delete this.taskSignalKeyToSubscriptionIds[key];
738
+ }
739
+ }
740
+ }
741
+ subscribe(request) {
742
+ const subscriptionId = (this.subscriptionCounter++).toString();
743
+ const subscriber = new LegacyDurableEventStreamable(() => this.cleanupSubscription(subscriptionId));
744
+ this.subscribers[subscriptionId] = subscriber;
745
+ const key = `${request.taskId}|${request.signalKey}`;
746
+ if (!this.taskSignalKeyToSubscriptionIds[key]) {
747
+ this.taskSignalKeyToSubscriptionIds[key] = [];
748
+ }
749
+ this.taskSignalKeyToSubscriptionIds[key].push(subscriptionId);
750
+ this.requestEmitter.emit('subscribe', request);
751
+ return subscriber;
752
+ }
753
+ request() {
754
+ return __asyncGenerator(this, arguments, function* request_1() {
755
+ var _a, e_3, _b, _c;
756
+ const { currRequester } = this;
757
+ const existing = new Set();
758
+ for (const key in this.taskSignalKeyToSubscriptionIds) {
759
+ if (this.taskSignalKeyToSubscriptionIds[key].length > 0) {
760
+ const [taskId, signalKey] = key.split('|');
761
+ existing.add(key);
762
+ yield yield __await({ taskId, signalKey });
763
+ }
764
+ }
765
+ try {
766
+ for (var _d = true, _e = __asyncValues((0, events_1.on)(this.requestEmitter, 'subscribe')), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
767
+ _c = _f.value;
768
+ _d = false;
769
+ const e = _c;
770
+ if (currRequester !== this.currRequester)
771
+ break;
772
+ const request = e[0];
773
+ const key = `${request.taskId}|${request.signalKey}`;
774
+ if (!existing.has(key)) {
775
+ existing.add(key);
776
+ yield yield __await(request);
777
+ }
778
+ }
779
+ }
780
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
781
+ finally {
782
+ try {
783
+ if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
784
+ }
785
+ finally { if (e_3) throw e_3.error; }
786
+ }
787
+ });
788
+ }
789
+ }