@relaycast/engine 12.2.0 → 12.3.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/dist/adapters/actor/credential-tag.d.ts +14 -0
- package/dist/adapters/actor/credential-tag.d.ts.map +1 -0
- package/dist/adapters/actor/credential-tag.js +30 -0
- package/dist/adapters/actor/credential-tag.js.map +1 -0
- package/dist/adapters/actor/database.d.ts +50 -0
- package/dist/adapters/actor/database.d.ts.map +1 -0
- package/dist/adapters/actor/database.js +86 -0
- package/dist/adapters/actor/database.js.map +1 -0
- package/dist/adapters/actor/ephemeral-outbox.d.ts +16 -0
- package/dist/adapters/actor/ephemeral-outbox.d.ts.map +1 -0
- package/dist/adapters/actor/ephemeral-outbox.js +53 -0
- package/dist/adapters/actor/ephemeral-outbox.js.map +1 -0
- package/dist/adapters/actor/event-queue.d.ts +23 -0
- package/dist/adapters/actor/event-queue.d.ts.map +1 -0
- package/dist/adapters/actor/event-queue.js +31 -0
- package/dist/adapters/actor/event-queue.js.map +1 -0
- package/dist/adapters/actor/files.d.ts +66 -0
- package/dist/adapters/actor/files.d.ts.map +1 -0
- package/dist/adapters/actor/files.js +83 -0
- package/dist/adapters/actor/files.js.map +1 -0
- package/dist/adapters/actor/http.d.ts +19 -0
- package/dist/adapters/actor/http.d.ts.map +1 -0
- package/dist/adapters/actor/http.js +2 -0
- package/dist/adapters/actor/http.js.map +1 -0
- package/dist/adapters/actor/index.d.ts +90 -0
- package/dist/adapters/actor/index.d.ts.map +1 -0
- package/dist/adapters/actor/index.js +299 -0
- package/dist/adapters/actor/index.js.map +1 -0
- package/dist/adapters/actor/kv.d.ts +21 -0
- package/dist/adapters/actor/kv.d.ts.map +1 -0
- package/dist/adapters/actor/kv.js +33 -0
- package/dist/adapters/actor/kv.js.map +1 -0
- package/dist/adapters/actor/migrations.d.ts +15 -0
- package/dist/adapters/actor/migrations.d.ts.map +1 -0
- package/dist/adapters/actor/migrations.generated.d.ts +5 -0
- package/dist/adapters/actor/migrations.generated.d.ts.map +1 -0
- package/dist/adapters/actor/migrations.generated.js +842 -0
- package/dist/adapters/actor/migrations.generated.js.map +1 -0
- package/dist/adapters/actor/migrations.js +32 -0
- package/dist/adapters/actor/migrations.js.map +1 -0
- package/dist/adapters/node/files.d.ts +2 -0
- package/dist/adapters/node/files.d.ts.map +1 -1
- package/dist/adapters/node/files.js +31 -3
- package/dist/adapters/node/files.js.map +1 -1
- package/dist/adapters/node/index.js +1 -1
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/auth/credentialTags.d.ts +43 -0
- package/dist/auth/credentialTags.d.ts.map +1 -0
- package/dist/auth/credentialTags.js +106 -0
- package/dist/auth/credentialTags.js.map +1 -0
- package/dist/auth/credentials.d.ts +103 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +147 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/index.d.ts +7 -4
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +115 -61
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/tokenKind.d.ts +17 -26
- package/dist/auth/tokenKind.d.ts.map +1 -1
- package/dist/auth/tokenKind.js +17 -46
- package/dist/auth/tokenKind.js.map +1 -1
- package/dist/auth/workspaceExpiry.d.ts +2 -0
- package/dist/auth/workspaceExpiry.d.ts.map +1 -1
- package/dist/auth/workspaceExpiry.js +7 -0
- package/dist/auth/workspaceExpiry.js.map +1 -1
- package/dist/bin/secretEnv.d.ts +17 -0
- package/dist/bin/secretEnv.d.ts.map +1 -0
- package/dist/bin/secretEnv.js +33 -0
- package/dist/bin/secretEnv.js.map +1 -0
- package/dist/bin/serve.js +42 -4
- package/dist/bin/serve.js.map +1 -1
- package/dist/config/credentialEnv.d.ts +19 -0
- package/dist/config/credentialEnv.d.ts.map +1 -0
- package/dist/config/credentialEnv.js +53 -0
- package/dist/config/credentialEnv.js.map +1 -0
- package/dist/db/migrations/0078_dm_participant_read_cursor.sql +15 -0
- package/dist/db/migrations/0079_credential_upgrades.sql +17 -0
- package/dist/db/schema.d.ts +183 -2
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +23 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/engine/a2a.d.ts +1 -1
- package/dist/engine/a2a.d.ts.map +1 -1
- package/dist/engine/a2a.js +2 -2
- package/dist/engine/a2a.js.map +1 -1
- package/dist/engine/a2aEgress.d.ts +3 -2
- package/dist/engine/a2aEgress.d.ts.map +1 -1
- package/dist/engine/a2aEgress.js +5 -4
- package/dist/engine/a2aEgress.js.map +1 -1
- package/dist/engine/action.d.ts +12 -0
- package/dist/engine/action.d.ts.map +1 -1
- package/dist/engine/action.js +45 -1
- package/dist/engine/action.js.map +1 -1
- package/dist/engine/agent.d.ts.map +1 -1
- package/dist/engine/agent.js +2 -1
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/agentIdentity.d.ts.map +1 -1
- package/dist/engine/agentIdentity.js +2 -1
- package/dist/engine/agentIdentity.js.map +1 -1
- package/dist/engine/credentialUpgrade.d.ts +48 -0
- package/dist/engine/credentialUpgrade.d.ts.map +1 -0
- package/dist/engine/credentialUpgrade.js +176 -0
- package/dist/engine/credentialUpgrade.js.map +1 -0
- package/dist/engine/delivery.d.ts.map +1 -1
- package/dist/engine/delivery.js +70 -31
- package/dist/engine/delivery.js.map +1 -1
- package/dist/engine/eventDispatch.d.ts.map +1 -1
- package/dist/engine/eventDispatch.js +3 -2
- package/dist/engine/eventDispatch.js.map +1 -1
- package/dist/engine/eventSubscription.d.ts +4 -4
- package/dist/engine/file.d.ts +8 -0
- package/dist/engine/file.d.ts.map +1 -1
- package/dist/engine/file.js +18 -5
- package/dist/engine/file.js.map +1 -1
- package/dist/engine/inboundWebhook.d.ts +2 -0
- package/dist/engine/inboundWebhook.d.ts.map +1 -1
- package/dist/engine/inboundWebhook.js +10 -4
- package/dist/engine/inboundWebhook.js.map +1 -1
- package/dist/engine/inbox.d.ts.map +1 -1
- package/dist/engine/inbox.js +10 -5
- package/dist/engine/inbox.js.map +1 -1
- package/dist/engine/internalAdmin.d.ts +80 -0
- package/dist/engine/internalAdmin.d.ts.map +1 -0
- package/dist/engine/internalAdmin.js +329 -0
- package/dist/engine/internalAdmin.js.map +1 -0
- package/dist/engine/invocationCompletion.d.ts.map +1 -1
- package/dist/engine/invocationCompletion.js +23 -5
- package/dist/engine/invocationCompletion.js.map +1 -1
- package/dist/engine/node.d.ts +38 -1
- package/dist/engine/node.d.ts.map +1 -1
- package/dist/engine/node.js +166 -11
- package/dist/engine/node.js.map +1 -1
- package/dist/engine/nodeContext.d.ts +2 -1
- package/dist/engine/nodeContext.d.ts.map +1 -1
- package/dist/engine/nodeContext.js +1 -1
- package/dist/engine/nodeContext.js.map +1 -1
- package/dist/engine/nodeDeliver.d.ts +2 -1
- package/dist/engine/nodeDeliver.d.ts.map +1 -1
- package/dist/engine/nodeDeliver.js +1 -1
- package/dist/engine/nodeDeliver.js.map +1 -1
- package/dist/engine/observerToken.d.ts +4 -0
- package/dist/engine/observerToken.d.ts.map +1 -1
- package/dist/engine/observerToken.js +14 -5
- package/dist/engine/observerToken.js.map +1 -1
- package/dist/engine/receipt.d.ts +100 -0
- package/dist/engine/receipt.d.ts.map +1 -1
- package/dist/engine/receipt.js +12 -0
- package/dist/engine/receipt.js.map +1 -1
- package/dist/engine/taskInvocation.d.ts +1 -1
- package/dist/engine/tokenRotate.d.ts.map +1 -1
- package/dist/engine/tokenRotate.js +4 -3
- package/dist/engine/tokenRotate.js.map +1 -1
- package/dist/engine/workspace.d.ts +8 -2
- package/dist/engine/workspace.d.ts.map +1 -1
- package/dist/engine/workspace.js +70 -21
- package/dist/engine/workspace.js.map +1 -1
- package/dist/engine/wsAuth.d.ts.map +1 -1
- package/dist/engine/wsAuth.js +14 -3
- package/dist/engine/wsAuth.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +31 -0
- package/dist/engine.js.map +1 -1
- package/dist/entrypoints/node.d.ts +3 -1
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +33 -1
- package/dist/entrypoints/node.js.map +1 -1
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/gateway.d.ts +11 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +16 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/credentialNotice.d.ts +32 -0
- package/dist/lib/credentialNotice.d.ts.map +1 -0
- package/dist/lib/credentialNotice.js +76 -0
- package/dist/lib/credentialNotice.js.map +1 -0
- package/dist/lib/fileTokens.d.ts +30 -0
- package/dist/lib/fileTokens.d.ts.map +1 -0
- package/dist/lib/fileTokens.js +76 -0
- package/dist/lib/fileTokens.js.map +1 -0
- package/dist/lib/httpError.d.ts +1 -1
- package/dist/lib/httpResponse.d.ts +6 -6
- package/dist/middleware/admission.d.ts +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +22 -31
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +1 -1
- package/dist/middleware/logger.d.ts.map +1 -1
- package/dist/middleware/logger.js +4 -1
- package/dist/middleware/logger.js.map +1 -1
- package/dist/ports/database.d.ts.map +1 -1
- package/dist/ports/database.js +8 -2
- package/dist/ports/database.js.map +1 -1
- package/dist/ports/files.d.ts +7 -1
- package/dist/ports/files.d.ts.map +1 -1
- package/dist/ports/index.d.ts +64 -1
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +4 -0
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/telemetry.d.ts +1 -0
- package/dist/ports/telemetry.d.ts.map +1 -1
- package/dist/ports/telemetry.js +1 -0
- package/dist/ports/telemetry.js.map +1 -1
- package/dist/routes/action.d.ts.map +1 -1
- package/dist/routes/action.js +2 -1
- package/dist/routes/action.js.map +1 -1
- package/dist/routes/credential.d.ts +4 -0
- package/dist/routes/credential.d.ts.map +1 -0
- package/dist/routes/credential.js +97 -0
- package/dist/routes/credential.js.map +1 -0
- package/dist/routes/file.js +10 -4
- package/dist/routes/file.js.map +1 -1
- package/dist/routes/inboundWebhook.d.ts.map +1 -1
- package/dist/routes/inboundWebhook.js +11 -2
- package/dist/routes/inboundWebhook.js.map +1 -1
- package/dist/routes/internal.d.ts +14 -0
- package/dist/routes/internal.d.ts.map +1 -0
- package/dist/routes/internal.js +157 -0
- package/dist/routes/internal.js.map +1 -0
- package/dist/routes/node.d.ts.map +1 -1
- package/dist/routes/node.js +44 -2
- package/dist/routes/node.js.map +1 -1
- package/dist/routes/observerToken.js +1 -1
- package/dist/routes/observerToken.js.map +1 -1
- package/dist/routes/reaction.d.ts.map +1 -1
- package/dist/routes/reaction.js +3 -2
- package/dist/routes/reaction.js.map +1 -1
- package/dist/routes/receipt.d.ts.map +1 -1
- package/dist/routes/receipt.js +2 -1
- package/dist/routes/receipt.js.map +1 -1
- package/dist/routes/workspace.d.ts.map +1 -1
- package/dist/routes/workspace.js +12 -1
- package/dist/routes/workspace.js.map +1 -1
- package/package.json +12 -3
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { createEngine } from '../../engine.js';
|
|
2
|
+
import { safeTelemetrySink } from '../../ports/telemetry.js';
|
|
3
|
+
import { SqliteApiKeyAuthProvider } from '../../auth/index.js';
|
|
4
|
+
import { NoopTelemetrySink } from '../../providers/noop-telemetry.js';
|
|
5
|
+
import { InProcessRealtime } from '../node/realtime.js';
|
|
6
|
+
import { InProcessPresence } from '../node/presence.js';
|
|
7
|
+
import { InProcessRateLimiter } from '../node/rate-limit.js';
|
|
8
|
+
import { createDeliveryMaintenanceRunner } from '../node/delivery-maintenance.js';
|
|
9
|
+
import { sweepOfflineNodes } from '../../engine/node.js';
|
|
10
|
+
import { AGENT_LIVENESS_TTL_MS, sweepStaleAgents } from '../../engine/agent.js';
|
|
11
|
+
import { ACTION_DISPATCH_TIMEOUT_MS, ACTION_HANDLER_UNREACHABLE_TTL_MS, PENDING_INVOCATION_MAX_AGE_MS, sweepTimedOutInvocations, } from '../../engine/action.js';
|
|
12
|
+
import { A2A_EGRESS_RETRY_WINDOW_MS, sweepPendingA2aEgress } from '../../engine/a2aEgress.js';
|
|
13
|
+
import { reapExpiredWorkspaces } from '../../engine/workspace.js';
|
|
14
|
+
import { createActorEngineDb } from './database.js';
|
|
15
|
+
import { ActorCredentialTag } from './credential-tag.js';
|
|
16
|
+
import { fixedCredentialTagger } from '../../auth/credentialTags.js';
|
|
17
|
+
import { restrictToArCredentials } from '../../auth/credentials.js';
|
|
18
|
+
import { isArWorkspaceId } from '@relaycast/types';
|
|
19
|
+
import { applyActorMigrations } from './migrations.js';
|
|
20
|
+
import { ActorKeyValueStore, ensureActorKvTable } from './kv.js';
|
|
21
|
+
import { ActorEventQueue } from './event-queue.js';
|
|
22
|
+
import { SignedUrlFileStorage } from './files.js';
|
|
23
|
+
import { ActorEphemeralOutbox, ensureActorOutboundTable } from './ephemeral-outbox.js';
|
|
24
|
+
import { isSafeExternalUrl } from '../../lib/ssrf.js';
|
|
25
|
+
/** Liveness sweeps for connected nodes run on the self-host sweep cadence. */
|
|
26
|
+
const MAINTENANCE_INTERVAL_MS = 15_000;
|
|
27
|
+
const DEFAULT_BLOB_DELETE_BUDGET_MS = 15_000;
|
|
28
|
+
/** Work already due is retried no sooner than this, so a stuck row cannot spin the alarm. */
|
|
29
|
+
const MIN_RETRY_MS = 5_000;
|
|
30
|
+
class ExternalIoOutsideMaintenance extends Error {
|
|
31
|
+
constructor() {
|
|
32
|
+
super('Outbound HTTP is deferred to actor maintenance');
|
|
33
|
+
this.name = 'ExternalIoOutsideMaintenance';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function createActorRuntime(options) {
|
|
37
|
+
if (!isActorSql(options.sql))
|
|
38
|
+
throw new Error('the relaycast actor adapter requires durable-actors >= 0.14.5');
|
|
39
|
+
const sql = options.sql;
|
|
40
|
+
const blobDeleteBudgetMs = positiveDuration('blobDeleteBudgetMs', options.blobDeleteBudgetMs, DEFAULT_BLOB_DELETE_BUDGET_MS, 1);
|
|
41
|
+
// `ar_` credentials carry the workspace as a 64-bit snowflake.
|
|
42
|
+
if (!isArWorkspaceId(options.workspaceId)) {
|
|
43
|
+
throw new Error(`Workspace actor id ${JSON.stringify(options.workspaceId)} must be a 64-bit snowflake`);
|
|
44
|
+
}
|
|
45
|
+
let maintaining = false;
|
|
46
|
+
// Write groups of the running maintenance step: how many opened, and the failures.
|
|
47
|
+
let stepGroups = 0;
|
|
48
|
+
let stepFailures = [];
|
|
49
|
+
applyActorMigrations(sql);
|
|
50
|
+
ensureActorKvTable(sql);
|
|
51
|
+
ensureActorOutboundTable(sql);
|
|
52
|
+
const credentialTag = new ActorCredentialTag(sql);
|
|
53
|
+
const db = createActorEngineDb(sql, {
|
|
54
|
+
onGroupStart: () => { stepGroups += 1; },
|
|
55
|
+
onGroupFailure: (error) => { if (maintaining)
|
|
56
|
+
stepFailures.push({ index: stepGroups - 1, error }); },
|
|
57
|
+
});
|
|
58
|
+
const requestMaintenance = (atMs = Date.now()) => {
|
|
59
|
+
const current = options.alarm.get();
|
|
60
|
+
// A past timestamp is an alarm that already fired (or is firing now).
|
|
61
|
+
if (current !== null && current > Date.now() && current <= atMs)
|
|
62
|
+
return;
|
|
63
|
+
options.alarm.set(atMs);
|
|
64
|
+
};
|
|
65
|
+
// Outbound HTTP holds the actor's mailbox for its whole duration, so it runs
|
|
66
|
+
// only from maintenance. In a request it fails fast; durable work (webhook
|
|
67
|
+
// outbox, http_push deliveries, A2A egress, blob cleanup) records a
|
|
68
|
+
// retryable attempt, and maintenance redrives it.
|
|
69
|
+
const maintenanceOnly = (fetchImpl) => (input, init) => {
|
|
70
|
+
if (!maintaining) {
|
|
71
|
+
requestMaintenance();
|
|
72
|
+
return Promise.reject(new ExternalIoOutsideMaintenance());
|
|
73
|
+
}
|
|
74
|
+
return fetchImpl(input, init);
|
|
75
|
+
};
|
|
76
|
+
const guardedFetch = (input, init) => {
|
|
77
|
+
const url = input instanceof Request ? input.url : String(input);
|
|
78
|
+
if (!isSafeExternalUrl(url, { strict: true, requireHttps: true })) {
|
|
79
|
+
return Promise.reject(new Error('Outbound HTTP destination is not a public HTTPS URL'));
|
|
80
|
+
}
|
|
81
|
+
return options.outboundFetch(input, { ...init, redirect: 'manual' });
|
|
82
|
+
};
|
|
83
|
+
const outboundFetch = maintenanceOnly(guardedFetch);
|
|
84
|
+
// Ephemeral events have no delivery row to retry from, so a request queues
|
|
85
|
+
// them in the actor database (they commit or roll back with the call) and
|
|
86
|
+
// maintenance sends them.
|
|
87
|
+
const ephemeralOutbox = new ActorEphemeralOutbox(sql, guardedFetch);
|
|
88
|
+
const ephemeralEventFetch = async (input, init) => {
|
|
89
|
+
if (maintaining)
|
|
90
|
+
return guardedFetch(input, init);
|
|
91
|
+
await ephemeralOutbox.enqueue(new Request(input, init));
|
|
92
|
+
requestMaintenance();
|
|
93
|
+
return new Response(null, { status: 202 });
|
|
94
|
+
};
|
|
95
|
+
const telemetry = safeTelemetrySink(options.telemetry ?? new NoopTelemetrySink());
|
|
96
|
+
const realtime = new InProcessRealtime(db);
|
|
97
|
+
const presence = new InProcessPresence(realtime, { db, sweepIntervalMs: 0 });
|
|
98
|
+
realtime.setPresenceTracker(presence);
|
|
99
|
+
const kv = new ActorKeyValueStore(sql);
|
|
100
|
+
// Blob deletes share one time budget per maintenance pass, so a gateway that
|
|
101
|
+
// hangs can hold the mailbox for at most that long.
|
|
102
|
+
let blobDeadline = 0;
|
|
103
|
+
const blobDeleteFetch = (input, init) => {
|
|
104
|
+
const remaining = blobDeadline - Date.now();
|
|
105
|
+
if (remaining <= 0)
|
|
106
|
+
return Promise.reject(new Error('Blob delete budget for this maintenance pass is spent'));
|
|
107
|
+
const budget = AbortSignal.timeout(remaining);
|
|
108
|
+
return options.outboundFetch(input, { ...init, signal: init?.signal ? AbortSignal.any([init.signal, budget]) : budget });
|
|
109
|
+
};
|
|
110
|
+
// Completion's size check runs in the request: a short, bounded call to our
|
|
111
|
+
// own gateway (not an outside destination).
|
|
112
|
+
const statFetch = (input, init) => options.outboundFetch(input, init);
|
|
113
|
+
const files = new SignedUrlFileStorage({
|
|
114
|
+
baseUrl: options.baseUrl,
|
|
115
|
+
secret: options.fileSigningSecret,
|
|
116
|
+
fetch: maintenanceOnly(blobDeleteFetch),
|
|
117
|
+
statFetch,
|
|
118
|
+
});
|
|
119
|
+
const messageTtlDays = options.config?.retention?.messageTtlDays ?? null;
|
|
120
|
+
const webhookQueue = new ActorEventQueue(db, () => requestMaintenance(), (err, ctx) => telemetry.captureException(err, ctx), { fetch: outboundFetch, retention: { defaults: { messageTtlDays } } });
|
|
121
|
+
const config = {
|
|
122
|
+
...options.config,
|
|
123
|
+
workspaceId: options.workspaceId,
|
|
124
|
+
credentialFormat: 'ar',
|
|
125
|
+
credentialTagger: fixedCredentialTagger(options.workspaceId, () => credentialTag.get()),
|
|
126
|
+
outboundWebhookFetch: outboundFetch,
|
|
127
|
+
ephemeralEventFetch,
|
|
128
|
+
retention: { messageTtlDays },
|
|
129
|
+
};
|
|
130
|
+
const deps = {
|
|
131
|
+
db,
|
|
132
|
+
realtime,
|
|
133
|
+
connections: realtime,
|
|
134
|
+
nodeConnections: realtime,
|
|
135
|
+
presence,
|
|
136
|
+
rateLimiter: new InProcessRateLimiter(),
|
|
137
|
+
files,
|
|
138
|
+
kv,
|
|
139
|
+
webhookQueue,
|
|
140
|
+
auth: options.auth ?? new SqliteApiKeyAuthProvider(),
|
|
141
|
+
telemetry,
|
|
142
|
+
config,
|
|
143
|
+
};
|
|
144
|
+
realtime.setNodeCompletionDeps(deps);
|
|
145
|
+
// A workspace actor's deployment never issued legacy credentials.
|
|
146
|
+
restrictToArCredentials(db);
|
|
147
|
+
const app = createEngine(deps);
|
|
148
|
+
const runDeliveryMaintenance = createDeliveryMaintenanceRunner(deps);
|
|
149
|
+
const alert = (step, writeGroup, error) => {
|
|
150
|
+
telemetry.captureException(error, {
|
|
151
|
+
source: 'actor.maintenance',
|
|
152
|
+
alert: 'maintenance_rolled_back',
|
|
153
|
+
workspace_id: options.workspaceId,
|
|
154
|
+
step,
|
|
155
|
+
write_group: writeGroup,
|
|
156
|
+
error_code: errorCode(error),
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
/** Run one maintenance step in its own transaction; a failure rolls back that step (or group) alone. */
|
|
160
|
+
const runStep = async (step, work) => {
|
|
161
|
+
stepGroups = 0;
|
|
162
|
+
stepFailures = [];
|
|
163
|
+
try {
|
|
164
|
+
await sql.transaction(work);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
// A group whose error the step rethrew is the step's failure, reported once.
|
|
168
|
+
const failed = stepFailures.find((failure) => failure.error === error);
|
|
169
|
+
stepFailures = stepFailures.filter((failure) => failure !== failed);
|
|
170
|
+
alert(step, failed?.index ?? null, error);
|
|
171
|
+
}
|
|
172
|
+
// Groups that rolled back while the step went on.
|
|
173
|
+
for (const failure of stepFailures)
|
|
174
|
+
alert(step, failure.index, failure.error);
|
|
175
|
+
};
|
|
176
|
+
return {
|
|
177
|
+
deps,
|
|
178
|
+
async create(request, tag) {
|
|
179
|
+
const { pathname } = new URL(request.url);
|
|
180
|
+
if (request.method !== 'POST' || pathname !== '/v1/workspaces') {
|
|
181
|
+
throw new Error('create serves POST /v1/workspaces only');
|
|
182
|
+
}
|
|
183
|
+
credentialTag.set(tag);
|
|
184
|
+
return this.handle(request);
|
|
185
|
+
},
|
|
186
|
+
async handle(request) {
|
|
187
|
+
applyActorMigrations(sql);
|
|
188
|
+
const background = [];
|
|
189
|
+
const executionCtx = {
|
|
190
|
+
waitUntil: (promise) => { background.push(promise); },
|
|
191
|
+
passThroughOnException() { },
|
|
192
|
+
props: {},
|
|
193
|
+
};
|
|
194
|
+
const response = await app.fetch(new Request(request.url, {
|
|
195
|
+
method: request.method,
|
|
196
|
+
headers: request.headers,
|
|
197
|
+
body: request.body,
|
|
198
|
+
}), {}, executionCtx);
|
|
199
|
+
const body = await response.text();
|
|
200
|
+
// Background work can schedule more background work; settle all of it
|
|
201
|
+
// so it commits (or rolls back) with this call.
|
|
202
|
+
for (let settled = 0; settled < background.length; settled = background.length) {
|
|
203
|
+
await Promise.allSettled(background.slice(settled));
|
|
204
|
+
}
|
|
205
|
+
const next = nextMaintenanceAt(sql);
|
|
206
|
+
if (next !== null)
|
|
207
|
+
requestMaintenance(next);
|
|
208
|
+
return { status: response.status, headers: [...response.headers], body };
|
|
209
|
+
},
|
|
210
|
+
async maintain() {
|
|
211
|
+
applyActorMigrations(sql);
|
|
212
|
+
maintaining = true;
|
|
213
|
+
blobDeadline = Date.now() + blobDeleteBudgetMs;
|
|
214
|
+
try {
|
|
215
|
+
const steps = [
|
|
216
|
+
['kv_expiry', async () => kv.prune()],
|
|
217
|
+
['presence', () => presence.sweep()],
|
|
218
|
+
['stale_agents', () => sweepStaleAgents(db)],
|
|
219
|
+
['offline_nodes', () => sweepOfflineNodes(db, realtime, deps)],
|
|
220
|
+
['invocations', () => sweepTimedOutInvocations(db, realtime, { completionDeps: deps })],
|
|
221
|
+
['workspace_expiry', () => reapExpiredWorkspaces(db, files)],
|
|
222
|
+
['deliveries', () => runDeliveryMaintenance()],
|
|
223
|
+
['a2a_egress', () => sweepPendingA2aEgress(db, undefined, outboundFetch)],
|
|
224
|
+
['webhooks', () => webhookQueue.drain()],
|
|
225
|
+
['ephemeral_events', () => ephemeralOutbox.drain()],
|
|
226
|
+
];
|
|
227
|
+
for (const [step, work] of steps)
|
|
228
|
+
await runStep(step, work);
|
|
229
|
+
}
|
|
230
|
+
finally {
|
|
231
|
+
maintaining = false;
|
|
232
|
+
}
|
|
233
|
+
const next = nextMaintenanceAt(sql);
|
|
234
|
+
if (next !== null)
|
|
235
|
+
requestMaintenance(next);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* When maintenance next has something to do, from the workspace's own
|
|
241
|
+
* outstanding work: the nearest due time of the webhook outbox, unfinished
|
|
242
|
+
* deliveries (redrive and expiry), A2A egress, the invocation timeouts the
|
|
243
|
+
* invocation sweep acts on, including task deadlines (a plain queue waiting
|
|
244
|
+
* for its node to reconnect has none: the reconnect is a request, which
|
|
245
|
+
* re-arms), agent
|
|
246
|
+
* liveness, blob cleanup, workspace expiry, idempotency-record expiry, A2A
|
|
247
|
+
* retention, and queued ephemeral events, and
|
|
248
|
+
* the sweep cadence while nodes are connected. `null` when nothing is
|
|
249
|
+
* outstanding, so an idle workspace's actor goes dormant.
|
|
250
|
+
*/
|
|
251
|
+
export function nextMaintenanceAt(sql) {
|
|
252
|
+
const [row] = sql.exec(`SELECT MIN(due) AS due FROM (
|
|
253
|
+
SELECT MIN(process_after) AS due FROM pending_events WHERE status = 'pending'
|
|
254
|
+
UNION ALL SELECT MIN(next_attempt_at) FROM deliveries WHERE status NOT IN ('acked', 'dead_lettered', 'failed')
|
|
255
|
+
UNION ALL SELECT MIN(expires_at) FROM deliveries WHERE status NOT IN ('acked', 'dead_lettered', 'failed')
|
|
256
|
+
UNION ALL SELECT MIN(COALESCE(lease_until, 0)) FROM a2a_egress WHERE status IN ('pending', 'sending')
|
|
257
|
+
UNION ALL SELECT MIN(dispatched_at + ?) FROM action_invocations WHERE status = 'dispatched'
|
|
258
|
+
UNION ALL SELECT MIN(retry_after_at) FROM action_invocations WHERE status = 'pending'
|
|
259
|
+
UNION ALL SELECT MIN(created_at + ?) FROM action_invocations WHERE status = 'pending' AND dispatch_attempts = 0
|
|
260
|
+
UNION ALL SELECT MIN(handler_unreachable_since + ?) FROM action_invocations WHERE status IN ('pending', 'dispatched')
|
|
261
|
+
UNION ALL SELECT MIN(unixepoch(json_extract(task_state, '$.deadline'))) FROM action_invocations
|
|
262
|
+
WHERE task_state IS NOT NULL AND status IN ('pending', 'dispatched', 'running')
|
|
263
|
+
UNION ALL SELECT MIN(last_seen + ?) FROM agents WHERE status IN ('active', 'online')
|
|
264
|
+
UNION ALL SELECT MIN(unixepoch() + ?) FROM nodes WHERE status != 'offline'
|
|
265
|
+
UNION ALL SELECT MIN(process_after) FROM file_cleanup_queue
|
|
266
|
+
UNION ALL SELECT MIN(expires_at) FROM workspaces
|
|
267
|
+
UNION ALL SELECT MIN(expires_at) / 1000 FROM _actor_kv
|
|
268
|
+
UNION ALL SELECT MIN(created_at + ?) FROM a2a_egress WHERE status NOT IN ('pending', 'sending')
|
|
269
|
+
UNION ALL SELECT MIN(created_at + ?) FROM a2a_inbound
|
|
270
|
+
UNION ALL SELECT MIN(created_at + ?) FROM direct_dm_idempotency
|
|
271
|
+
UNION ALL SELECT MIN(0) FROM _actor_outbound
|
|
272
|
+
)`, Math.ceil(ACTION_DISPATCH_TIMEOUT_MS / 1000), Math.ceil(PENDING_INVOCATION_MAX_AGE_MS / 1000), Math.ceil(ACTION_HANDLER_UNREACHABLE_TTL_MS / 1000), Math.ceil(AGENT_LIVENESS_TTL_MS / 1000), Math.ceil(MAINTENANCE_INTERVAL_MS / 1000), Math.ceil(A2A_EGRESS_RETRY_WINDOW_MS / 1000), Math.ceil(A2A_EGRESS_RETRY_WINDOW_MS / 1000), Math.ceil(A2A_EGRESS_RETRY_WINDOW_MS / 1000));
|
|
273
|
+
if (row?.due === null || row?.due === undefined)
|
|
274
|
+
return null;
|
|
275
|
+
return Math.max(Number(row.due) * 1000, Date.now() + MIN_RETRY_MS);
|
|
276
|
+
}
|
|
277
|
+
function isActorSql(db) {
|
|
278
|
+
return typeof db?.query === 'function' && typeof db.transaction === 'function';
|
|
279
|
+
}
|
|
280
|
+
/** The first string `code` along an error's cause chain (drizzle wraps driver errors). */
|
|
281
|
+
function errorCode(error) {
|
|
282
|
+
const seen = new Set();
|
|
283
|
+
for (let link = error; link !== null && typeof link === 'object' && !seen.has(link); link = link.cause) {
|
|
284
|
+
seen.add(link);
|
|
285
|
+
const code = link.code;
|
|
286
|
+
if (typeof code === 'string')
|
|
287
|
+
return code;
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
function positiveDuration(name, value, fallback, minimum) {
|
|
292
|
+
if (value === undefined)
|
|
293
|
+
return fallback;
|
|
294
|
+
if (!Number.isFinite(value) || value < minimum) {
|
|
295
|
+
throw new Error(`${name} must be a finite number of milliseconds, at least ${minimum}`);
|
|
296
|
+
}
|
|
297
|
+
return value;
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/actor/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { KeyValueStore } from '../../ports/kv.js';
|
|
2
|
+
import type { ActorSql } from './database.js';
|
|
3
|
+
/** Create the KV table. Idempotent; runs with the actor's migrations. */
|
|
4
|
+
export declare function ensureActorKvTable(sql: ActorSql): void;
|
|
5
|
+
/**
|
|
6
|
+
* Key/value store in the actor's own SQLite. Idempotency records and locks
|
|
7
|
+
* written here commit or roll back with the actor call that wrote them, and
|
|
8
|
+
* survive the actor going dormant.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ActorKeyValueStore implements KeyValueStore {
|
|
11
|
+
private readonly sql;
|
|
12
|
+
constructor(sql: ActorSql);
|
|
13
|
+
get(key: string): Promise<string | null>;
|
|
14
|
+
put(key: string, value: string, options?: {
|
|
15
|
+
expirationTtl?: number;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
delete(key: string): Promise<void>;
|
|
18
|
+
/** Drop expired entries. Runs from actor maintenance. */
|
|
19
|
+
prune(): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=kv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../../../src/adapters/actor/kv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAI9C,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAItD;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,QAAQ;IAEpC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,yDAAyD;IACzD,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const TABLE = '_actor_kv';
|
|
2
|
+
/** Create the KV table. Idempotent; runs with the actor's migrations. */
|
|
3
|
+
export function ensureActorKvTable(sql) {
|
|
4
|
+
sql.exec(`CREATE TABLE IF NOT EXISTS ${TABLE} (key TEXT PRIMARY KEY, value TEXT NOT NULL, expires_at INTEGER)`);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Key/value store in the actor's own SQLite. Idempotency records and locks
|
|
8
|
+
* written here commit or roll back with the actor call that wrote them, and
|
|
9
|
+
* survive the actor going dormant.
|
|
10
|
+
*/
|
|
11
|
+
export class ActorKeyValueStore {
|
|
12
|
+
sql;
|
|
13
|
+
constructor(sql) {
|
|
14
|
+
this.sql = sql;
|
|
15
|
+
}
|
|
16
|
+
async get(key) {
|
|
17
|
+
const [row] = this.sql.exec(`SELECT value FROM ${TABLE} WHERE key = ? AND (expires_at IS NULL OR expires_at > ?)`, key, Date.now());
|
|
18
|
+
return row?.value ?? null;
|
|
19
|
+
}
|
|
20
|
+
async put(key, value, options) {
|
|
21
|
+
const expiresAt = options?.expirationTtl ? Date.now() + options.expirationTtl * 1000 : null;
|
|
22
|
+
this.sql.exec(`INSERT INTO ${TABLE} (key, value, expires_at) VALUES (?, ?, ?)
|
|
23
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value, expires_at = excluded.expires_at`, key, value, expiresAt);
|
|
24
|
+
}
|
|
25
|
+
async delete(key) {
|
|
26
|
+
this.sql.exec(`DELETE FROM ${TABLE} WHERE key = ?`, key);
|
|
27
|
+
}
|
|
28
|
+
/** Drop expired entries. Runs from actor maintenance. */
|
|
29
|
+
prune() {
|
|
30
|
+
this.sql.exec(`DELETE FROM ${TABLE} WHERE expires_at IS NOT NULL AND expires_at <= ?`, Date.now());
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=kv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.js","sourceRoot":"","sources":["../../../src/adapters/actor/kv.ts"],"names":[],"mappings":"AAGA,MAAM,KAAK,GAAG,WAAW,CAAC;AAE1B,yEAAyE;AACzE,MAAM,UAAU,kBAAkB,CAAC,GAAa;IAC9C,GAAG,CAAC,IAAI,CACN,8BAA8B,KAAK,kEAAkE,CACtG,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IACA;IAA7B,YAA6B,GAAa;QAAb,QAAG,GAAH,GAAG,CAAU;IAAG,CAAC;IAE9C,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CACzB,qBAAqB,KAAK,2DAA2D,EACrF,GAAG,EACH,IAAI,CAAC,GAAG,EAAE,CACY,CAAC;QACzB,OAAO,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,OAAoC;QACxE,MAAM,SAAS,GAAG,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5F,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,eAAe,KAAK;+FACqE,EACzF,GAAG,EACH,KAAK,EACL,SAAS,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,KAAK,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,yDAAyD;IACzD,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,KAAK,mDAAmD,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACrG,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ActorSql } from './database.js';
|
|
2
|
+
/**
|
|
3
|
+
* Apply the engine's bundled migrations to an actor database, statement by
|
|
4
|
+
* statement, recording each file in `_engine_migrations` (the same tracking
|
|
5
|
+
* table as the Node adapter).
|
|
6
|
+
*
|
|
7
|
+
* There is no transaction to open: the writes commit with the actor call (or
|
|
8
|
+
* constructor) they run in, and roll back with it. A rolled-back first call
|
|
9
|
+
* therefore leaves the schema unapplied, so every call checks the count
|
|
10
|
+
* first, a single indexed query once the schema is current.
|
|
11
|
+
*/
|
|
12
|
+
export declare function applyActorMigrations(sql: ActorSql): {
|
|
13
|
+
applied: string[];
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../src/adapters/actor/migrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQ9C;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAezE"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Each engine migration file, split into single statements. */
|
|
2
|
+
export declare const ACTOR_MIGRATIONS: readonly (readonly [string, readonly string[]])[];
|
|
3
|
+
/** `src/db/migrations/supersessions.json`. */
|
|
4
|
+
export declare const ACTOR_MIGRATION_SUPERSESSIONS: unknown;
|
|
5
|
+
//# sourceMappingURL=migrations.generated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.generated.d.ts","sourceRoot":"","sources":["../../../src/adapters/actor/migrations.generated.ts"],"names":[],"mappings":"AAEA,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,EAi0B7E,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,6BAA6B,EAAE,OAG3C,CAAC"}
|