@superdurable/dex 1.20.0 → 1.25.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/README.md +48 -32
- package/dist/src/client.d.ts +3 -2
- package/dist/src/client.js +10 -16
- package/dist/src/client.js.map +1 -1
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/errors.js +1 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/gen/dex.d.ts +5 -1
- package/dist/src/gen/dex.js +43 -3
- package/dist/src/gen/dex.js.map +1 -1
- package/dist/src/grpc-status.d.ts +0 -1
- package/dist/src/grpc-status.js +2 -31
- package/dist/src/grpc-status.js.map +1 -1
- package/dist/src/options.d.ts +11 -55
- package/dist/src/options.js.map +1 -1
- package/dist/src/pull-registration.d.ts +1 -1
- package/dist/src/pull-worker.d.ts +8 -1
- package/dist/src/pull-worker.js +92 -9
- package/dist/src/pull-worker.js.map +1 -1
- package/dist/src/sdk-version.generated.d.ts +1 -1
- package/dist/src/sdk-version.generated.js +1 -1
- package/dist/src/worker-dispatcher.js +7 -12
- package/dist/src/worker-dispatcher.js.map +1 -1
- package/dist/src/worker.d.ts +16 -22
- package/dist/src/worker.js +27 -215
- package/dist/src/worker.js.map +1 -1
- package/native/windows-x86_64/dex_blob_cache_node.node +0 -0
- package/package.json +1 -1
- package/dist/src/worker-target.d.ts +0 -3
- package/dist/src/worker-target.js +0 -23
- package/dist/src/worker-target.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { status, type ServiceError as GrpcServiceError } from "@grpc/grpc-js";
|
|
2
2
|
import { WorkerErrorResponse } from "./gen/dex.js";
|
|
3
3
|
import { DexServiceError } from "./errors.js";
|
|
4
|
-
export declare function workerServiceError(failure: unknown): GrpcServiceError;
|
|
5
4
|
export declare function workerErrorResponse(failure: unknown, grpcStatus?: status): WorkerErrorResponse;
|
|
6
5
|
export type FlowTargetRequirement = "none" | "existing" | "active";
|
|
7
6
|
export declare function translateServiceError(error: GrpcServiceError, operation: string, flowId: string | undefined, requirement: FlowTargetRequirement): DexServiceError;
|
package/dist/src/grpc-status.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// See the LICENSE file in the repository root.
|
|
6
6
|
//
|
|
7
7
|
// SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
|
|
8
|
-
import { BinaryReader
|
|
9
|
-
import {
|
|
8
|
+
import { BinaryReader } from "@bufbuild/protobuf/wire";
|
|
9
|
+
import { status } from "@grpc/grpc-js";
|
|
10
10
|
import { ServiceErrorResponse, ErrorSubStatus as ProtoErrorSubStatus, WorkerErrorResponse, } from "./gen/dex.js";
|
|
11
11
|
import { DexServiceError, ErrorSubStatus, FlowAlreadyStartedError, FlowClosingError, FlowNotActiveOrNotFoundError, FlowNotFoundError, LongPollTimeoutError, RequestTimeoutError, ChannelMessageNotFoundError, RpcLockConflictError, WorkerInvocationError, } from "./errors.js";
|
|
12
12
|
import { RetryAfterError } from "./retry-after.js";
|
|
@@ -17,19 +17,6 @@ const maxWorkerStackTraceBytes = 4 * 1024;
|
|
|
17
17
|
const errorDetailTruncationMarker = Buffer.from("\n... error detail truncated by Dex TypeScript SDK ...");
|
|
18
18
|
const errorTypeTruncationMarker = Buffer.from("\n... error type truncated by Dex TypeScript SDK ...");
|
|
19
19
|
const stackTraceTruncationMarker = Buffer.from("\n... stack trace truncated by Dex TypeScript SDK ...");
|
|
20
|
-
export function workerServiceError(failure) {
|
|
21
|
-
const response = workerErrorResponse(failure);
|
|
22
|
-
const worker = WorkerErrorResponse.encode(response).finish();
|
|
23
|
-
const metadata = new Metadata();
|
|
24
|
-
metadata.set(statusDetailsKey, Buffer.from(encodeStatus(response.grpcStatus, response.detail, [
|
|
25
|
-
{ typeUrl: "type.googleapis.com/dex.WorkerErrorResponse", value: worker },
|
|
26
|
-
])));
|
|
27
|
-
return Object.assign(new Error(response.detail), {
|
|
28
|
-
code: response.grpcStatus,
|
|
29
|
-
details: response.detail,
|
|
30
|
-
metadata,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
20
|
export function workerErrorResponse(failure, grpcStatus = status.UNKNOWN) {
|
|
34
21
|
const retryAfterError = failure instanceof RetryAfterError ? failure : undefined;
|
|
35
22
|
const cause = retryAfterError?.cause instanceof Error
|
|
@@ -141,22 +128,6 @@ function mapSubStatus(value) {
|
|
|
141
128
|
return ErrorSubStatus.UNCATEGORIZED;
|
|
142
129
|
}
|
|
143
130
|
}
|
|
144
|
-
function encodeStatus(code, message, details) {
|
|
145
|
-
const writer = new BinaryWriter();
|
|
146
|
-
if (code !== 0) {
|
|
147
|
-
writer.uint32(8).int32(code);
|
|
148
|
-
}
|
|
149
|
-
if (message !== "") {
|
|
150
|
-
writer.uint32(18).string(message);
|
|
151
|
-
}
|
|
152
|
-
for (const detail of details) {
|
|
153
|
-
writer.uint32(26).fork();
|
|
154
|
-
writer.uint32(10).string(detail.typeUrl);
|
|
155
|
-
writer.uint32(18).bytes(detail.value);
|
|
156
|
-
writer.join();
|
|
157
|
-
}
|
|
158
|
-
return writer.finish();
|
|
159
|
-
}
|
|
160
131
|
function decodeStatus(input) {
|
|
161
132
|
const reader = new BinaryReader(input);
|
|
162
133
|
const details = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc-status.js","sourceRoot":"","sources":["../../src/grpc-status.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAE1D,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"grpc-status.js","sourceRoot":"","sources":["../../src/grpc-status.ts"],"names":[],"mappings":"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"}
|
package/dist/src/options.d.ts
CHANGED
|
@@ -2,14 +2,12 @@ import type { Credential } from "./credential.js";
|
|
|
2
2
|
import type { Attribute, AttributeLock, AttributeMap, AttributeMapLoad } from "./persistence.js";
|
|
3
3
|
import type { RetryPolicy, StepClass, StepDurability, StepOptions } from "./step.js";
|
|
4
4
|
import type { Channel, ChannelMap, ChannelMapLoad } from "./wait.js";
|
|
5
|
-
/** Configures FlowService connectivity and
|
|
5
|
+
/** Configures FlowService connectivity and bearer credentials. */
|
|
6
6
|
export interface ClientOptions {
|
|
7
7
|
/** Plaintext Dex gRPC target; defaults to `localhost:8801`. */
|
|
8
8
|
readonly serverAddress?: string;
|
|
9
9
|
/** Bearer token provider for every FlowService call; omitted sends no authorization metadata. */
|
|
10
10
|
readonly credential?: Credential;
|
|
11
|
-
/** Worker endpoint advertised by `startFlow` unless a Flow overrides it; use `{ pull: true }` for pull Workers. */
|
|
12
|
-
readonly workerTarget?: WorkerTarget | PullWorkerTarget;
|
|
13
11
|
}
|
|
14
12
|
/**
|
|
15
13
|
* Configures one durable Step completion wait.
|
|
@@ -151,8 +149,6 @@ export interface FlowConfig {
|
|
|
151
149
|
readonly continueAsNewPageSizeBytes?: number;
|
|
152
150
|
/** Default durability for later Step handler results. */
|
|
153
151
|
readonly stepDurability?: StepDurability;
|
|
154
|
-
/** Worker endpoint used for later handler calls; use `{ pull: true }` for pull routing. */
|
|
155
|
-
readonly workerTarget?: WorkerTarget | PullWorkerTarget;
|
|
156
152
|
}
|
|
157
153
|
/**
|
|
158
154
|
* Describes one Attribute value written atomically when a Flow starts.
|
|
@@ -387,18 +383,14 @@ export interface StopFlowOptions {
|
|
|
387
383
|
readonly reason?: string;
|
|
388
384
|
}
|
|
389
385
|
/**
|
|
390
|
-
* Configures Worker startup and
|
|
386
|
+
* Configures Worker startup and outbound task streams.
|
|
391
387
|
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
388
|
+
* Every Worker pulls tasks over an outbound connection to the Dex Server.
|
|
389
|
+
* See {@link PullWorkerOptions} for capacity and shutdown settings.
|
|
394
390
|
*/
|
|
395
391
|
export interface WorkerOptions {
|
|
396
|
-
/**
|
|
392
|
+
/** Task capacity and shutdown settings; omitted uses the defaults in {@link PullWorkerOptions}. */
|
|
397
393
|
readonly pull?: PullWorkerOptions;
|
|
398
|
-
/** Local plaintext WorkerService listener; defaults to `127.0.0.1:8803` outside pull mode. */
|
|
399
|
-
readonly bindAddress?: string;
|
|
400
|
-
/** Endpoint advertised to Dex; derived from `bindAddress` when omitted. */
|
|
401
|
-
readonly workerTarget?: WorkerTarget;
|
|
402
394
|
/** Dex FlowService target; defaults to `localhost:8801`. */
|
|
403
395
|
readonly serverAddress?: string;
|
|
404
396
|
/** Bearer token provider for startup, hydration, and pull streams; omitted sends no authorization metadata. */
|
|
@@ -409,14 +401,14 @@ export interface WorkerOptions {
|
|
|
409
401
|
/**
|
|
410
402
|
* Configures an outbound pull Worker.
|
|
411
403
|
*
|
|
412
|
-
* Pass this as `WorkerOptions.pull
|
|
404
|
+
* Pass this as `WorkerOptions.pull` to customize task capacity and shutdown.
|
|
413
405
|
* Each stream handles one task, while handlers on different streams can run concurrently.
|
|
414
406
|
*
|
|
415
407
|
* @example
|
|
416
408
|
* ```ts
|
|
417
409
|
* const worker = new Worker(registry, cache, { pull: { maxConcurrentTasks: 8 } });
|
|
418
410
|
* await worker.start();
|
|
419
|
-
* const client = new Client(registry, cache
|
|
411
|
+
* const client = new Client(registry, cache);
|
|
420
412
|
* try { await client.startFlow(flow, flowId); } finally { await client.close(); await worker.close(); }
|
|
421
413
|
* ```
|
|
422
414
|
*/
|
|
@@ -430,7 +422,7 @@ export interface PullWorkerOptions {
|
|
|
430
422
|
* Unset reserves one slot when resolved capacity is at least two, otherwise zero.
|
|
431
423
|
* With the CPU-count default, Steps get one fewer slot than before. Set zero to opt out.
|
|
432
424
|
* With one slot and no explicit reserve, start warns once that RPCs may wait behind Steps.
|
|
433
|
-
* Flows must stay responsive
|
|
425
|
+
* Flows must stay responsive because RPCs share Worker task capacity with Steps.
|
|
434
426
|
* WaitFor and Execute tasks, including local attempts, are declined
|
|
435
427
|
* when total busy handlers reach maxConcurrentTasks minus this reserve. RPCs can
|
|
436
428
|
* use the full task limit, including API-direct and transactional RPCs. Requires an integer at least zero and below the task
|
|
@@ -441,57 +433,21 @@ export interface PullWorkerOptions {
|
|
|
441
433
|
* then fall back according to their policy.
|
|
442
434
|
* Declines emit a node:util debuglog message under dex:pull with the Flow type.
|
|
443
435
|
* The pullReservedRpcDeclines counter increments; registration readiness is unaffected.
|
|
436
|
+
* A queue keeps one extra idle stream for 30 seconds after its last reserve decline.
|
|
437
|
+
* The Worker does not open it while all task slots are busy.
|
|
444
438
|
* @example
|
|
445
439
|
* ```ts
|
|
446
440
|
* const pull: PullWorkerOptions = { maxConcurrentTasks: 8, reservedRpcTasks: 2 };
|
|
447
441
|
* ```
|
|
448
442
|
*/
|
|
449
443
|
readonly reservedRpcTasks?: number;
|
|
450
|
-
/** Waiting streams on
|
|
444
|
+
/** Waiting streams on each queue; zero or omission uses one. A queue keeps one more after a recent reserve decline. Use at least two for heavy Step backlogs. Negative values are invalid. */
|
|
451
445
|
readonly idleStreamsPerQueue?: number;
|
|
452
446
|
/** Process-unique Worker ID; defaults to host identity plus eight random base32 characters. Use a new ID after every restart. Values contain 1-63 ASCII letters, digits, dots, underscores, or hyphens and cannot equal a registered Flow type. */
|
|
453
447
|
readonly appWorkerID?: string;
|
|
454
448
|
/** Milliseconds allowed for graceful shutdown and busy Reconnect final-frame delivery; defaults to 30000. Requires a non-negative finite value. After shutdown expiry, Worker.close cancels active handlers and waits for them to return. */
|
|
455
449
|
readonly stopDrainTimeoutMs?: number;
|
|
456
450
|
}
|
|
457
|
-
/**
|
|
458
|
-
* Selects the listening endpoint used for Step and RPC work.
|
|
459
|
-
*
|
|
460
|
-
* Use this for a WorkerService listener. Use {@link PullWorkerTarget} for
|
|
461
|
-
* outbound pull routing.
|
|
462
|
-
*
|
|
463
|
-
* @example
|
|
464
|
-
* ```ts
|
|
465
|
-
* const client = new Client(registry, cache, { workerTarget: { address: "worker.example:8803" } });
|
|
466
|
-
* ```
|
|
467
|
-
*/
|
|
468
|
-
export interface WorkerTarget {
|
|
469
|
-
/** Plaintext gRPC target; headless targets must use `host:port`. */
|
|
470
|
-
readonly address: string;
|
|
471
|
-
/** Whether Dex connects directly without service discovery. */
|
|
472
|
-
readonly headless?: boolean;
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Routes Step and RPC work through Dex task queues to an outbound pull Worker.
|
|
476
|
-
*
|
|
477
|
-
* Supply this target as a Client default, StartFlow configuration override, or
|
|
478
|
-
* SubFlow configuration override. The Worker must have `WorkerOptions.pull` enabled.
|
|
479
|
-
* Pull cannot include a nonempty address or enable headless routing.
|
|
480
|
-
*
|
|
481
|
-
* @example
|
|
482
|
-
* ```ts
|
|
483
|
-
* const client = new Client(registry, cache, { workerTarget: { pull: true } });
|
|
484
|
-
* await client.startFlow(flow, flowId, input);
|
|
485
|
-
* ```
|
|
486
|
-
*/
|
|
487
|
-
export interface PullWorkerTarget {
|
|
488
|
-
/** Enables routing through Dex task queues. */
|
|
489
|
-
readonly pull: true;
|
|
490
|
-
/** Omit this field or use an empty string; pull Workers do not listen. */
|
|
491
|
-
readonly address?: "";
|
|
492
|
-
/** Omit this field or use false; headless routing requires a listener. */
|
|
493
|
-
readonly headless?: false;
|
|
494
|
-
}
|
|
495
451
|
/** Selects whether a visibility search includes earlier Continue-as-New runs. */
|
|
496
452
|
export interface SearchFlowsOptions {
|
|
497
453
|
/** Disable default exclusion while retaining every explicit query filter. Defaults to false. */
|
package/dist/src/options.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/options.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAM1D,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/options.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,7 +23,7 @@ export interface PullQueueRegistrationState {
|
|
|
23
23
|
export interface PullRegistrationState {
|
|
24
24
|
/** Latches after all queues register; false while a queue has a permanent error and no registered stream. */
|
|
25
25
|
readonly isReady: boolean;
|
|
26
|
-
/** Queue snapshots in registration order
|
|
26
|
+
/** Queue snapshots in registration order, including the process queue and every registered Flow type. */
|
|
27
27
|
readonly queues: readonly PullQueueRegistrationState[];
|
|
28
28
|
}
|
|
29
29
|
/** Optional cancellation and deadline for Worker.waitPullRegistered. */
|
|
@@ -7,6 +7,7 @@ export declare class PullWorker {
|
|
|
7
7
|
private readonly dispatcher;
|
|
8
8
|
private readonly options;
|
|
9
9
|
private readonly onPermanentRejection;
|
|
10
|
+
private readonly reservePressureLingerMs;
|
|
10
11
|
readonly appWorkerID: string;
|
|
11
12
|
readonly registration: PullRegistration;
|
|
12
13
|
private readonly client;
|
|
@@ -17,6 +18,8 @@ export declare class PullWorker {
|
|
|
17
18
|
private readonly maxConcurrentTasks;
|
|
18
19
|
private readonly reservedRpcTasks;
|
|
19
20
|
private reservedRpcDeclineCount;
|
|
21
|
+
private readonly lastReserveDeclineMs;
|
|
22
|
+
private readonly reservePressureTimers;
|
|
20
23
|
private hasWarnedRpcCapacity;
|
|
21
24
|
private readonly idleStreamsPerQueue;
|
|
22
25
|
private readonly stopDrainTimeoutMs;
|
|
@@ -26,20 +29,24 @@ export declare class PullWorker {
|
|
|
26
29
|
private stopDeadlineMs;
|
|
27
30
|
private hasLoggedUnsupportedServer;
|
|
28
31
|
private busyTaskCount;
|
|
29
|
-
constructor(registry: Registry, dispatcher: WorkerDispatcher, serverAddress: string, options: PullWorkerOptions, credential?: Credential, onPermanentRejection?: () => void);
|
|
32
|
+
constructor(registry: Registry, dispatcher: WorkerDispatcher, serverAddress: string, options: PullWorkerOptions, credential?: Credential, onPermanentRejection?: () => void, reservePressureLingerMs?: number);
|
|
30
33
|
get reservedRpcDeclines(): number;
|
|
31
34
|
start(): void;
|
|
32
35
|
close(): Promise<void>;
|
|
33
36
|
private reconcile;
|
|
37
|
+
private desiredIdleStreamsPerQueue;
|
|
34
38
|
private openStream;
|
|
35
39
|
private handleFrame;
|
|
36
40
|
private startTask;
|
|
41
|
+
private scheduleReservePressureExpiry;
|
|
42
|
+
private expireReservePressure;
|
|
37
43
|
private unknownTaskReason;
|
|
38
44
|
private rejectTask;
|
|
39
45
|
private executeTask;
|
|
40
46
|
private finishTask;
|
|
41
47
|
private hasRegisteredIdleReplacements;
|
|
42
48
|
private sendTaskFrame;
|
|
49
|
+
private stopKeepalive;
|
|
43
50
|
private send;
|
|
44
51
|
private disconnect;
|
|
45
52
|
private onStreamClosed;
|
package/dist/src/pull-worker.js
CHANGED
|
@@ -16,10 +16,12 @@ import { workerErrorResponse } from "./grpc-status.js";
|
|
|
16
16
|
import { PullRegistration } from "./pull-registration.js";
|
|
17
17
|
import { sdkVersion } from "./sdk-version.generated.js";
|
|
18
18
|
const debug = debuglog("dex:pull");
|
|
19
|
+
const BUSY_PULL_STREAM_KEEPALIVE_MS = 20_000;
|
|
19
20
|
export class PullWorker {
|
|
20
21
|
dispatcher;
|
|
21
22
|
options;
|
|
22
23
|
onPermanentRejection;
|
|
24
|
+
reservePressureLingerMs;
|
|
23
25
|
appWorkerID;
|
|
24
26
|
registration;
|
|
25
27
|
client;
|
|
@@ -30,6 +32,8 @@ export class PullWorker {
|
|
|
30
32
|
maxConcurrentTasks;
|
|
31
33
|
reservedRpcTasks;
|
|
32
34
|
reservedRpcDeclineCount = 0;
|
|
35
|
+
lastReserveDeclineMs = new Map();
|
|
36
|
+
reservePressureTimers = new Map();
|
|
33
37
|
hasWarnedRpcCapacity = false;
|
|
34
38
|
idleStreamsPerQueue;
|
|
35
39
|
stopDrainTimeoutMs;
|
|
@@ -39,10 +43,11 @@ export class PullWorker {
|
|
|
39
43
|
stopDeadlineMs;
|
|
40
44
|
hasLoggedUnsupportedServer = false;
|
|
41
45
|
busyTaskCount = 0;
|
|
42
|
-
constructor(registry, dispatcher, serverAddress, options, credential, onPermanentRejection = () => { }) {
|
|
46
|
+
constructor(registry, dispatcher, serverAddress, options, credential, onPermanentRejection = () => { }, reservePressureLingerMs = 30_000) {
|
|
43
47
|
this.dispatcher = dispatcher;
|
|
44
48
|
this.options = options;
|
|
45
49
|
this.onPermanentRejection = onPermanentRejection;
|
|
50
|
+
this.reservePressureLingerMs = reservePressureLingerMs;
|
|
46
51
|
this.maxConcurrentTasks = positiveOption(options.maxConcurrentTasks, availableParallelism(), "maxConcurrentTasks");
|
|
47
52
|
this.reservedRpcTasks = options.reservedRpcTasks ?? (this.maxConcurrentTasks >= 2 ? 1 : 0);
|
|
48
53
|
if (!Number.isInteger(this.reservedRpcTasks) || this.reservedRpcTasks < 0 || this.reservedRpcTasks >= this.maxConcurrentTasks) {
|
|
@@ -84,6 +89,9 @@ export class PullWorker {
|
|
|
84
89
|
async close() {
|
|
85
90
|
const stopDeadlineMs = this.stopDeadlineMs ??= Date.now() + this.stopDrainTimeoutMs;
|
|
86
91
|
this.isStopping = true;
|
|
92
|
+
for (const timer of this.reservePressureTimers.values())
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
this.reservePressureTimers.clear();
|
|
87
95
|
this.registration.stopped();
|
|
88
96
|
for (const poll of this.streams) {
|
|
89
97
|
poll.isDraining = true;
|
|
@@ -143,11 +151,13 @@ export class PullWorker {
|
|
|
143
151
|
if (poll.queue === queue && poll.task === undefined && !poll.isDraining)
|
|
144
152
|
idleCount++;
|
|
145
153
|
}
|
|
146
|
-
|
|
154
|
+
const desiredIdle = this.desiredIdleStreamsPerQueue(queue);
|
|
155
|
+
const creationTarget = this.busyTaskCount === this.maxConcurrentTasks ? this.idleStreamsPerQueue : desiredIdle;
|
|
156
|
+
while (idleCount < creationTarget) {
|
|
147
157
|
const poll = {
|
|
148
158
|
queue, stream: undefined, task: undefined, retryTimer: undefined,
|
|
149
|
-
halfCloseTimer: undefined, halfClosePromise: undefined, resolveHalfClose: undefined,
|
|
150
|
-
isRegistered: false, hasRecordedResult: false, supportsUnknownNameRejection: false, isDisconnected: false, isHalfClosed: false, isDraining: false, isRetiring: false,
|
|
159
|
+
halfCloseTimer: undefined, keepaliveTimer: undefined, halfClosePromise: undefined, resolveHalfClose: undefined,
|
|
160
|
+
isRegistered: false, hasRecordedResult: false, supportsUnknownNameRejection: false, isDisconnected: false, isHalfClosed: false, isFinalFrameSent: false, isDraining: false, isRetiring: false,
|
|
151
161
|
isReconnectRequested: false, hasRetriedRejectedToken: false,
|
|
152
162
|
backoffMs: 100, failure: undefined,
|
|
153
163
|
};
|
|
@@ -157,6 +167,11 @@ export class PullWorker {
|
|
|
157
167
|
}
|
|
158
168
|
}
|
|
159
169
|
}
|
|
170
|
+
desiredIdleStreamsPerQueue(queue) {
|
|
171
|
+
const lastDeclineMs = this.lastReserveDeclineMs.get(queue);
|
|
172
|
+
return this.idleStreamsPerQueue + Number(this.reservedRpcTasks > 0 && lastDeclineMs !== undefined
|
|
173
|
+
&& performance.now() - lastDeclineMs < this.reservePressureLingerMs);
|
|
174
|
+
}
|
|
160
175
|
openStream(poll) {
|
|
161
176
|
if (this.isStopping)
|
|
162
177
|
return;
|
|
@@ -165,6 +180,7 @@ export class PullWorker {
|
|
|
165
180
|
poll.supportsUnknownNameRejection = false;
|
|
166
181
|
poll.isDisconnected = false;
|
|
167
182
|
poll.isHalfClosed = false;
|
|
183
|
+
poll.isFinalFrameSent = false;
|
|
168
184
|
poll.failure = undefined;
|
|
169
185
|
poll.isDraining = false;
|
|
170
186
|
poll.isReconnectRequested = false;
|
|
@@ -231,6 +247,8 @@ export class PullWorker {
|
|
|
231
247
|
poll.task.controller.abort();
|
|
232
248
|
break;
|
|
233
249
|
case "ping":
|
|
250
|
+
if (poll.task !== undefined && poll.isFinalFrameSent)
|
|
251
|
+
break;
|
|
234
252
|
try {
|
|
235
253
|
this.send(poll, { frame: { $case: "pong", value: {} } });
|
|
236
254
|
}
|
|
@@ -266,8 +284,14 @@ export class PullWorker {
|
|
|
266
284
|
const isStepTask = task.request?.$case === "waitFor" || task.request?.$case === "execute";
|
|
267
285
|
if (isStepTask && this.reservedRpcTasks > 0 && this.busyTaskCount >= this.maxConcurrentTasks - this.reservedRpcTasks && unknownReason === undefined) {
|
|
268
286
|
this.reservedRpcDeclineCount++;
|
|
287
|
+
this.lastReserveDeclineMs.set(poll.queue, performance.now());
|
|
288
|
+
const existingTimer = this.reservePressureTimers.get(poll.queue);
|
|
289
|
+
if (existingTimer !== undefined)
|
|
290
|
+
clearTimeout(existingTimer);
|
|
291
|
+
this.scheduleReservePressureExpiry(poll.queue, this.reservePressureLingerMs);
|
|
269
292
|
debug("decline Step task for reserved RPC capacity: %s", task.request?.value.flowType);
|
|
270
293
|
this.rejectTask(poll, task.taskId, PollWorkerTaskRejectReason.POLL_WORKER_TASK_REJECT_REASON_NO_CAPACITY);
|
|
294
|
+
this.reconcile();
|
|
271
295
|
return;
|
|
272
296
|
}
|
|
273
297
|
const controller = new AbortController();
|
|
@@ -275,12 +299,43 @@ export class PullWorker {
|
|
|
275
299
|
const deadlineCancellation = deadlineMs === undefined
|
|
276
300
|
? undefined
|
|
277
301
|
: new DeadlineCancellation(deadlineMs, controller);
|
|
302
|
+
poll.isFinalFrameSent = false;
|
|
303
|
+
poll.keepaliveTimer = setInterval(() => {
|
|
304
|
+
if (poll.isDisconnected || poll.isFinalFrameSent || poll.task === undefined)
|
|
305
|
+
return;
|
|
306
|
+
try {
|
|
307
|
+
this.send(poll, { frame: { $case: "pong", value: {} } });
|
|
308
|
+
}
|
|
309
|
+
catch (failure) {
|
|
310
|
+
console.error("send Worker keepalive Pong", failure);
|
|
311
|
+
this.disconnect(poll);
|
|
312
|
+
}
|
|
313
|
+
}, BUSY_PULL_STREAM_KEEPALIVE_MS);
|
|
314
|
+
poll.keepaliveTimer.unref();
|
|
278
315
|
const completion = this.executeTask(poll, task, controller.signal).finally(() => this.finishTask(poll));
|
|
279
316
|
poll.task = { id: task.taskId, controller, completion, deadlineCancellation };
|
|
280
317
|
this.activeTasks.add(completion);
|
|
281
318
|
this.busyTaskCount++;
|
|
282
319
|
this.reconcile();
|
|
283
320
|
}
|
|
321
|
+
scheduleReservePressureExpiry(queue, delayMs) {
|
|
322
|
+
const timer = setTimeout(() => this.expireReservePressure(queue), delayMs);
|
|
323
|
+
timer.unref();
|
|
324
|
+
this.reservePressureTimers.set(queue, timer);
|
|
325
|
+
}
|
|
326
|
+
expireReservePressure(queue) {
|
|
327
|
+
const lastDeclineMs = this.lastReserveDeclineMs.get(queue);
|
|
328
|
+
if (lastDeclineMs === undefined)
|
|
329
|
+
return;
|
|
330
|
+
const remainingMs = this.reservePressureLingerMs - (performance.now() - lastDeclineMs);
|
|
331
|
+
if (remainingMs > 0) {
|
|
332
|
+
this.scheduleReservePressureExpiry(queue, remainingMs);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
this.lastReserveDeclineMs.delete(queue);
|
|
336
|
+
this.reservePressureTimers.delete(queue);
|
|
337
|
+
this.reconcile();
|
|
338
|
+
}
|
|
284
339
|
unknownTaskReason(task) {
|
|
285
340
|
switch (task.request?.$case) {
|
|
286
341
|
case "waitFor":
|
|
@@ -314,10 +369,11 @@ export class PullWorker {
|
|
|
314
369
|
}
|
|
315
370
|
}
|
|
316
371
|
async executeTask(poll, task, signal) {
|
|
372
|
+
let emitter;
|
|
317
373
|
try {
|
|
318
374
|
switch (task.request?.$case) {
|
|
319
375
|
case "waitFor": {
|
|
320
|
-
|
|
376
|
+
emitter = new PullStepOutputEmitter(poll, task.taskId, "waitFor", signal, (frame) => this.sendTaskFrame(poll, frame));
|
|
321
377
|
const result = await this.dispatcher.invokeWaitFor(task.request.value, signal, emitter);
|
|
322
378
|
this.sendTaskFrame(poll, { taskId: task.taskId, output: {
|
|
323
379
|
$case: "waitFor", value: InvokeWaitForMethodOutput.create({ output: { $case: "result", value: result } }),
|
|
@@ -325,7 +381,7 @@ export class PullWorker {
|
|
|
325
381
|
break;
|
|
326
382
|
}
|
|
327
383
|
case "execute": {
|
|
328
|
-
|
|
384
|
+
emitter = new PullStepOutputEmitter(poll, task.taskId, "execute", signal, (frame) => this.sendTaskFrame(poll, frame));
|
|
329
385
|
const result = await this.dispatcher.invokeExecute(task.request.value, signal, emitter);
|
|
330
386
|
this.sendTaskFrame(poll, { taskId: task.taskId, output: {
|
|
331
387
|
$case: "execute", value: InvokeExecuteMethodOutput.create({ output: { $case: "result", value: result } }),
|
|
@@ -356,13 +412,18 @@ export class PullWorker {
|
|
|
356
412
|
}
|
|
357
413
|
}
|
|
358
414
|
}
|
|
415
|
+
finally {
|
|
416
|
+
emitter?.close();
|
|
417
|
+
}
|
|
359
418
|
}
|
|
360
419
|
finishTask(poll) {
|
|
420
|
+
this.stopKeepalive(poll);
|
|
361
421
|
const task = poll.task;
|
|
362
422
|
if (task === undefined)
|
|
363
423
|
return;
|
|
364
424
|
task.deadlineCancellation?.stop();
|
|
365
425
|
poll.task = undefined;
|
|
426
|
+
poll.isFinalFrameSent = false;
|
|
366
427
|
this.activeTasks.delete(task.completion);
|
|
367
428
|
this.busyTaskCount--;
|
|
368
429
|
if (!poll.isDisconnected && !poll.isDraining && this.hasRegisteredIdleReplacements(poll)) {
|
|
@@ -380,11 +441,22 @@ export class PullWorker {
|
|
|
380
441
|
}
|
|
381
442
|
hasRegisteredIdleReplacements(poll) {
|
|
382
443
|
return [...this.streams].filter((candidate) => candidate !== poll && candidate.queue === poll.queue && candidate.isRegistered
|
|
383
|
-
&& candidate.task === undefined && !candidate.isDraining && !candidate.isDisconnected).length >= this.
|
|
444
|
+
&& candidate.task === undefined && !candidate.isDraining && !candidate.isDisconnected).length >= this.desiredIdleStreamsPerQueue(poll.queue);
|
|
384
445
|
}
|
|
385
446
|
sendTaskFrame(poll, frame) {
|
|
447
|
+
if (frame.output?.$case === "rpc" || frame.output?.$case === "workerError"
|
|
448
|
+
|| frame.output?.$case === "waitFor" && frame.output.value.output?.$case === "result"
|
|
449
|
+
|| frame.output?.$case === "execute" && frame.output.value.output?.$case === "result") {
|
|
450
|
+
this.stopKeepalive(poll);
|
|
451
|
+
poll.isFinalFrameSent = true;
|
|
452
|
+
}
|
|
386
453
|
this.send(poll, { frame: { $case: "taskFrame", value: frame } });
|
|
387
454
|
}
|
|
455
|
+
stopKeepalive(poll) {
|
|
456
|
+
if (poll.keepaliveTimer !== undefined)
|
|
457
|
+
clearInterval(poll.keepaliveTimer);
|
|
458
|
+
poll.keepaliveTimer = undefined;
|
|
459
|
+
}
|
|
388
460
|
send(poll, request) {
|
|
389
461
|
if (poll.isDisconnected || poll.stream === undefined) {
|
|
390
462
|
throw new Error("Worker task stream is closed");
|
|
@@ -392,6 +464,7 @@ export class PullWorker {
|
|
|
392
464
|
poll.stream.write(request);
|
|
393
465
|
}
|
|
394
466
|
disconnect(poll) {
|
|
467
|
+
this.stopKeepalive(poll);
|
|
395
468
|
if (poll.isDisconnected)
|
|
396
469
|
return;
|
|
397
470
|
this.recordStreamResult(poll);
|
|
@@ -404,6 +477,7 @@ export class PullWorker {
|
|
|
404
477
|
this.scheduleReconnect(poll);
|
|
405
478
|
}
|
|
406
479
|
onStreamClosed(poll) {
|
|
480
|
+
this.stopKeepalive(poll);
|
|
407
481
|
if (poll.isHalfClosed) {
|
|
408
482
|
this.completeHalfClose(poll);
|
|
409
483
|
return;
|
|
@@ -417,6 +491,7 @@ export class PullWorker {
|
|
|
417
491
|
this.scheduleReconnect(poll);
|
|
418
492
|
}
|
|
419
493
|
halfCloseStream(poll) {
|
|
494
|
+
this.stopKeepalive(poll);
|
|
420
495
|
if (poll.isHalfClosed || poll.stream === undefined)
|
|
421
496
|
return;
|
|
422
497
|
poll.isDisconnected = true;
|
|
@@ -456,7 +531,7 @@ export class PullWorker {
|
|
|
456
531
|
poll.stream = undefined;
|
|
457
532
|
if (!this.isStopping) {
|
|
458
533
|
const idleStreamCount = [...this.streams].filter((candidate) => candidate !== poll && candidate.queue === poll.queue && candidate.task === undefined && !candidate.isDraining).length;
|
|
459
|
-
if (poll.isRetiring || poll.isReconnectRequested && idleStreamCount >= this.
|
|
534
|
+
if (poll.isRetiring || poll.isReconnectRequested && idleStreamCount >= this.desiredIdleStreamsPerQueue(poll.queue)) {
|
|
460
535
|
this.streams.delete(poll);
|
|
461
536
|
}
|
|
462
537
|
else {
|
|
@@ -535,13 +610,19 @@ class PullStepOutputEmitter {
|
|
|
535
610
|
poll;
|
|
536
611
|
taskID;
|
|
537
612
|
method;
|
|
613
|
+
signal;
|
|
538
614
|
sendFrame;
|
|
539
|
-
|
|
615
|
+
isActive = true;
|
|
616
|
+
constructor(poll, taskID, method, signal, sendFrame) {
|
|
540
617
|
this.poll = poll;
|
|
541
618
|
this.taskID = taskID;
|
|
542
619
|
this.method = method;
|
|
620
|
+
this.signal = signal;
|
|
543
621
|
this.sendFrame = sendFrame;
|
|
544
622
|
}
|
|
623
|
+
close() {
|
|
624
|
+
this.isActive = false;
|
|
625
|
+
}
|
|
545
626
|
recordHeartbeat(value) {
|
|
546
627
|
this.sendOutput({ $case: "heartbeat", value: { value } });
|
|
547
628
|
return Promise.resolve();
|
|
@@ -550,6 +631,8 @@ class PullStepOutputEmitter {
|
|
|
550
631
|
this.sendOutput({ $case: "streamWrite", value: write });
|
|
551
632
|
}
|
|
552
633
|
sendOutput(output) {
|
|
634
|
+
if (!this.isActive || this.signal.aborted)
|
|
635
|
+
throw new Error("Worker task is no longer active");
|
|
553
636
|
if (this.poll.isDisconnected)
|
|
554
637
|
throw new Error("Worker task stream is closed");
|
|
555
638
|
const value = this.method === "waitFor"
|