@qlever-llc/trellis 0.10.17 → 0.19.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/auth/mod.d.ts +1 -1
- package/esm/auth/mod.d.ts.map +1 -1
- package/esm/auth/mod.js +1 -1
- package/esm/auth/protocol.d.ts +416 -398
- package/esm/auth/protocol.d.ts.map +1 -1
- package/esm/auth/protocol.js +35 -33
- package/esm/codec.d.ts +1 -0
- package/esm/codec.d.ts.map +1 -1
- package/esm/codec.js +1 -0
- package/esm/contract_support/canonical.d.ts +3 -0
- package/esm/contract_support/canonical.d.ts.map +1 -1
- package/esm/contract_support/canonical.js +3 -0
- package/esm/contract_support/mod.d.ts +28 -4
- package/esm/contract_support/mod.d.ts.map +1 -1
- package/esm/contract_support/mod.js +85 -4
- package/esm/contract_support/protocol.d.ts +92 -7
- package/esm/contract_support/protocol.d.ts.map +1 -1
- package/esm/contract_support/protocol.js +40 -6
- package/esm/errors/index.d.ts +9 -9
- package/esm/generated-sdk/auth/api.d.ts +4 -1
- package/esm/generated-sdk/auth/api.d.ts.map +1 -1
- package/esm/generated-sdk/auth/api.js +6 -1
- package/esm/generated-sdk/auth/client.d.ts +47 -32
- package/esm/generated-sdk/auth/client.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.d.ts +1 -1
- package/esm/generated-sdk/auth/contract.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.js +1570 -1202
- package/esm/generated-sdk/auth/schemas.d.ts +1757 -1759
- package/esm/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/auth/schemas.js +963 -768
- package/esm/generated-sdk/auth/types.d.ts +292 -302
- package/esm/generated-sdk/auth/types.d.ts.map +1 -1
- package/esm/generated-sdk/auth/types.js +1 -1
- package/esm/generated-sdk/health/client.d.ts +4 -4
- package/esm/generated-sdk/health/client.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.d.ts +1 -1
- package/esm/generated-sdk/health/contract.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.js +2 -10
- package/esm/generated-sdk/health/schemas.d.ts +1 -14
- package/esm/generated-sdk/health/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/health/schemas.js +1 -9
- package/esm/generated-sdk/health/types.d.ts +3 -5
- package/esm/generated-sdk/health/types.d.ts.map +1 -1
- package/esm/generated-sdk/health/types.js +1 -2
- package/esm/generated-sdk/jobs/api.d.ts +13 -0
- package/esm/generated-sdk/jobs/api.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/client.d.ts +6 -4
- package/esm/generated-sdk/jobs/client.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.d.ts +14 -1
- package/esm/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.js +268 -1
- package/esm/generated-sdk/jobs/owned_api.d.ts +13 -0
- package/esm/generated-sdk/jobs/owned_api.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/owned_api.js +20 -1
- package/esm/generated-sdk/jobs/schemas.d.ts +437 -0
- package/esm/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/schemas.js +211 -0
- package/esm/generated-sdk/jobs/types.d.ts +123 -1
- package/esm/generated-sdk/jobs/types.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/types.js +1 -1
- package/esm/generated-sdk/state/client.d.ts +4 -4
- package/esm/generated-sdk/state/client.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/api.d.ts +4 -1
- package/esm/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/api.js +6 -1
- package/esm/generated-sdk/trellis-core/client.d.ts +28 -3
- package/esm/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.d.ts +1 -1
- package/esm/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.js +91 -1
- package/esm/generated-sdk/trellis-core/schemas.d.ts +113 -0
- package/esm/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/schemas.js +81 -0
- package/esm/generated-sdk/trellis-core/types.d.ts +23 -1
- package/esm/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/types.js +1 -1
- package/esm/health.d.ts +1 -1
- package/esm/health.d.ts.map +1 -1
- package/esm/health.js +1 -1
- package/esm/index.d.ts +2 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/jobs.d.ts +69 -3
- package/esm/jobs.d.ts.map +1 -1
- package/esm/jobs.js +92 -3
- package/esm/server/health.d.ts +2 -6
- package/esm/server/health.d.ts.map +1 -1
- package/esm/server/health_schemas.d.ts +0 -8
- package/esm/server/health_schemas.d.ts.map +1 -1
- package/esm/server/health_schemas.js +0 -5
- package/esm/server/internal_jobs/bindings.d.ts +11 -0
- package/esm/server/internal_jobs/bindings.d.ts.map +1 -1
- package/esm/server/internal_jobs/job-manager.d.ts +44 -1
- package/esm/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/esm/server/internal_jobs/job-manager.js +361 -51
- package/esm/server/internal_jobs/key-coordinator.d.ts +260 -0
- package/esm/server/internal_jobs/key-coordinator.d.ts.map +1 -0
- package/esm/server/internal_jobs/key-coordinator.js +580 -0
- package/esm/server/internal_jobs/projection.d.ts.map +1 -1
- package/esm/server/internal_jobs/projection.js +2 -0
- package/esm/server/internal_jobs/runtime-worker.d.ts +5 -1
- package/esm/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/esm/server/internal_jobs/runtime-worker.js +14 -2
- package/esm/server/internal_jobs/types.d.ts +5 -5
- package/esm/server/internal_jobs/types.d.ts.map +1 -1
- package/esm/server/internal_jobs/types.js +6 -0
- package/esm/server/service.d.ts +8 -3
- package/esm/server/service.d.ts.map +1 -1
- package/esm/server/service.js +127 -6
- package/esm/service/drizzle.d.ts +27 -0
- package/esm/service/drizzle.d.ts.map +1 -0
- package/esm/service/drizzle.js +84 -0
- package/esm/service/mod.d.ts +1 -1
- package/esm/service/mod.d.ts.map +1 -1
- package/esm/service/mod.js +1 -1
- package/esm/service/outbox_inbox.d.ts.map +1 -1
- package/esm/service/outbox_inbox.js +13 -2
- package/esm/trellis.d.ts +24 -8
- package/esm/trellis.d.ts.map +1 -1
- package/esm/trellis.js +44 -22
- package/package.json +14 -2
- package/script/auth/mod.d.ts +1 -1
- package/script/auth/mod.d.ts.map +1 -1
- package/script/auth/mod.js +22 -6
- package/script/auth/protocol.d.ts +416 -398
- package/script/auth/protocol.d.ts.map +1 -1
- package/script/auth/protocol.js +40 -37
- package/script/codec.d.ts +1 -0
- package/script/codec.d.ts.map +1 -1
- package/script/codec.js +1 -0
- package/script/contract_support/canonical.d.ts +3 -0
- package/script/contract_support/canonical.d.ts.map +1 -1
- package/script/contract_support/canonical.js +3 -0
- package/script/contract_support/mod.d.ts +28 -4
- package/script/contract_support/mod.d.ts.map +1 -1
- package/script/contract_support/mod.js +90 -4
- package/script/contract_support/protocol.d.ts +92 -7
- package/script/contract_support/protocol.d.ts.map +1 -1
- package/script/contract_support/protocol.js +41 -7
- package/script/errors/index.d.ts +9 -9
- package/script/generated-sdk/auth/api.d.ts +4 -1
- package/script/generated-sdk/auth/api.d.ts.map +1 -1
- package/script/generated-sdk/auth/api.js +6 -1
- package/script/generated-sdk/auth/client.d.ts +47 -32
- package/script/generated-sdk/auth/client.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.d.ts +1 -1
- package/script/generated-sdk/auth/contract.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.js +1570 -1202
- package/script/generated-sdk/auth/schemas.d.ts +1757 -1759
- package/script/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/script/generated-sdk/auth/schemas.js +963 -768
- package/script/generated-sdk/auth/types.d.ts +292 -302
- package/script/generated-sdk/auth/types.d.ts.map +1 -1
- package/script/generated-sdk/auth/types.js +1 -1
- package/script/generated-sdk/health/client.d.ts +4 -4
- package/script/generated-sdk/health/client.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.d.ts +1 -1
- package/script/generated-sdk/health/contract.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.js +2 -10
- package/script/generated-sdk/health/schemas.d.ts +1 -14
- package/script/generated-sdk/health/schemas.d.ts.map +1 -1
- package/script/generated-sdk/health/schemas.js +1 -9
- package/script/generated-sdk/health/types.d.ts +3 -5
- package/script/generated-sdk/health/types.d.ts.map +1 -1
- package/script/generated-sdk/health/types.js +1 -2
- package/script/generated-sdk/jobs/api.d.ts +13 -0
- package/script/generated-sdk/jobs/api.d.ts.map +1 -1
- package/script/generated-sdk/jobs/client.d.ts +6 -4
- package/script/generated-sdk/jobs/client.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.d.ts +14 -1
- package/script/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.js +268 -1
- package/script/generated-sdk/jobs/owned_api.d.ts +13 -0
- package/script/generated-sdk/jobs/owned_api.d.ts.map +1 -1
- package/script/generated-sdk/jobs/owned_api.js +19 -0
- package/script/generated-sdk/jobs/schemas.d.ts +437 -0
- package/script/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/script/generated-sdk/jobs/schemas.js +212 -1
- package/script/generated-sdk/jobs/types.d.ts +123 -1
- package/script/generated-sdk/jobs/types.d.ts.map +1 -1
- package/script/generated-sdk/jobs/types.js +1 -1
- package/script/generated-sdk/state/client.d.ts +4 -4
- package/script/generated-sdk/state/client.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/api.d.ts +4 -1
- package/script/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/api.js +6 -1
- package/script/generated-sdk/trellis-core/client.d.ts +28 -3
- package/script/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.d.ts +1 -1
- package/script/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.js +91 -1
- package/script/generated-sdk/trellis-core/schemas.d.ts +113 -0
- package/script/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/schemas.js +81 -0
- package/script/generated-sdk/trellis-core/types.d.ts +23 -1
- package/script/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/types.js +1 -1
- package/script/health.d.ts +1 -1
- package/script/health.d.ts.map +1 -1
- package/script/health.js +1 -2
- package/script/index.d.ts +2 -2
- package/script/index.d.ts.map +1 -1
- package/script/index.js +2 -3
- package/script/jobs.d.ts +69 -3
- package/script/jobs.d.ts.map +1 -1
- package/script/jobs.js +93 -3
- package/script/server/health.d.ts +2 -6
- package/script/server/health.d.ts.map +1 -1
- package/script/server/health_schemas.d.ts +0 -8
- package/script/server/health_schemas.d.ts.map +1 -1
- package/script/server/health_schemas.js +1 -6
- package/script/server/internal_jobs/bindings.d.ts +11 -0
- package/script/server/internal_jobs/bindings.d.ts.map +1 -1
- package/script/server/internal_jobs/job-manager.d.ts +44 -1
- package/script/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/script/server/internal_jobs/job-manager.js +361 -51
- package/script/server/internal_jobs/key-coordinator.d.ts +260 -0
- package/script/server/internal_jobs/key-coordinator.d.ts.map +1 -0
- package/script/server/internal_jobs/key-coordinator.js +593 -0
- package/script/server/internal_jobs/projection.d.ts.map +1 -1
- package/script/server/internal_jobs/projection.js +2 -0
- package/script/server/internal_jobs/runtime-worker.d.ts +5 -1
- package/script/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/script/server/internal_jobs/runtime-worker.js +14 -2
- package/script/server/internal_jobs/types.d.ts +5 -5
- package/script/server/internal_jobs/types.d.ts.map +1 -1
- package/script/server/internal_jobs/types.js +6 -0
- package/script/server/service.d.ts +8 -3
- package/script/server/service.d.ts.map +1 -1
- package/script/server/service.js +126 -5
- package/script/service/drizzle.d.ts +27 -0
- package/script/service/drizzle.d.ts.map +1 -0
- package/script/service/drizzle.js +88 -0
- package/script/service/mod.d.ts +1 -1
- package/script/service/mod.d.ts.map +1 -1
- package/script/service/mod.js +1 -2
- package/script/service/outbox_inbox.d.ts.map +1 -1
- package/script/service/outbox_inbox.js +13 -2
- package/script/trellis.d.ts +24 -8
- package/script/trellis.d.ts.map +1 -1
- package/script/trellis.js +44 -22
- package/src/auth/mod.ts +28 -2
- package/src/auth/protocol.ts +72 -37
- package/src/codec.ts +1 -0
- package/src/contract_support/canonical.ts +3 -0
- package/src/contract_support/mod.ts +158 -5
- package/src/contract_support/protocol.ts +56 -9
- package/src/health.ts +0 -1
- package/src/index.ts +2 -1
- package/src/jobs.ts +138 -1
- package/src/sdk/_generated/auth/api.ts +9 -2
- package/src/sdk/_generated/auth/client.ts +85 -78
- package/src/sdk/_generated/auth/contract.ts +1803 -1435
- package/src/sdk/_generated/auth/schemas.ts +1166 -971
- package/src/sdk/_generated/auth/types.ts +330 -314
- package/src/sdk/_generated/core/api.ts +9 -2
- package/src/sdk/_generated/core/client.ts +41 -2
- package/src/sdk/_generated/core/contract.ts +91 -1
- package/src/sdk/_generated/core/schemas.ts +81 -0
- package/src/sdk/_generated/core/types.ts +23 -1
- package/src/sdk/_generated/health/client.ts +6 -6
- package/src/sdk/_generated/health/contract.ts +2 -10
- package/src/sdk/_generated/health/schemas.ts +1 -9
- package/src/sdk/_generated/health/types.ts +6 -2
- package/src/sdk/_generated/jobs/client.ts +17 -6
- package/src/sdk/_generated/jobs/contract.ts +269 -1
- package/src/sdk/_generated/jobs/owned_api.ts +21 -0
- package/src/sdk/_generated/jobs/schemas.ts +213 -0
- package/src/sdk/_generated/jobs/types.ts +116 -1
- package/src/sdk/_generated/state/client.ts +6 -6
- package/src/server/health.ts +2 -6
- package/src/server/health_schemas.ts +0 -6
- package/src/server/internal_jobs/bindings.ts +11 -0
- package/src/server/internal_jobs/job-manager.ts +436 -16
- package/src/server/internal_jobs/key-coordinator.ts +955 -0
- package/src/server/internal_jobs/projection.ts +2 -0
- package/src/server/internal_jobs/runtime-worker.ts +17 -1
- package/src/server/internal_jobs/types.ts +6 -0
- package/src/server/service.ts +168 -9
- package/src/service/drizzle.ts +125 -0
- package/src/service/mod.ts +0 -1
- package/src/service/outbox_inbox.ts +16 -6
- package/src/trellis.ts +76 -27
|
@@ -9,12 +9,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _JobManager_instances, _JobManager_context, _JobManager_meta, _JobManager_getQueueBinding, _JobManager_publishJobEvent;
|
|
12
|
+
var _JobManager_instances, _JobManager_context, _JobManager_meta, _JobManager_getQueueBinding, _JobManager_publishJobEvent, _JobManager_submit, _JobManager_admitKeyedCreate, _JobManager_removeQueuedKeyedReservation, _JobManager_restoreReplacedKeyedReservation, _JobManager_publishSkipped, _JobManager_keyedHeartbeat, _JobManager_releaseKeyedSlot, _JobManager_releaseKeyedSlotAfterPublishFailure, _JobManager_publishStaleCompletionIgnored;
|
|
13
13
|
import { headers as natsHeaders } from "@nats-io/nats-core";
|
|
14
14
|
import { ulid } from "ulid";
|
|
15
15
|
import { createMapCarrier, injectTraceContext, } from "../../telemetry/carrier.js";
|
|
16
16
|
import { recordTrellisError } from "../../telemetry/mod.js";
|
|
17
|
+
import { JobNotEnqueuedError } from "../../jobs.js";
|
|
17
18
|
import { ActiveJob, ActiveJobRuntimeError, JobCancellationToken, } from "./active-job.js";
|
|
19
|
+
import { normalizeJobKeyPolicy } from "./key-coordinator.js";
|
|
18
20
|
export class JobProcessError extends Error {
|
|
19
21
|
constructor(kind, message) {
|
|
20
22
|
super(message);
|
|
@@ -41,41 +43,47 @@ export class JobManager {
|
|
|
41
43
|
__classPrivateFieldSet(this, _JobManager_context, context, "f");
|
|
42
44
|
}
|
|
43
45
|
async create(type, payload) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
await __classPrivateFieldGet(this, _JobManager_instances, "m",
|
|
78
|
-
|
|
46
|
+
const outcome = await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_submit).call(this, type, payload, true);
|
|
47
|
+
if (outcome.kind === "accepted") {
|
|
48
|
+
return outcome.job;
|
|
49
|
+
}
|
|
50
|
+
if (outcome.kind === "coalesced") {
|
|
51
|
+
throw new JobNotEnqueuedError({
|
|
52
|
+
reason: "coalesced",
|
|
53
|
+
key: outcome.key,
|
|
54
|
+
active: 0,
|
|
55
|
+
queued: 1,
|
|
56
|
+
limit: 0,
|
|
57
|
+
existingJobId: outcome.existing.id,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (outcome.kind === "replaced") {
|
|
61
|
+
throw new JobNotEnqueuedError({
|
|
62
|
+
reason: "queue-depth",
|
|
63
|
+
key: outcome.key,
|
|
64
|
+
active: 0,
|
|
65
|
+
queued: 1,
|
|
66
|
+
limit: 0,
|
|
67
|
+
existingJobId: outcome.replaced.id,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
throw new JobNotEnqueuedError({
|
|
71
|
+
reason: outcome.reason,
|
|
72
|
+
key: outcome.key,
|
|
73
|
+
active: outcome.active,
|
|
74
|
+
queued: outcome.queued,
|
|
75
|
+
limit: outcome.limit,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async submit(type, payload) {
|
|
79
|
+
return await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_submit).call(this, type, payload, false);
|
|
80
|
+
}
|
|
81
|
+
async cleanupQueuedKeyedJob(job) {
|
|
82
|
+
const queue = __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_getQueueBinding).call(this, job.type);
|
|
83
|
+
const keyedPolicy = getKeyPolicy(queue);
|
|
84
|
+
if (!keyedPolicy)
|
|
85
|
+
return;
|
|
86
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_removeQueuedKeyedReservation).call(this, job, keyedPolicy);
|
|
79
87
|
}
|
|
80
88
|
process(job, cancellation, handler, metadata = {}, validation = {}) {
|
|
81
89
|
return this.processWithHeartbeat(job, cancellation, () => {
|
|
@@ -83,25 +91,78 @@ export class JobManager {
|
|
|
83
91
|
}, handler, metadata, validation);
|
|
84
92
|
}
|
|
85
93
|
async processWithHeartbeat(job, cancellation, heartbeat, handler, metadata = {}, validation = {}) {
|
|
86
|
-
__classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_getQueueBinding).call(this, job.type);
|
|
87
94
|
const tries = job.tries + 1;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
const queue = __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_getQueueBinding).call(this, job.type);
|
|
96
|
+
const keyedPolicy = getKeyPolicy(queue);
|
|
97
|
+
let lease;
|
|
98
|
+
let staleSlots = [];
|
|
99
|
+
if (keyedPolicy) {
|
|
100
|
+
const coordinator = __classPrivateFieldGet(this, _JobManager_context, "f").keyCoordinator;
|
|
101
|
+
if (!coordinator) {
|
|
102
|
+
throw new Error(`Keyed jobs queue '${job.type}' requires the JOBS_KEYS coordinator`);
|
|
103
|
+
}
|
|
104
|
+
const acquired = await coordinator.acquireActiveSlot({
|
|
105
|
+
service: job.service,
|
|
106
|
+
jobType: job.type,
|
|
107
|
+
jobId: job.id,
|
|
108
|
+
payload: job.payload,
|
|
109
|
+
context: job.context,
|
|
110
|
+
lifecycleState: metadata.latestState ?? job.state,
|
|
111
|
+
tries,
|
|
112
|
+
instanceId: metadata.instanceId ?? "unknown",
|
|
113
|
+
now: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
114
|
+
policy: keyedPolicy,
|
|
115
|
+
});
|
|
116
|
+
if (acquired.kind === "blocked") {
|
|
117
|
+
return { outcome: "deferred", tries, reason: acquired.reason };
|
|
118
|
+
}
|
|
119
|
+
lease = {
|
|
120
|
+
key: acquired.key,
|
|
121
|
+
keyHash: acquired.keyHash,
|
|
122
|
+
slotToken: acquired.slotToken,
|
|
123
|
+
policy: keyedPolicy,
|
|
124
|
+
};
|
|
125
|
+
staleSlots = acquired.stale;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
for (const stale of staleSlots) {
|
|
129
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, job.type, stale.jobId, {
|
|
130
|
+
jobId: stale.jobId,
|
|
131
|
+
service: job.service,
|
|
132
|
+
jobType: job.type,
|
|
133
|
+
eventType: "stale",
|
|
134
|
+
state: "stale",
|
|
135
|
+
previousState: "active",
|
|
136
|
+
context: stale.context,
|
|
137
|
+
tries: stale.tries,
|
|
138
|
+
error: "keyed job lease expired",
|
|
139
|
+
timestamp: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, job.type, job.id, {
|
|
143
|
+
jobId: job.id,
|
|
144
|
+
service: job.service,
|
|
145
|
+
jobType: job.type,
|
|
146
|
+
eventType: "started",
|
|
147
|
+
state: "active",
|
|
148
|
+
previousState: job.state,
|
|
149
|
+
context: job.context,
|
|
150
|
+
tries,
|
|
151
|
+
timestamp: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlotAfterPublishFailure).call(this, job, lease, error);
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
99
158
|
try {
|
|
100
|
-
const result = await this.withActiveJobAndHeartbeat({ ...job, state: "active", tries }, cancellation, heartbeat, handler, metadata);
|
|
159
|
+
const result = await this.withActiveJobAndHeartbeat({ ...job, state: "active", tries }, cancellation, lease ? __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_keyedHeartbeat).call(this, job, lease, heartbeat) : heartbeat, handler, metadata, lease);
|
|
101
160
|
if (cancellation.isHostShutdown()) {
|
|
161
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
102
162
|
return { outcome: "interrupted", tries };
|
|
103
163
|
}
|
|
104
164
|
if (cancellation.isCancelled()) {
|
|
165
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
105
166
|
return { outcome: "cancelled", tries };
|
|
106
167
|
}
|
|
107
168
|
try {
|
|
@@ -114,6 +175,11 @@ export class JobManager {
|
|
|
114
175
|
catch (error) {
|
|
115
176
|
throw JobProcessError.failed(error instanceof Error ? error.message : String(error));
|
|
116
177
|
}
|
|
178
|
+
const release = await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
179
|
+
if (release === "staleCompletion") {
|
|
180
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishStaleCompletionIgnored).call(this, job, tries);
|
|
181
|
+
return { outcome: "stale_completion_ignored", tries };
|
|
182
|
+
}
|
|
117
183
|
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, job.type, job.id, {
|
|
118
184
|
jobId: job.id,
|
|
119
185
|
service: job.service,
|
|
@@ -130,9 +196,11 @@ export class JobManager {
|
|
|
130
196
|
}
|
|
131
197
|
catch (error) {
|
|
132
198
|
if (cancellation.isHostShutdown()) {
|
|
199
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
133
200
|
return { outcome: "interrupted", tries };
|
|
134
201
|
}
|
|
135
202
|
if (cancellation.isCancelled()) {
|
|
203
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
136
204
|
return { outcome: "cancelled", tries };
|
|
137
205
|
}
|
|
138
206
|
if (error instanceof JobProcessError) {
|
|
@@ -144,6 +212,11 @@ export class JobManager {
|
|
|
144
212
|
operation: job.type,
|
|
145
213
|
phase: "handler_result",
|
|
146
214
|
});
|
|
215
|
+
const release = await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
216
|
+
if (release === "staleCompletion") {
|
|
217
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishStaleCompletionIgnored).call(this, job, tries);
|
|
218
|
+
return { outcome: "stale_completion_ignored", tries };
|
|
219
|
+
}
|
|
147
220
|
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, job.type, job.id, {
|
|
148
221
|
jobId: job.id,
|
|
149
222
|
service: job.service,
|
|
@@ -164,6 +237,11 @@ export class JobManager {
|
|
|
164
237
|
operation: job.type,
|
|
165
238
|
phase: "handler_result",
|
|
166
239
|
});
|
|
240
|
+
const release = await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
241
|
+
if (release === "staleCompletion") {
|
|
242
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishStaleCompletionIgnored).call(this, job, tries);
|
|
243
|
+
return { outcome: "stale_completion_ignored", tries };
|
|
244
|
+
}
|
|
167
245
|
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, job.type, job.id, {
|
|
168
246
|
jobId: job.id,
|
|
169
247
|
service: job.service,
|
|
@@ -234,7 +312,10 @@ export class JobManager {
|
|
|
234
312
|
throw new ActiveJobRuntimeError("worker heartbeat unavailable");
|
|
235
313
|
}, f, metadata);
|
|
236
314
|
}
|
|
237
|
-
async withActiveJobAndHeartbeat(job, cancellation, heartbeat, f, metadata = {}) {
|
|
315
|
+
async withActiveJobAndHeartbeat(job, cancellation, heartbeat, f, metadata = {}, lease) {
|
|
316
|
+
const stopAutoHeartbeat = lease
|
|
317
|
+
? startAutoHeartbeat(heartbeat, lease.policy.heartbeatIntervalMs)
|
|
318
|
+
: () => { };
|
|
238
319
|
const activeJob = new ActiveJob(job, cancellation, {
|
|
239
320
|
updateProgress: (progress) => this.emitProgress(job, progress),
|
|
240
321
|
log: (entry) => this.emitLog(job, entry),
|
|
@@ -252,7 +333,12 @@ export class JobManager {
|
|
|
252
333
|
}, {
|
|
253
334
|
redeliveryCount: metadata.redeliveryCount ?? 0,
|
|
254
335
|
});
|
|
255
|
-
|
|
336
|
+
try {
|
|
337
|
+
return await f(activeJob);
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
stopAutoHeartbeat();
|
|
341
|
+
}
|
|
256
342
|
}
|
|
257
343
|
}
|
|
258
344
|
_JobManager_context = new WeakMap(), _JobManager_instances = new WeakSet(), _JobManager_meta = function _JobManager_meta() {
|
|
@@ -282,7 +368,231 @@ _JobManager_context = new WeakMap(), _JobManager_instances = new WeakSet(), _Job
|
|
|
282
368
|
});
|
|
283
369
|
throw error;
|
|
284
370
|
}
|
|
371
|
+
}, _JobManager_submit = async function _JobManager_submit(type, payload, strictCreate) {
|
|
372
|
+
const binding = __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_getQueueBinding).call(this, type);
|
|
373
|
+
const meta = __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this);
|
|
374
|
+
const now = meta.nowIso();
|
|
375
|
+
const id = meta.nextJobId();
|
|
376
|
+
const context = createJobContext();
|
|
377
|
+
const namespace = __classPrivateFieldGet(this, _JobManager_context, "f").jobs.namespace;
|
|
378
|
+
const deadline = computeDeadline(now, binding.defaultDeadlineMs);
|
|
379
|
+
const job = {
|
|
380
|
+
id,
|
|
381
|
+
service: namespace,
|
|
382
|
+
type,
|
|
383
|
+
state: "pending",
|
|
384
|
+
context,
|
|
385
|
+
payload,
|
|
386
|
+
createdAt: now,
|
|
387
|
+
updatedAt: now,
|
|
388
|
+
tries: 0,
|
|
389
|
+
maxTries: binding.maxDeliver,
|
|
390
|
+
...(deadline ? { deadline } : {}),
|
|
391
|
+
};
|
|
392
|
+
const event = {
|
|
393
|
+
jobId: id,
|
|
394
|
+
service: job.service,
|
|
395
|
+
jobType: type,
|
|
396
|
+
eventType: "created",
|
|
397
|
+
state: "pending",
|
|
398
|
+
context,
|
|
399
|
+
tries: 0,
|
|
400
|
+
maxTries: binding.maxDeliver,
|
|
401
|
+
payload,
|
|
402
|
+
...(deadline ? { deadline } : {}),
|
|
403
|
+
timestamp: now,
|
|
404
|
+
};
|
|
405
|
+
const keyedPolicy = getKeyPolicy(binding);
|
|
406
|
+
if (keyedPolicy) {
|
|
407
|
+
const admission = await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_admitKeyedCreate).call(this, {
|
|
408
|
+
type,
|
|
409
|
+
job,
|
|
410
|
+
event,
|
|
411
|
+
policy: keyedPolicy,
|
|
412
|
+
strictCreate,
|
|
413
|
+
});
|
|
414
|
+
if (admission.kind !== "accepted" && admission.kind !== "replaced") {
|
|
415
|
+
return admission;
|
|
416
|
+
}
|
|
417
|
+
if (strictCreate && admission.kind === "replaced") {
|
|
418
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_restoreReplacedKeyedReservation).call(this, job, admission.replaced, keyedPolicy);
|
|
419
|
+
return {
|
|
420
|
+
kind: "rejected",
|
|
421
|
+
key: admission.key,
|
|
422
|
+
reason: "queue-depth",
|
|
423
|
+
active: admission.state.active.length,
|
|
424
|
+
queued: admission.state.queued.length,
|
|
425
|
+
limit: keyedPolicy.queue.maxQueuedPerKey,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
if (admission.kind === "replaced") {
|
|
429
|
+
try {
|
|
430
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishSkipped).call(this, type, admission.replaced, now);
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_restoreReplacedKeyedReservation).call(this, job, admission.replaced, keyedPolicy);
|
|
434
|
+
throw error;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
try {
|
|
438
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, type, id, event);
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_removeQueuedKeyedReservation).call(this, job, keyedPolicy);
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
if (admission.kind === "replaced") {
|
|
445
|
+
return {
|
|
446
|
+
kind: "replaced",
|
|
447
|
+
key: admission.key,
|
|
448
|
+
replaced: {
|
|
449
|
+
service: admission.replaced.service,
|
|
450
|
+
jobType: admission.replaced.jobType,
|
|
451
|
+
id: admission.replaced.id,
|
|
452
|
+
},
|
|
453
|
+
job,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
return { kind: "accepted", job, key: admission.key };
|
|
457
|
+
}
|
|
458
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, type, id, event);
|
|
459
|
+
return { kind: "accepted", job };
|
|
460
|
+
}, _JobManager_admitKeyedCreate = async function _JobManager_admitKeyedCreate(args) {
|
|
461
|
+
const coordinator = __classPrivateFieldGet(this, _JobManager_context, "f").keyCoordinator;
|
|
462
|
+
if (!coordinator) {
|
|
463
|
+
throw new Error(`Keyed jobs queue '${args.type}' requires the JOBS_KEYS coordinator`);
|
|
464
|
+
}
|
|
465
|
+
return await coordinator.admitCreate({
|
|
466
|
+
service: args.job.service,
|
|
467
|
+
jobType: args.type,
|
|
468
|
+
jobId: args.job.id,
|
|
469
|
+
payload: args.job.payload,
|
|
470
|
+
context: args.event.context,
|
|
471
|
+
createdAt: args.event.timestamp,
|
|
472
|
+
policy: args.policy,
|
|
473
|
+
strictCreate: args.strictCreate,
|
|
474
|
+
});
|
|
475
|
+
}, _JobManager_removeQueuedKeyedReservation = async function _JobManager_removeQueuedKeyedReservation(job, policy) {
|
|
476
|
+
const coordinator = __classPrivateFieldGet(this, _JobManager_context, "f").keyCoordinator;
|
|
477
|
+
if (!coordinator)
|
|
478
|
+
return;
|
|
479
|
+
await coordinator.removeQueuedJob({
|
|
480
|
+
service: job.service,
|
|
481
|
+
jobType: job.type,
|
|
482
|
+
jobId: job.id,
|
|
483
|
+
payload: job.payload,
|
|
484
|
+
now: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
485
|
+
policy,
|
|
486
|
+
});
|
|
487
|
+
}, _JobManager_restoreReplacedKeyedReservation = async function _JobManager_restoreReplacedKeyedReservation(job, replaced, policy) {
|
|
488
|
+
const coordinator = __classPrivateFieldGet(this, _JobManager_context, "f").keyCoordinator;
|
|
489
|
+
if (!coordinator)
|
|
490
|
+
return;
|
|
491
|
+
await coordinator.restoreReplacedQueuedJob({
|
|
492
|
+
service: job.service,
|
|
493
|
+
jobType: job.type,
|
|
494
|
+
replacementJobId: job.id,
|
|
495
|
+
replaced,
|
|
496
|
+
payload: job.payload,
|
|
497
|
+
now: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
498
|
+
policy,
|
|
499
|
+
});
|
|
500
|
+
}, _JobManager_publishSkipped = async function _JobManager_publishSkipped(type, replaced, timestamp) {
|
|
501
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, type, replaced.id, {
|
|
502
|
+
jobId: replaced.id,
|
|
503
|
+
service: __classPrivateFieldGet(this, _JobManager_context, "f").jobs.namespace,
|
|
504
|
+
jobType: type,
|
|
505
|
+
eventType: "skipped",
|
|
506
|
+
state: "skipped",
|
|
507
|
+
previousState: "pending",
|
|
508
|
+
context: replaced.context,
|
|
509
|
+
tries: 0,
|
|
510
|
+
error: "replaced by newer keyed job",
|
|
511
|
+
timestamp,
|
|
512
|
+
});
|
|
513
|
+
}, _JobManager_keyedHeartbeat = function _JobManager_keyedHeartbeat(job, lease, heartbeat) {
|
|
514
|
+
return async () => {
|
|
515
|
+
await heartbeat();
|
|
516
|
+
const renewed = await __classPrivateFieldGet(this, _JobManager_context, "f").keyCoordinator.renewHeartbeat({
|
|
517
|
+
service: job.service,
|
|
518
|
+
jobType: job.type,
|
|
519
|
+
jobId: job.id,
|
|
520
|
+
lease,
|
|
521
|
+
now: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
522
|
+
});
|
|
523
|
+
if (renewed.kind === "lost") {
|
|
524
|
+
recordTrellisError(new ActiveJobRuntimeError("keyed job slot lease was lost"), {
|
|
525
|
+
surface: "job",
|
|
526
|
+
direction: "worker",
|
|
527
|
+
operation: job.type,
|
|
528
|
+
phase: "heartbeat",
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
}, _JobManager_releaseKeyedSlot = async function _JobManager_releaseKeyedSlot(job, lease) {
|
|
533
|
+
if (!lease)
|
|
534
|
+
return undefined;
|
|
535
|
+
const released = await __classPrivateFieldGet(this, _JobManager_context, "f").keyCoordinator.releaseActiveSlot({
|
|
536
|
+
service: job.service,
|
|
537
|
+
jobType: job.type,
|
|
538
|
+
jobId: job.id,
|
|
539
|
+
lease,
|
|
540
|
+
now: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
541
|
+
});
|
|
542
|
+
return released.kind === "released" ? "released" : "staleCompletion";
|
|
543
|
+
}, _JobManager_releaseKeyedSlotAfterPublishFailure = async function _JobManager_releaseKeyedSlotAfterPublishFailure(job, lease, publishError) {
|
|
544
|
+
try {
|
|
545
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_releaseKeyedSlot).call(this, job, lease);
|
|
546
|
+
}
|
|
547
|
+
catch (cleanupError) {
|
|
548
|
+
recordTrellisError(cleanupError, {
|
|
549
|
+
surface: "job",
|
|
550
|
+
direction: "worker",
|
|
551
|
+
operation: job.type,
|
|
552
|
+
phase: "keyed_slot_cleanup",
|
|
553
|
+
});
|
|
554
|
+
recordTrellisError(publishError, {
|
|
555
|
+
surface: "job",
|
|
556
|
+
direction: "worker",
|
|
557
|
+
operation: job.type,
|
|
558
|
+
phase: "publish",
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
}, _JobManager_publishStaleCompletionIgnored = async function _JobManager_publishStaleCompletionIgnored(job, tries) {
|
|
562
|
+
await __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_publishJobEvent).call(this, job.type, job.id, {
|
|
563
|
+
jobId: job.id,
|
|
564
|
+
service: job.service,
|
|
565
|
+
jobType: job.type,
|
|
566
|
+
eventType: "staleCompletionIgnored",
|
|
567
|
+
state: "stale",
|
|
568
|
+
previousState: "active",
|
|
569
|
+
context: job.context,
|
|
570
|
+
tries,
|
|
571
|
+
error: "keyed job slot lease was lost before completion",
|
|
572
|
+
timestamp: __classPrivateFieldGet(this, _JobManager_instances, "m", _JobManager_meta).call(this).nowIso(),
|
|
573
|
+
});
|
|
285
574
|
};
|
|
575
|
+
function getKeyPolicy(binding) {
|
|
576
|
+
if (!binding.keyConcurrency) {
|
|
577
|
+
return undefined;
|
|
578
|
+
}
|
|
579
|
+
return normalizeJobKeyPolicy({
|
|
580
|
+
keyConcurrency: binding.keyConcurrency,
|
|
581
|
+
queue: binding.queue,
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
function startAutoHeartbeat(heartbeat, intervalMs) {
|
|
585
|
+
const timer = setInterval(() => {
|
|
586
|
+
void heartbeat().catch((error) => {
|
|
587
|
+
recordTrellisError(error, {
|
|
588
|
+
surface: "job",
|
|
589
|
+
direction: "worker",
|
|
590
|
+
phase: "heartbeat",
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
}, intervalMs);
|
|
594
|
+
return () => clearInterval(timer);
|
|
595
|
+
}
|
|
286
596
|
function computeDeadline(now, deadlineMs) {
|
|
287
597
|
if (deadlineMs === undefined) {
|
|
288
598
|
return undefined;
|