deepline 0.3.284 → 0.3.286
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/bundling-sources/sdk/src/client.ts +1 -2
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/activity-observation.ts +26 -2
- package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +836 -2234
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +19 -6
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -789
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +18 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +180 -14
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +3 -22
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +59 -8
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +122 -18
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +458 -130
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +60 -9
- package/dist/bundling-sources/shared_libs/play-runtime/test-async-batching.ts +4 -1
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +13 -2
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +181 -326
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +38 -151
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +8 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +10 -1
- package/dist/bundling-sources/shared_libs/plays/enrich-compat-adapter.ts +2 -0
- package/dist/cli/index.js +30579 -34364
- package/dist/cli/index.mjs +30647 -34443
- package/dist/{client-BCXQ_Ftc.d.ts → client-B7ic-kY5.d.ts} +6 -3
- package/dist/{client-B0AjIkgb.d.mts → client-Dzf_KovW.d.mts} +6 -3
- package/dist/{compiler-manifest-B1zo3igW.d.mts → compiler-manifest-9SQtUuKb.d.mts} +1 -1
- package/dist/{compiler-manifest-B1zo3igW.d.ts → compiler-manifest-9SQtUuKb.d.ts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +34 -4
- package/dist/index.mjs +34 -4
- package/dist/install-integrity.json +4 -4
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/plays/bundle-play-file.mjs +8 -1
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -606,6 +606,8 @@ export type PostgresSchedulerRunStatusSnapshot = {
|
|
|
606
606
|
runId: string;
|
|
607
607
|
/** Owning org from the scheduler runs row; '' on pre-org legacy rows. */
|
|
608
608
|
orgId: string;
|
|
609
|
+
/** Included only for callers that explicitly request admission identity. */
|
|
610
|
+
definitionScope?: 'org' | 'system';
|
|
609
611
|
status: string;
|
|
610
612
|
playName: string;
|
|
611
613
|
graphHash: string | null;
|
|
@@ -630,6 +632,7 @@ type RunStatusRow = RunRow & {
|
|
|
630
632
|
graph_hash: string | null;
|
|
631
633
|
runtime_profile: string | null;
|
|
632
634
|
launch_json: unknown;
|
|
635
|
+
definition_scope?: string | null;
|
|
633
636
|
suspension_json: unknown | null;
|
|
634
637
|
updated_at: Date | null;
|
|
635
638
|
};
|
|
@@ -5649,6 +5652,7 @@ export class PostgresSchedulerCronLaunchConflictError extends PostgresSchedulerC
|
|
|
5649
5652
|
*/
|
|
5650
5653
|
export type PostgresSchedulerCronSourcePin = {
|
|
5651
5654
|
orgId: string;
|
|
5655
|
+
definitionScope?: 'org' | 'system';
|
|
5652
5656
|
userId: string | null;
|
|
5653
5657
|
playName: string;
|
|
5654
5658
|
revisionId: string | null;
|
|
@@ -5675,6 +5679,9 @@ export function postgresSchedulerCronSourcePinFromLaunch(
|
|
|
5675
5679
|
: null;
|
|
5676
5680
|
return {
|
|
5677
5681
|
orgId: launch.orgId,
|
|
5682
|
+
...(launch.definitionScope === 'org' || launch.definitionScope === 'system'
|
|
5683
|
+
? { definitionScope: launch.definitionScope }
|
|
5684
|
+
: {}),
|
|
5678
5685
|
userId: launch.userId ?? null,
|
|
5679
5686
|
playName: launch.playName,
|
|
5680
5687
|
revisionId: launch.revisionId ?? null,
|
|
@@ -5785,7 +5792,23 @@ export async function seedPostgresSchedulerCronSchedule(
|
|
|
5785
5792
|
schedule.cron = $4::text
|
|
5786
5793
|
AND schedule.timezone IS NOT DISTINCT FROM $5::text
|
|
5787
5794
|
AND schedule.current_due_at = to_timestamp($3::double precision / 1000.0)
|
|
5788
|
-
AND
|
|
5795
|
+
AND (
|
|
5796
|
+
schedule.source_pin_json = $6::jsonb
|
|
5797
|
+
OR (
|
|
5798
|
+
schedule.source_pin_json - 'definitionScope' =
|
|
5799
|
+
$6::jsonb - 'definitionScope'
|
|
5800
|
+
AND (
|
|
5801
|
+
(
|
|
5802
|
+
NOT (schedule.source_pin_json ? 'definitionScope')
|
|
5803
|
+
AND $6::jsonb ->> 'definitionScope' = 'org'
|
|
5804
|
+
)
|
|
5805
|
+
OR (
|
|
5806
|
+
NOT ($6::jsonb ? 'definitionScope')
|
|
5807
|
+
AND schedule.source_pin_json ->> 'definitionScope' = 'org'
|
|
5808
|
+
)
|
|
5809
|
+
)
|
|
5810
|
+
)
|
|
5811
|
+
)
|
|
5789
5812
|
) AS matches_input
|
|
5790
5813
|
FROM schedule_lock
|
|
5791
5814
|
JOIN ${tableName(POSTGRES_SCHEDULER_CRON_SCHEDULES_TABLE, options)} AS schedule
|
|
@@ -7083,16 +7106,21 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7083
7106
|
SELECT
|
|
7084
7107
|
runs.run_id,
|
|
7085
7108
|
runs.started_at,
|
|
7086
|
-
max(attempts.attempt)
|
|
7109
|
+
max(attempts.attempt) FILTER (
|
|
7110
|
+
WHERE attempts.status IN ('claimed', 'running', 'waiting')
|
|
7111
|
+
) AS active_attempt
|
|
7087
7112
|
FROM locked_run AS runs
|
|
7088
7113
|
LEFT JOIN ${tableName('attempts', options)} AS attempts
|
|
7089
7114
|
ON attempts.run_id = runs.run_id
|
|
7090
|
-
AND attempts.status IN ('claimed', 'running', 'waiting')
|
|
7091
7115
|
WHERE runs.run_id = $1
|
|
7092
7116
|
AND runs.status IN ('queued', 'running', 'waiting')
|
|
7093
7117
|
GROUP BY runs.run_id, runs.started_at
|
|
7094
|
-
HAVING max(attempts.attempt)
|
|
7095
|
-
|
|
7118
|
+
HAVING max(attempts.attempt) FILTER (
|
|
7119
|
+
WHERE attempts.status IN ('claimed', 'running', 'waiting')
|
|
7120
|
+
) IS NULL
|
|
7121
|
+
OR max(attempts.attempt) FILTER (
|
|
7122
|
+
WHERE attempts.status IN ('claimed', 'running', 'waiting')
|
|
7123
|
+
) < $2
|
|
7096
7124
|
),
|
|
7097
7125
|
assigned AS (
|
|
7098
7126
|
INSERT INTO ${tableName('attempts', options)} (
|
|
@@ -7124,6 +7152,45 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7124
7152
|
AND attempt < $2
|
|
7125
7153
|
AND status IN ('claimed', 'running', 'waiting')
|
|
7126
7154
|
),
|
|
7155
|
+
-- A run can only have one live, unbound Daytona create in flight. Reuse
|
|
7156
|
+
-- its durable provider identity across attempt retries and move its
|
|
7157
|
+
-- fence to the new owner; the provider idempotency key makes replay safe.
|
|
7158
|
+
adopted_daytona_operations AS (
|
|
7159
|
+
UPDATE ${tableName('runtime_sandbox_operations', options)} AS operation
|
|
7160
|
+
SET attempt = $2,
|
|
7161
|
+
updated_at = clock_timestamp()
|
|
7162
|
+
FROM target_run
|
|
7163
|
+
JOIN assigned USING (run_id)
|
|
7164
|
+
WHERE operation.run_id = target_run.run_id
|
|
7165
|
+
AND operation.attempt < $2
|
|
7166
|
+
AND operation.provider = 'daytona'
|
|
7167
|
+
AND operation.state = 'reserved'
|
|
7168
|
+
AND EXISTS (
|
|
7169
|
+
SELECT 1
|
|
7170
|
+
FROM ${tableName('runtime_sandbox_capacity_leases', options)} AS lease
|
|
7171
|
+
WHERE lease.lease_id = operation.operation_key
|
|
7172
|
+
AND lease.released_at IS NULL
|
|
7173
|
+
AND lease.sandbox_id IS NULL
|
|
7174
|
+
AND lease.expires_at > clock_timestamp()
|
|
7175
|
+
)
|
|
7176
|
+
AND 1 = (
|
|
7177
|
+
SELECT count(*)
|
|
7178
|
+
FROM ${tableName('runtime_sandbox_operations', options)} AS pending
|
|
7179
|
+
WHERE pending.run_id = target_run.run_id
|
|
7180
|
+
AND pending.attempt < $2
|
|
7181
|
+
AND pending.provider = 'daytona'
|
|
7182
|
+
AND pending.state = 'reserved'
|
|
7183
|
+
AND EXISTS (
|
|
7184
|
+
SELECT 1
|
|
7185
|
+
FROM ${tableName('runtime_sandbox_capacity_leases', options)} AS pending_lease
|
|
7186
|
+
WHERE pending_lease.lease_id = pending.operation_key
|
|
7187
|
+
AND pending_lease.released_at IS NULL
|
|
7188
|
+
AND pending_lease.sandbox_id IS NULL
|
|
7189
|
+
AND pending_lease.expires_at > clock_timestamp()
|
|
7190
|
+
)
|
|
7191
|
+
)
|
|
7192
|
+
RETURNING operation.operation_key
|
|
7193
|
+
),
|
|
7127
7194
|
first_start AS (
|
|
7128
7195
|
SELECT assigned.run_id
|
|
7129
7196
|
FROM assigned
|
|
@@ -7333,7 +7400,7 @@ export async function markPostgresSchedulerAttemptWaiting(
|
|
|
7333
7400
|
);
|
|
7334
7401
|
const waiting = await client.query<{ run_id: string; event_id: string }>(
|
|
7335
7402
|
`
|
|
7336
|
-
WITH waiting_attempt AS (
|
|
7403
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, waiting_attempt AS (
|
|
7337
7404
|
UPDATE ${tableName('attempts', options)}
|
|
7338
7405
|
SET status = 'waiting',
|
|
7339
7406
|
resource_json = CASE
|
|
@@ -7369,6 +7436,7 @@ export async function markPostgresSchedulerAttemptWaiting(
|
|
|
7369
7436
|
END,
|
|
7370
7437
|
heartbeat_at = CASE WHEN $8::boolean THEN heartbeat_at ELSE now() END,
|
|
7371
7438
|
updated_at = now()
|
|
7439
|
+
FROM (SELECT count(*) FROM custody_attempts) AS attempt_locks
|
|
7372
7440
|
WHERE run_id = $1
|
|
7373
7441
|
AND attempt = $2
|
|
7374
7442
|
AND status = 'running'
|
|
@@ -8097,13 +8165,14 @@ export async function deferPostgresSchedulerAttemptForCapacity(
|
|
|
8097
8165
|
): Promise<boolean> {
|
|
8098
8166
|
const deferred = await client.query<{ run_id: string }>(
|
|
8099
8167
|
`
|
|
8100
|
-
WITH deferred_attempt AS (
|
|
8168
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, deferred_attempt AS (
|
|
8101
8169
|
UPDATE ${tableName('attempts', options)}
|
|
8102
8170
|
SET status = 'stale',
|
|
8103
8171
|
lease_expires_at = NULL,
|
|
8104
8172
|
heartbeat_at = now(),
|
|
8105
8173
|
error_json = $4::jsonb,
|
|
8106
8174
|
updated_at = now()
|
|
8175
|
+
FROM (SELECT count(*) FROM custody_attempts) AS attempt_locks
|
|
8107
8176
|
WHERE run_id = $1
|
|
8108
8177
|
AND attempt = $2
|
|
8109
8178
|
AND status IN ('claimed', 'running', 'waiting')
|
|
@@ -8165,9 +8234,9 @@ export async function deferPostgresSchedulerAttemptForExecutorTokenOutage(
|
|
|
8165
8234
|
deferred: boolean;
|
|
8166
8235
|
}>(
|
|
8167
8236
|
`
|
|
8168
|
-
WITH current_attempt AS (
|
|
8237
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, current_attempt AS (
|
|
8169
8238
|
SELECT created_at
|
|
8170
|
-
FROM
|
|
8239
|
+
FROM custody_attempts
|
|
8171
8240
|
WHERE run_id = $1
|
|
8172
8241
|
AND attempt = $2
|
|
8173
8242
|
AND lease_token = $3
|
|
@@ -8200,6 +8269,7 @@ export async function deferPostgresSchedulerAttemptForExecutorTokenOutage(
|
|
|
8200
8269
|
heartbeat_at = now(),
|
|
8201
8270
|
error_json = $4::jsonb,
|
|
8202
8271
|
updated_at = now()
|
|
8272
|
+
FROM (SELECT count(*) FROM custody_attempts) AS attempt_locks
|
|
8203
8273
|
WHERE run_id = $1
|
|
8204
8274
|
AND attempt = $2
|
|
8205
8275
|
AND status IN ('claimed', 'running')
|
|
@@ -8259,10 +8329,10 @@ export async function claimPostgresSchedulerWaitingDetachedAttemptForTerminal(
|
|
|
8259
8329
|
): Promise<boolean> {
|
|
8260
8330
|
const claimed = await client.query<{ run_id: string }>(
|
|
8261
8331
|
`
|
|
8262
|
-
WITH candidate AS MATERIALIZED (
|
|
8332
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, candidate AS MATERIALIZED (
|
|
8263
8333
|
SELECT runs.run_id, attempts.attempt
|
|
8264
|
-
FROM
|
|
8265
|
-
JOIN
|
|
8334
|
+
FROM custody_runs AS runs
|
|
8335
|
+
JOIN custody_attempts AS attempts
|
|
8266
8336
|
ON attempts.run_id = runs.run_id
|
|
8267
8337
|
AND attempts.attempt = (runs.suspension_json ->> 'runnerAttempt')::integer
|
|
8268
8338
|
WHERE runs.run_id = $1
|
|
@@ -8282,7 +8352,6 @@ export async function claimPostgresSchedulerWaitingDetachedAttemptForTerminal(
|
|
|
8282
8352
|
AND newer.attempt > attempts.attempt
|
|
8283
8353
|
AND newer.status IN ('claimed', 'running', 'waiting', 'completed', 'failed')
|
|
8284
8354
|
)
|
|
8285
|
-
FOR UPDATE OF runs, attempts
|
|
8286
8355
|
),
|
|
8287
8356
|
running_attempt AS (
|
|
8288
8357
|
UPDATE ${tableName('attempts', options)} AS target
|
|
@@ -8521,19 +8590,18 @@ export async function deferPostgresSchedulerAttemptForRecovery(
|
|
|
8521
8590
|
deadline_at_ms: string | null;
|
|
8522
8591
|
}>(
|
|
8523
8592
|
`
|
|
8524
|
-
WITH candidate AS (
|
|
8593
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, candidate AS (
|
|
8525
8594
|
SELECT runs.run_id,
|
|
8526
8595
|
runs.recovery_json,
|
|
8527
8596
|
attempts.run_id AS attempt_run_id
|
|
8528
|
-
FROM
|
|
8529
|
-
JOIN
|
|
8597
|
+
FROM custody_runs AS runs
|
|
8598
|
+
JOIN custody_attempts AS attempts
|
|
8530
8599
|
ON attempts.run_id = runs.run_id
|
|
8531
8600
|
WHERE attempts.run_id = $1
|
|
8532
8601
|
AND attempts.attempt = $2
|
|
8533
8602
|
AND attempts.lease_token = $3
|
|
8534
8603
|
AND attempts.status IN ('claimed', 'running', 'waiting')
|
|
8535
8604
|
AND runs.status IN ('queued', 'running', 'waiting')
|
|
8536
|
-
FOR UPDATE OF runs, attempts
|
|
8537
8605
|
), computed AS (
|
|
8538
8606
|
SELECT run_id,
|
|
8539
8607
|
coalesce((recovery_json ->> 'deferCount')::integer, 0) + 1
|
|
@@ -9255,20 +9323,24 @@ export async function recordPostgresSchedulerManagedSandboxOperationLive(
|
|
|
9255
9323
|
'production';
|
|
9256
9324
|
const recorded = await client.query<{ operation_key: string }>(
|
|
9257
9325
|
`
|
|
9258
|
-
WITH eligible_attempt AS (
|
|
9326
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, eligible_attempt AS (
|
|
9259
9327
|
SELECT run_id
|
|
9260
|
-
FROM
|
|
9328
|
+
FROM custody_attempts
|
|
9261
9329
|
WHERE run_id = $1
|
|
9262
9330
|
AND attempt = $2
|
|
9263
9331
|
AND lease_token = $3
|
|
9264
9332
|
AND status IN ('claimed', 'running', 'waiting')
|
|
9333
|
+
AND EXISTS (SELECT 1 FROM custody_runs WHERE status IN ('queued', 'running', 'waiting'))
|
|
9334
|
+
AND NOT EXISTS (SELECT 1 FROM custody_attempts AS newer WHERE newer.attempt > $2)
|
|
9265
9335
|
), eligible_lease AS MATERIALIZED (
|
|
9266
9336
|
SELECT lease_id
|
|
9267
|
-
FROM
|
|
9337
|
+
FROM custody_leases
|
|
9338
|
+
CROSS JOIN (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
9268
9339
|
WHERE lease_id = $5
|
|
9340
|
+
AND run_id = $1 AND provider = $10
|
|
9341
|
+
AND (sandbox_id IS NULL OR (sandbox_id = $6 AND routing_domain IS NOT DISTINCT FROM $7))
|
|
9269
9342
|
AND released_at IS NULL
|
|
9270
9343
|
AND expires_at > clock_timestamp()
|
|
9271
|
-
FOR UPDATE
|
|
9272
9344
|
), live_operation AS (
|
|
9273
9345
|
UPDATE ${tableName('runtime_sandbox_operations', options)} AS operation
|
|
9274
9346
|
SET sandbox_id = $6,
|
|
@@ -9311,7 +9383,6 @@ export async function recordPostgresSchedulerManagedSandboxOperationLive(
|
|
|
9311
9383
|
JOIN recorded_attempt ON TRUE
|
|
9312
9384
|
WHERE lease.lease_id = live_operation.operation_key
|
|
9313
9385
|
AND lease.released_at IS NULL
|
|
9314
|
-
AND lease.expires_at > clock_timestamp()
|
|
9315
9386
|
RETURNING lease.lease_id
|
|
9316
9387
|
)
|
|
9317
9388
|
SELECT live_operation.operation_key
|
|
@@ -9346,42 +9417,52 @@ export async function recordPostgresSchedulerManagedSandboxOperationLive(
|
|
|
9346
9417
|
return false;
|
|
9347
9418
|
}
|
|
9348
9419
|
const updated = await client.query<{ run_id: string }>(
|
|
9349
|
-
`
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9420
|
+
`WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, eligible_retirement AS MATERIALIZED (
|
|
9421
|
+
SELECT operation.operation_key, operation.run_id, operation.attempt
|
|
9422
|
+
FROM custody_operations AS operation
|
|
9423
|
+
JOIN custody_attempts AS attempt ON attempt.run_id = operation.run_id AND attempt.attempt = operation.attempt
|
|
9424
|
+
JOIN custody_leases AS lease ON lease.lease_id = operation.operation_key
|
|
9425
|
+
WHERE attempt.run_id = $1 AND attempt.attempt = $2 AND attempt.lease_token = $3
|
|
9426
|
+
AND attempt.status IN ('claimed', 'running', 'waiting')
|
|
9427
|
+
AND NOT EXISTS (SELECT 1 FROM custody_attempts AS newer WHERE newer.attempt > $2)
|
|
9428
|
+
AND EXISTS (SELECT 1 FROM custody_runs WHERE status IN ('queued', 'running', 'waiting'))
|
|
9429
|
+
AND operation.operation_key = $5 AND operation.sandbox_id = $6
|
|
9430
|
+
AND operation.provider = $7 AND operation.state IN ($8, 'deleting')
|
|
9431
|
+
AND operation.environment = $9 AND operation.routing_domain IS NOT DISTINCT FROM $10
|
|
9432
|
+
AND lease.sandbox_id = $6 AND lease.released_at IS NULL
|
|
9433
|
+
AND EXISTS (
|
|
9434
|
+
SELECT 1 FROM jsonb_array_elements(attempt.resource_json) AS fact
|
|
9435
|
+
WHERE fact->>'sandboxCapacityLeaseId' = $5 AND fact->>'sandboxId' = $6
|
|
9436
|
+
AND fact->>'kind' = $4::jsonb->>'kind'
|
|
9437
|
+
)
|
|
9438
|
+
), retiring_operation AS (
|
|
9439
|
+
UPDATE ${tableName('runtime_sandbox_operations', options)} AS operation
|
|
9440
|
+
SET state = 'deleting', updated_at = clock_timestamp()
|
|
9441
|
+
FROM eligible_retirement
|
|
9442
|
+
WHERE operation.operation_key = eligible_retirement.operation_key
|
|
9443
|
+
RETURNING operation.operation_key
|
|
9444
|
+
), closed_resource AS (
|
|
9445
|
+
UPDATE ${tableName('attempts', options)} AS attempt
|
|
9446
|
+
SET resource_json = (
|
|
9447
|
+
SELECT jsonb_agg(
|
|
9448
|
+
CASE
|
|
9449
|
+
WHEN resource->>'sandboxCapacityLeaseId' = $5 AND resource->>'sandboxId' = $6
|
|
9450
|
+
AND resource->>'kind' = $4::jsonb->>'kind'
|
|
9451
|
+
AND (resource->'billingEndedAt' IS NULL OR resource->'billingEndedAt' = 'null'::jsonb)
|
|
9452
|
+
THEN resource || jsonb_build_object('billingEndedAt', $4::jsonb->'billingEndedAt')
|
|
9453
|
+
ELSE resource END ORDER BY ordinal
|
|
9454
|
+
) FROM jsonb_array_elements(attempt.resource_json) WITH ORDINALITY AS resources(resource, ordinal)
|
|
9455
|
+
), updated_at = clock_timestamp()
|
|
9456
|
+
FROM retiring_operation
|
|
9457
|
+
WHERE attempt.run_id = $1 AND attempt.attempt = $2 AND attempt.lease_token = $3
|
|
9458
|
+
RETURNING attempt.run_id
|
|
9459
|
+
), queued AS (
|
|
9460
|
+
INSERT INTO ${tableName('sandbox_cleanup_jobs_v2', options)} (
|
|
9461
|
+
provider, sandbox_id, run_id, attempt, environment, routing_domain
|
|
9462
|
+
) SELECT $7, $6, $1, $2, $9, $10 FROM closed_resource
|
|
9463
|
+
ON CONFLICT (provider, sandbox_id, routing_domain_key) DO NOTHING
|
|
9464
|
+
)
|
|
9465
|
+
SELECT run_id FROM closed_resource`,
|
|
9385
9466
|
[
|
|
9386
9467
|
input.runId,
|
|
9387
9468
|
input.attempt,
|
|
@@ -9425,14 +9506,17 @@ export async function readPostgresSchedulerManagedSandboxOperationAlreadyLive(
|
|
|
9425
9506
|
operationKey: string;
|
|
9426
9507
|
provider: RuntimeSandboxProvider;
|
|
9427
9508
|
sandboxId: string;
|
|
9509
|
+
environment?: 'preview' | 'production';
|
|
9510
|
+
routingDomain?: string | null;
|
|
9428
9511
|
},
|
|
9429
9512
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
9430
9513
|
): Promise<boolean> {
|
|
9431
9514
|
const found = await client.query<{ operation_key: string }>(
|
|
9432
9515
|
`
|
|
9516
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}
|
|
9433
9517
|
SELECT operation.operation_key
|
|
9434
|
-
FROM
|
|
9435
|
-
JOIN
|
|
9518
|
+
FROM custody_operations AS operation
|
|
9519
|
+
JOIN custody_attempts AS attempt
|
|
9436
9520
|
ON attempt.run_id = operation.run_id
|
|
9437
9521
|
AND attempt.attempt = operation.attempt
|
|
9438
9522
|
WHERE operation.operation_key = $4
|
|
@@ -9441,8 +9525,12 @@ export async function readPostgresSchedulerManagedSandboxOperationAlreadyLive(
|
|
|
9441
9525
|
AND operation.provider = $5
|
|
9442
9526
|
AND operation.state = $6
|
|
9443
9527
|
AND operation.sandbox_id = $7
|
|
9528
|
+
AND ($8::text IS NULL OR operation.environment = $8)
|
|
9529
|
+
AND (NOT $9::boolean OR operation.routing_domain IS NOT DISTINCT FROM $10::text)
|
|
9444
9530
|
AND attempt.lease_token = $3
|
|
9445
9531
|
AND attempt.status IN ('claimed', 'running', 'waiting')
|
|
9532
|
+
AND NOT EXISTS (SELECT 1 FROM custody_attempts AS newer WHERE newer.attempt > $2)
|
|
9533
|
+
AND EXISTS (SELECT 1 FROM custody_runs WHERE status IN ('queued', 'running', 'waiting'))
|
|
9446
9534
|
`,
|
|
9447
9535
|
[
|
|
9448
9536
|
input.runId,
|
|
@@ -9452,6 +9540,9 @@ export async function readPostgresSchedulerManagedSandboxOperationAlreadyLive(
|
|
|
9452
9540
|
input.provider,
|
|
9453
9541
|
RuntimeSandboxOperationState.Live,
|
|
9454
9542
|
input.sandboxId,
|
|
9543
|
+
input.environment ?? null,
|
|
9544
|
+
input.routingDomain !== undefined,
|
|
9545
|
+
input.routingDomain?.trim() || null,
|
|
9455
9546
|
],
|
|
9456
9547
|
);
|
|
9457
9548
|
return found.rows.length === 1;
|
|
@@ -9604,9 +9695,10 @@ export async function resolvePostgresSchedulerAmbiguousModalCreateIntentFromProv
|
|
|
9604
9695
|
): Promise<boolean> {
|
|
9605
9696
|
const resolved = await client.query<{ run_id: string }>(
|
|
9606
9697
|
`
|
|
9607
|
-
WITH resolved AS (
|
|
9698
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, resolved AS (
|
|
9608
9699
|
UPDATE ${tableName('ambiguous_modal_creates', options)}
|
|
9609
9700
|
SET status = 'resolved', resolved_at = clock_timestamp()
|
|
9701
|
+
FROM (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
9610
9702
|
WHERE run_id = $1
|
|
9611
9703
|
AND attempt = $2
|
|
9612
9704
|
AND modal_app_id = $3
|
|
@@ -9659,9 +9751,10 @@ export async function recordPostgresSchedulerReconciledModalResourcesForCleanup(
|
|
|
9659
9751
|
const payload = stringifyPostgresJson(resources);
|
|
9660
9752
|
const recorded = await client.query<{ run_id: string }>(
|
|
9661
9753
|
`
|
|
9662
|
-
WITH claimed_intent AS (
|
|
9754
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, claimed_intent AS (
|
|
9663
9755
|
UPDATE ${tableName('ambiguous_modal_creates', options)}
|
|
9664
9756
|
SET status = 'resolved', resolved_at = clock_timestamp()
|
|
9757
|
+
FROM (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
9665
9758
|
WHERE run_id = $1
|
|
9666
9759
|
AND attempt = $2
|
|
9667
9760
|
AND modal_app_id = $3
|
|
@@ -9884,16 +9977,16 @@ export async function recordPostgresSchedulerLateManagedSandboxOperationForClean
|
|
|
9884
9977
|
'production';
|
|
9885
9978
|
const result = await client.query<{ operation_key: string }>(
|
|
9886
9979
|
`
|
|
9887
|
-
WITH eligible_lease AS MATERIALIZED (
|
|
9980
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, eligible_lease AS MATERIALIZED (
|
|
9888
9981
|
SELECT lease_id
|
|
9889
|
-
FROM
|
|
9982
|
+
FROM custody_leases
|
|
9983
|
+
CROSS JOIN (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
9890
9984
|
WHERE lease_id = $4
|
|
9891
9985
|
AND released_at IS NULL
|
|
9892
9986
|
AND expires_at > clock_timestamp()
|
|
9893
|
-
FOR UPDATE
|
|
9894
9987
|
), eligible_attempt AS (
|
|
9895
9988
|
SELECT run_id
|
|
9896
|
-
FROM
|
|
9989
|
+
FROM custody_attempts
|
|
9897
9990
|
WHERE run_id = $1
|
|
9898
9991
|
AND attempt = $2
|
|
9899
9992
|
AND lease_token = $3
|
|
@@ -10096,7 +10189,11 @@ export async function markPostgresSchedulerRuntimeResourceDetached(
|
|
|
10096
10189
|
|
|
10097
10190
|
export async function readPostgresSchedulerRuntimeResourcesForRun(
|
|
10098
10191
|
client: PostgresSchedulerQueryClient,
|
|
10099
|
-
input: {
|
|
10192
|
+
input: {
|
|
10193
|
+
runId: string;
|
|
10194
|
+
attempt?: number | null;
|
|
10195
|
+
throughAttempt?: number;
|
|
10196
|
+
},
|
|
10100
10197
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
10101
10198
|
): Promise<unknown[]> {
|
|
10102
10199
|
const resources = await client.query<{ resource_json: unknown }>(
|
|
@@ -10105,10 +10202,11 @@ export async function readPostgresSchedulerRuntimeResourcesForRun(
|
|
|
10105
10202
|
FROM ${tableName('attempts', options)}
|
|
10106
10203
|
WHERE run_id = $1
|
|
10107
10204
|
AND ($2::integer IS NULL OR attempt = $2)
|
|
10205
|
+
AND ($3::integer IS NULL OR attempt <= $3)
|
|
10108
10206
|
AND resource_json IS NOT NULL
|
|
10109
10207
|
ORDER BY attempt DESC
|
|
10110
10208
|
`,
|
|
10111
|
-
[input.runId, input.attempt ?? null],
|
|
10209
|
+
[input.runId, input.attempt ?? null, input.throughAttempt ?? null],
|
|
10112
10210
|
);
|
|
10113
10211
|
return resources.rows.flatMap((row) =>
|
|
10114
10212
|
Array.isArray(row.resource_json) ? row.resource_json : [row.resource_json],
|
|
@@ -10137,17 +10235,20 @@ export async function settlePostgresSchedulerRuntimeResources(
|
|
|
10137
10235
|
| 'runtime_limit'
|
|
10138
10236
|
| 'cancelled'
|
|
10139
10237
|
| 'lease_expired';
|
|
10238
|
+
throughAttempt?: number;
|
|
10140
10239
|
},
|
|
10141
10240
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
10142
10241
|
): Promise<number> {
|
|
10143
10242
|
const stamped = await client.query<{ run_id: string }>(
|
|
10144
10243
|
`
|
|
10244
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}
|
|
10145
10245
|
UPDATE ${tableName('attempts', options)}
|
|
10146
10246
|
SET resource_json = (
|
|
10147
10247
|
SELECT COALESCE(
|
|
10148
10248
|
jsonb_agg(
|
|
10149
10249
|
CASE
|
|
10150
10250
|
WHEN elem->>'kind' IN ('daytona_sandbox', 'modal_sandbox')
|
|
10251
|
+
AND NOT ${protectedManagedSandboxSql({ runId: '$1', provider: "(CASE elem->>'kind' WHEN 'modal_sandbox' THEN 'modal' ELSE 'daytona' END)", sandboxId: "elem->>'sandboxId'", routingDomain: "(CASE elem->>'kind' WHEN 'modal_sandbox' THEN NULLIF(elem->>'modalAppId', '') ELSE NULLIF(elem->>'daytonaOrganizationId', '') END)" }, options, true)}
|
|
10151
10252
|
AND (
|
|
10152
10253
|
elem->'billingEndedAt' IS NULL
|
|
10153
10254
|
OR elem->'billingEndedAt' = 'null'::jsonb
|
|
@@ -10168,7 +10269,9 @@ export async function settlePostgresSchedulerRuntimeResources(
|
|
|
10168
10269
|
FROM jsonb_array_elements(resource_json) AS elem
|
|
10169
10270
|
),
|
|
10170
10271
|
updated_at = now()
|
|
10272
|
+
FROM (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
10171
10273
|
WHERE run_id = $1
|
|
10274
|
+
AND ($4::integer IS NULL OR attempt <= $4)
|
|
10172
10275
|
AND resource_json IS NOT NULL
|
|
10173
10276
|
AND jsonb_typeof(resource_json) = 'array'
|
|
10174
10277
|
AND EXISTS (
|
|
@@ -10182,7 +10285,12 @@ export async function settlePostgresSchedulerRuntimeResources(
|
|
|
10182
10285
|
)
|
|
10183
10286
|
RETURNING run_id
|
|
10184
10287
|
`,
|
|
10185
|
-
[
|
|
10288
|
+
[
|
|
10289
|
+
input.runId,
|
|
10290
|
+
input.billingEndedAt,
|
|
10291
|
+
input.terminalReason,
|
|
10292
|
+
input.throughAttempt ?? null,
|
|
10293
|
+
],
|
|
10186
10294
|
);
|
|
10187
10295
|
return stamped.rows.length;
|
|
10188
10296
|
}
|
|
@@ -11460,6 +11568,79 @@ export async function completePostgresSchedulerComputeBillingSessionBootstrap(
|
|
|
11460
11568
|
return completed.rows.length > 0;
|
|
11461
11569
|
}
|
|
11462
11570
|
|
|
11571
|
+
function runtimeSandboxCustodyLocksSql(
|
|
11572
|
+
runPredicate: string,
|
|
11573
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
11574
|
+
skipLocked = false,
|
|
11575
|
+
): string {
|
|
11576
|
+
return `custody_runs AS MATERIALIZED (
|
|
11577
|
+
SELECT run.* FROM ${tableName('runs', options)} AS run
|
|
11578
|
+
WHERE ${runPredicate}
|
|
11579
|
+
ORDER BY run.run_id FOR NO KEY UPDATE ${skipLocked ? 'SKIP LOCKED' : ''}
|
|
11580
|
+
), custody_attempts AS MATERIALIZED (
|
|
11581
|
+
SELECT attempt.* FROM ${tableName('attempts', options)} AS attempt
|
|
11582
|
+
WHERE attempt.run_id IN (SELECT run_id FROM custody_runs)
|
|
11583
|
+
ORDER BY attempt.run_id, attempt.attempt FOR UPDATE
|
|
11584
|
+
), custody_leases AS MATERIALIZED (
|
|
11585
|
+
SELECT lease.* FROM ${tableName('runtime_sandbox_capacity_leases', options)} AS lease
|
|
11586
|
+
CROSS JOIN (SELECT count(*) FROM custody_attempts) AS attempt_locks
|
|
11587
|
+
WHERE lease.run_id IN (SELECT run_id FROM custody_runs)
|
|
11588
|
+
ORDER BY lease.run_id, lease.lease_id FOR UPDATE OF lease
|
|
11589
|
+
), custody_operations AS MATERIALIZED (
|
|
11590
|
+
SELECT operation.* FROM ${tableName('runtime_sandbox_operations', options)} AS operation
|
|
11591
|
+
CROSS JOIN (SELECT count(*) FROM custody_leases) AS lease_locks
|
|
11592
|
+
WHERE operation.run_id IN (SELECT run_id FROM custody_runs)
|
|
11593
|
+
ORDER BY operation.run_id, operation.operation_key FOR UPDATE OF operation
|
|
11594
|
+
)`;
|
|
11595
|
+
}
|
|
11596
|
+
|
|
11597
|
+
function protectedManagedSandboxSql(
|
|
11598
|
+
identity: {
|
|
11599
|
+
runId: string;
|
|
11600
|
+
provider: string;
|
|
11601
|
+
sandboxId: string;
|
|
11602
|
+
routingDomain: string;
|
|
11603
|
+
},
|
|
11604
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
11605
|
+
locked = false,
|
|
11606
|
+
): string {
|
|
11607
|
+
const runs = locked ? 'custody_runs' : tableName('runs', options);
|
|
11608
|
+
const attempts = locked ? 'custody_attempts' : tableName('attempts', options);
|
|
11609
|
+
const operations = locked
|
|
11610
|
+
? 'custody_operations'
|
|
11611
|
+
: tableName('runtime_sandbox_operations', options);
|
|
11612
|
+
const leases = locked
|
|
11613
|
+
? 'custody_leases'
|
|
11614
|
+
: tableName('runtime_sandbox_capacity_leases', options);
|
|
11615
|
+
return `EXISTS (
|
|
11616
|
+
SELECT 1 FROM ${runs} AS managed_run
|
|
11617
|
+
JOIN ${operations} AS managed_operation ON managed_operation.run_id = managed_run.run_id
|
|
11618
|
+
JOIN ${leases} AS managed_lease ON managed_lease.lease_id = managed_operation.operation_key
|
|
11619
|
+
WHERE managed_run.run_id = ${identity.runId}
|
|
11620
|
+
AND managed_run.status IN ('queued', 'running', 'waiting')
|
|
11621
|
+
AND managed_operation.provider = ${identity.provider}
|
|
11622
|
+
AND COALESCE(managed_operation.sandbox_id, managed_lease.sandbox_id) = ${identity.sandboxId}
|
|
11623
|
+
AND COALESCE(managed_operation.routing_domain, managed_lease.routing_domain)
|
|
11624
|
+
IS NOT DISTINCT FROM ${identity.routingDomain}
|
|
11625
|
+
AND managed_lease.released_at IS NULL
|
|
11626
|
+
AND NOT EXISTS (SELECT 1 FROM ${tableName('control', options)} AS cancel
|
|
11627
|
+
WHERE cancel.key = 'runtime_cancel:' || managed_run.run_id)
|
|
11628
|
+
AND (
|
|
11629
|
+
(managed_operation.state = 'reserved' AND managed_lease.expires_at > clock_timestamp())
|
|
11630
|
+
OR (managed_operation.state = 'live' AND EXISTS (
|
|
11631
|
+
SELECT 1 FROM ${attempts} AS owner_attempt
|
|
11632
|
+
WHERE owner_attempt.run_id = managed_run.run_id
|
|
11633
|
+
AND owner_attempt.attempt = managed_operation.attempt
|
|
11634
|
+
AND owner_attempt.status IN ('claimed', 'running', 'waiting')
|
|
11635
|
+
AND owner_attempt.runner_result_json IS NULL
|
|
11636
|
+
AND NOT EXISTS (SELECT 1 FROM ${attempts} AS newer
|
|
11637
|
+
WHERE newer.run_id = owner_attempt.run_id AND newer.attempt > owner_attempt.attempt)
|
|
11638
|
+
AND (owner_attempt.lease_expires_at IS NULL OR owner_attempt.lease_expires_at > clock_timestamp())
|
|
11639
|
+
))
|
|
11640
|
+
)
|
|
11641
|
+
)`;
|
|
11642
|
+
}
|
|
11643
|
+
|
|
11463
11644
|
/** Deletion needs terminal/cancellation/retired-resource authority. An old
|
|
11464
11645
|
* worker error (including a billing end) is not evidence the runner stopped. */
|
|
11465
11646
|
function protectedDetachedSandboxSql(
|
|
@@ -11470,10 +11651,11 @@ function protectedDetachedSandboxSql(
|
|
|
11470
11651
|
routingDomain: string;
|
|
11471
11652
|
},
|
|
11472
11653
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
11654
|
+
locked = false,
|
|
11473
11655
|
): string {
|
|
11474
|
-
return `EXISTS (
|
|
11475
|
-
SELECT 1 FROM ${tableName('runs', options)} AS detached_run
|
|
11476
|
-
JOIN ${tableName('attempts', options)} AS detached_attempt
|
|
11656
|
+
return `(${protectedManagedSandboxSql(identity, options, locked)} OR EXISTS (
|
|
11657
|
+
SELECT 1 FROM ${locked ? 'custody_runs' : tableName('runs', options)} AS detached_run
|
|
11658
|
+
JOIN ${locked ? 'custody_attempts' : tableName('attempts', options)} AS detached_attempt
|
|
11477
11659
|
ON detached_attempt.run_id = detached_run.run_id
|
|
11478
11660
|
CROSS JOIN LATERAL jsonb_array_elements(
|
|
11479
11661
|
CASE WHEN jsonb_typeof(detached_attempt.resource_json) = 'array'
|
|
@@ -11501,18 +11683,19 @@ function protectedDetachedSandboxSql(
|
|
|
11501
11683
|
AND detached_resource -> 'executionDetachedAt' IS NOT NULL
|
|
11502
11684
|
AND detached_resource -> 'executionDetachedAt' <> 'null'::jsonb)
|
|
11503
11685
|
)
|
|
11504
|
-
AND NOT EXISTS (SELECT 1 FROM ${tableName('attempts', options)} AS newer
|
|
11686
|
+
AND NOT EXISTS (SELECT 1 FROM ${locked ? 'custody_attempts' : tableName('attempts', options)} AS newer
|
|
11505
11687
|
WHERE newer.run_id = detached_run.run_id
|
|
11506
11688
|
AND newer.attempt > detached_attempt.attempt
|
|
11507
11689
|
AND newer.status IN ('claimed', 'running', 'waiting', 'completed', 'failed'))
|
|
11508
11690
|
AND NOT EXISTS (SELECT 1 FROM ${tableName('control', options)} AS cancel
|
|
11509
11691
|
WHERE cancel.key = 'runtime_cancel:' || detached_run.run_id)
|
|
11510
|
-
)`;
|
|
11692
|
+
))`;
|
|
11511
11693
|
}
|
|
11512
11694
|
|
|
11513
11695
|
function protectedDetachedResourceSql(
|
|
11514
11696
|
runId: string,
|
|
11515
11697
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
11698
|
+
locked = false,
|
|
11516
11699
|
): string {
|
|
11517
11700
|
return protectedDetachedSandboxSql(
|
|
11518
11701
|
{
|
|
@@ -11524,6 +11707,7 @@ function protectedDetachedResourceSql(
|
|
|
11524
11707
|
"(CASE resource->>'kind' WHEN 'modal_sandbox' THEN NULLIF(resource->>'modalAppId', '') ELSE NULLIF(resource->>'daytonaOrganizationId', '') END)",
|
|
11525
11708
|
},
|
|
11526
11709
|
options,
|
|
11710
|
+
locked,
|
|
11527
11711
|
);
|
|
11528
11712
|
}
|
|
11529
11713
|
|
|
@@ -11553,9 +11737,10 @@ export async function enqueuePostgresSchedulerSandboxCleanupForAttempt(
|
|
|
11553
11737
|
): Promise<number> {
|
|
11554
11738
|
const enqueued = await client.query<{ sandbox_id: string }>(
|
|
11555
11739
|
`
|
|
11556
|
-
WITH attempt_resources AS (
|
|
11740
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, attempt_resources AS (
|
|
11557
11741
|
SELECT run_id, attempt, resource_json
|
|
11558
|
-
FROM
|
|
11742
|
+
FROM custody_attempts
|
|
11743
|
+
CROSS JOIN (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
11559
11744
|
WHERE run_id = $1
|
|
11560
11745
|
AND attempt = $2
|
|
11561
11746
|
AND resource_json IS NOT NULL
|
|
@@ -11590,7 +11775,7 @@ export async function enqueuePostgresSchedulerSandboxCleanupForAttempt(
|
|
|
11590
11775
|
) AS resource
|
|
11591
11776
|
WHERE resource->>'kind' IN ('daytona_sandbox', 'modal_sandbox')
|
|
11592
11777
|
AND NULLIF(resource->>'sandboxId', '') IS NOT NULL
|
|
11593
|
-
AND NOT ${protectedDetachedResourceSql('$1', options)}
|
|
11778
|
+
AND NOT ${protectedDetachedResourceSql('$1', options, true)}
|
|
11594
11779
|
ON CONFLICT (provider, sandbox_id, routing_domain_key) DO NOTHING
|
|
11595
11780
|
RETURNING sandbox_id
|
|
11596
11781
|
)
|
|
@@ -11605,11 +11790,12 @@ export async function enqueuePostgresSchedulerSandboxCleanupForAttempt(
|
|
|
11605
11790
|
* admits the current runner before cancellation terminalizes. */
|
|
11606
11791
|
export async function enqueuePostgresSchedulerSandboxCleanupForRun(
|
|
11607
11792
|
client: PostgresSchedulerQueryClient,
|
|
11608
|
-
input: { runId: string },
|
|
11793
|
+
input: { runId: string; throughAttempt?: number },
|
|
11609
11794
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
11610
11795
|
): Promise<void> {
|
|
11611
11796
|
await client.query(
|
|
11612
11797
|
`
|
|
11798
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}
|
|
11613
11799
|
INSERT INTO ${tableName('sandbox_cleanup_jobs_v2', options)} (
|
|
11614
11800
|
provider, sandbox_id, run_id, attempt, environment, routing_domain
|
|
11615
11801
|
)
|
|
@@ -11630,7 +11816,8 @@ export async function enqueuePostgresSchedulerSandboxCleanupForRun(
|
|
|
11630
11816
|
WHEN 'modal_sandbox' THEN NULLIF(resource->>'modalAppId', '')
|
|
11631
11817
|
ELSE NULLIF(resource->>'daytonaOrganizationId', '')
|
|
11632
11818
|
END
|
|
11633
|
-
FROM
|
|
11819
|
+
FROM custody_attempts AS attempt
|
|
11820
|
+
CROSS JOIN (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
11634
11821
|
CROSS JOIN LATERAL jsonb_array_elements(
|
|
11635
11822
|
CASE
|
|
11636
11823
|
WHEN jsonb_typeof(attempt.resource_json) = 'array'
|
|
@@ -11639,21 +11826,23 @@ export async function enqueuePostgresSchedulerSandboxCleanupForRun(
|
|
|
11639
11826
|
END
|
|
11640
11827
|
) AS resource
|
|
11641
11828
|
WHERE attempt.run_id = $1
|
|
11829
|
+
AND ($2::integer IS NULL OR attempt.attempt <= $2)
|
|
11642
11830
|
AND attempt.resource_json IS NOT NULL
|
|
11643
11831
|
AND resource->>'kind' IN ('daytona_sandbox', 'modal_sandbox')
|
|
11644
11832
|
AND NULLIF(resource->>'sandboxId', '') IS NOT NULL
|
|
11645
|
-
AND NOT ${protectedDetachedResourceSql('$1', options)}
|
|
11833
|
+
AND NOT ${protectedDetachedResourceSql('$1', options, true)}
|
|
11646
11834
|
UNION ALL
|
|
11647
11835
|
SELECT operation.provider, operation.sandbox_id, operation.run_id,
|
|
11648
11836
|
operation.attempt, operation.environment, operation.routing_domain
|
|
11649
|
-
FROM
|
|
11837
|
+
FROM custody_operations AS operation
|
|
11650
11838
|
WHERE operation.run_id = $1
|
|
11839
|
+
AND ($2::integer IS NULL OR operation.attempt <= $2)
|
|
11651
11840
|
AND operation.state IN ('live', 'deleting')
|
|
11652
11841
|
AND operation.sandbox_id IS NOT NULL
|
|
11653
|
-
AND NOT ${protectedDetachedSandboxSql({ runId: 'operation.run_id', provider: 'operation.provider', sandboxId: 'operation.sandbox_id', routingDomain: 'operation.routing_domain' }, options)}
|
|
11842
|
+
AND NOT ${protectedDetachedSandboxSql({ runId: 'operation.run_id', provider: 'operation.provider', sandboxId: 'operation.sandbox_id', routingDomain: 'operation.routing_domain' }, options, true)}
|
|
11654
11843
|
ON CONFLICT (provider, sandbox_id, routing_domain_key) DO NOTHING
|
|
11655
11844
|
`,
|
|
11656
|
-
[input.runId],
|
|
11845
|
+
[input.runId, input.throughAttempt ?? null],
|
|
11657
11846
|
);
|
|
11658
11847
|
}
|
|
11659
11848
|
|
|
@@ -11665,9 +11854,10 @@ export async function abandonUnstartedModalCancellationReservations(
|
|
|
11665
11854
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
11666
11855
|
): Promise<void> {
|
|
11667
11856
|
await client.query(
|
|
11668
|
-
`WITH abandoned AS (
|
|
11857
|
+
`WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, abandoned AS (
|
|
11669
11858
|
UPDATE ${tableName('runtime_sandbox_operations', options)} AS operation
|
|
11670
11859
|
SET state = 'abandoned', updated_at = clock_timestamp()
|
|
11860
|
+
FROM (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
11671
11861
|
WHERE operation.run_id = $1
|
|
11672
11862
|
AND operation.provider = 'modal'
|
|
11673
11863
|
AND operation.state = 'reserved'
|
|
@@ -11734,6 +11924,7 @@ export async function claimPostgresSchedulerSandboxCleanupJobs(
|
|
|
11734
11924
|
input: {
|
|
11735
11925
|
leaseOwner: string;
|
|
11736
11926
|
runId?: string;
|
|
11927
|
+
throughAttempt?: number;
|
|
11737
11928
|
limit?: number;
|
|
11738
11929
|
leaseSeconds?: number;
|
|
11739
11930
|
environment?: string | null;
|
|
@@ -11808,7 +11999,21 @@ export async function claimPostgresSchedulerSandboxCleanupJobs(
|
|
|
11808
11999
|
diagnostic_json: unknown | null;
|
|
11809
12000
|
}>(
|
|
11810
12001
|
`
|
|
11811
|
-
WITH
|
|
12002
|
+
WITH candidate_jobs AS MATERIALIZED (
|
|
12003
|
+
SELECT cleanup.provider, cleanup.sandbox_id, cleanup.routing_domain_key, cleanup.run_id
|
|
12004
|
+
FROM ${tableName('sandbox_cleanup_jobs_v2', options)} AS cleanup
|
|
12005
|
+
WHERE cleanup.status <> 'deleted' AND cleanup.blocked_at IS NULL
|
|
12006
|
+
AND (cleanup.available_at <= now() OR cleanup.diagnostic_json IS NOT NULL)
|
|
12007
|
+
AND (cleanup.lease_expires_at IS NULL OR cleanup.lease_expires_at <= now())
|
|
12008
|
+
AND ($4::text IS NULL OR cleanup.environment = $4)
|
|
12009
|
+
AND ($5::text[] IS NULL OR cleanup.provider = ANY($5::text[]))
|
|
12010
|
+
AND ($8::text IS NULL OR cleanup.run_id = $8)
|
|
12011
|
+
AND ($9::integer IS NULL OR cleanup.attempt <= $9)
|
|
12012
|
+
AND NOT ${protectedDetachedSandboxSql({ runId: 'cleanup.run_id', provider: 'cleanup.provider', sandboxId: 'cleanup.sandbox_id', routingDomain: 'cleanup.routing_domain' }, options)}
|
|
12013
|
+
ORDER BY CASE WHEN cleanup.diagnostic_json IS NOT NULL THEN 0 ELSE 1 END,
|
|
12014
|
+
cleanup.available_at, cleanup.created_at, cleanup.provider, cleanup.sandbox_id, cleanup.routing_domain_key
|
|
12015
|
+
LIMIT $2
|
|
12016
|
+
), ${runtimeSandboxCustodyLocksSql('EXISTS (SELECT 1 FROM candidate_jobs WHERE candidate_jobs.run_id = run.run_id)', options, true)}, candidates AS (
|
|
11812
12017
|
SELECT
|
|
11813
12018
|
cleanup.provider,
|
|
11814
12019
|
cleanup.sandbox_id,
|
|
@@ -11816,9 +12021,14 @@ export async function claimPostgresSchedulerSandboxCleanupJobs(
|
|
|
11816
12021
|
cleanup.routing_domain_key,
|
|
11817
12022
|
run.status AS terminal_status
|
|
11818
12023
|
FROM ${tableName('sandbox_cleanup_jobs_v2', options)} AS cleanup
|
|
11819
|
-
JOIN
|
|
12024
|
+
JOIN custody_runs AS run
|
|
11820
12025
|
ON run.run_id = cleanup.run_id
|
|
11821
|
-
|
|
12026
|
+
CROSS JOIN (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
12027
|
+
WHERE EXISTS (SELECT 1 FROM candidate_jobs AS selected
|
|
12028
|
+
WHERE selected.provider = cleanup.provider
|
|
12029
|
+
AND selected.sandbox_id = cleanup.sandbox_id
|
|
12030
|
+
AND selected.routing_domain_key = cleanup.routing_domain_key)
|
|
12031
|
+
AND cleanup.status <> 'deleted'
|
|
11822
12032
|
AND cleanup.blocked_at IS NULL
|
|
11823
12033
|
AND (
|
|
11824
12034
|
cleanup.available_at <= now()
|
|
@@ -11828,7 +12038,8 @@ export async function claimPostgresSchedulerSandboxCleanupJobs(
|
|
|
11828
12038
|
AND ($4::text IS NULL OR cleanup.environment = $4)
|
|
11829
12039
|
AND ($5::text[] IS NULL OR cleanup.provider = ANY($5::text[]))
|
|
11830
12040
|
AND ($8::text IS NULL OR cleanup.run_id = $8)
|
|
11831
|
-
AND
|
|
12041
|
+
AND ($9::integer IS NULL OR cleanup.attempt <= $9)
|
|
12042
|
+
AND NOT ${protectedDetachedSandboxSql({ runId: 'cleanup.run_id', provider: 'cleanup.provider', sandboxId: 'cleanup.sandbox_id', routingDomain: 'cleanup.routing_domain' }, options, true)}
|
|
11832
12043
|
ORDER BY
|
|
11833
12044
|
CASE WHEN cleanup.diagnostic_json IS NOT NULL THEN 0 ELSE 1 END ASC,
|
|
11834
12045
|
cleanup.available_at ASC,
|
|
@@ -11865,12 +12076,28 @@ export async function claimPostgresSchedulerSandboxCleanupJobs(
|
|
|
11865
12076
|
operation_claimed AS (
|
|
11866
12077
|
UPDATE ${tableName('runtime_sandbox_operations', options)} AS operation
|
|
11867
12078
|
SET state = $6,
|
|
12079
|
+
sandbox_id = claimed.sandbox_id,
|
|
12080
|
+
routing_domain = claimed.routing_domain,
|
|
12081
|
+
provider_created_at = COALESCE(operation.provider_created_at, clock_timestamp()),
|
|
11868
12082
|
updated_at = clock_timestamp()
|
|
11869
12083
|
FROM claimed
|
|
11870
|
-
WHERE operation.
|
|
11871
|
-
AND operation.
|
|
11872
|
-
AND
|
|
11873
|
-
|
|
12084
|
+
WHERE operation.run_id = claimed.run_id
|
|
12085
|
+
AND operation.provider = claimed.provider
|
|
12086
|
+
AND (
|
|
12087
|
+
(operation.state = $7
|
|
12088
|
+
AND operation.sandbox_id = claimed.sandbox_id
|
|
12089
|
+
AND operation.routing_domain IS NOT DISTINCT FROM claimed.routing_domain)
|
|
12090
|
+
OR (operation.state = 'reserved'
|
|
12091
|
+
AND operation.sandbox_id IS NULL
|
|
12092
|
+
AND EXISTS (
|
|
12093
|
+
SELECT 1 FROM custody_leases AS lease
|
|
12094
|
+
WHERE lease.lease_id = operation.operation_key
|
|
12095
|
+
AND lease.run_id = claimed.run_id
|
|
12096
|
+
AND lease.provider = claimed.provider
|
|
12097
|
+
AND lease.sandbox_id = claimed.sandbox_id
|
|
12098
|
+
AND lease.routing_domain IS NOT DISTINCT FROM claimed.routing_domain
|
|
12099
|
+
))
|
|
12100
|
+
)
|
|
11874
12101
|
RETURNING operation.operation_key
|
|
11875
12102
|
),
|
|
11876
12103
|
claim_events AS (
|
|
@@ -11914,6 +12141,7 @@ export async function claimPostgresSchedulerSandboxCleanupJobs(
|
|
|
11914
12141
|
RuntimeSandboxOperationState.Deleting,
|
|
11915
12142
|
RuntimeSandboxOperationState.Live,
|
|
11916
12143
|
input.runId ?? null,
|
|
12144
|
+
input.throughAttempt ?? null,
|
|
11917
12145
|
],
|
|
11918
12146
|
);
|
|
11919
12147
|
return claimed.rows.map((row) => ({
|
|
@@ -12081,12 +12309,14 @@ export async function completePostgresSchedulerSandboxCleanupJob(
|
|
|
12081
12309
|
> {
|
|
12082
12310
|
const completed = await client.query<{ outcome: string }>(
|
|
12083
12311
|
`
|
|
12084
|
-
WITH current_job AS MATERIALIZED (
|
|
12312
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $3', options)}, current_job AS MATERIALIZED (
|
|
12085
12313
|
SELECT status, attempt_count, lease_owner, routing_domain
|
|
12086
|
-
FROM ${tableName('sandbox_cleanup_jobs_v2', options)}
|
|
12314
|
+
FROM ${tableName('sandbox_cleanup_jobs_v2', options)} AS sandbox_cleanup_jobs_v2
|
|
12315
|
+
CROSS JOIN (SELECT count(*) FROM custody_operations) AS operation_locks
|
|
12087
12316
|
WHERE provider = $8
|
|
12088
12317
|
AND sandbox_id = $1
|
|
12089
12318
|
AND routing_domain IS NOT DISTINCT FROM $9
|
|
12319
|
+
FOR UPDATE OF sandbox_cleanup_jobs_v2
|
|
12090
12320
|
),
|
|
12091
12321
|
completed AS (
|
|
12092
12322
|
UPDATE ${tableName('sandbox_cleanup_jobs_v2', options)} AS target
|
|
@@ -12162,7 +12392,8 @@ export async function completePostgresSchedulerSandboxCleanupJob(
|
|
|
12162
12392
|
SET resource_json = (
|
|
12163
12393
|
SELECT jsonb_agg(
|
|
12164
12394
|
CASE
|
|
12165
|
-
WHEN resource->>'kind' = 'modal_sandbox'
|
|
12395
|
+
WHEN resource->>'kind' = CASE $8::text WHEN 'modal' THEN 'modal_sandbox' ELSE 'daytona_sandbox' END
|
|
12396
|
+
AND (CASE $8::text WHEN 'modal' THEN NULLIF(resource->>'modalAppId', '') ELSE NULLIF(resource->>'daytonaOrganizationId', '') END) IS NOT DISTINCT FROM $9::text
|
|
12166
12397
|
AND resource->>'sandboxId' = $1
|
|
12167
12398
|
AND resource->>'lateAcquired' = 'true'
|
|
12168
12399
|
AND (
|
|
@@ -12203,7 +12434,8 @@ export async function completePostgresSchedulerSandboxCleanupJob(
|
|
|
12203
12434
|
ELSE jsonb_build_array(attempt.resource_json)
|
|
12204
12435
|
END
|
|
12205
12436
|
) AS candidate
|
|
12206
|
-
WHERE candidate->>'kind' = 'modal_sandbox'
|
|
12437
|
+
WHERE candidate->>'kind' = CASE $8::text WHEN 'modal' THEN 'modal_sandbox' ELSE 'daytona_sandbox' END
|
|
12438
|
+
AND (CASE $8::text WHEN 'modal' THEN NULLIF(candidate->>'modalAppId', '') ELSE NULLIF(candidate->>'daytonaOrganizationId', '') END) IS NOT DISTINCT FROM $9::text
|
|
12207
12439
|
AND candidate->>'sandboxId' = $1
|
|
12208
12440
|
AND candidate->>'lateAcquired' = 'true'
|
|
12209
12441
|
)
|
|
@@ -12930,7 +13162,7 @@ export async function completePostgresSchedulerAttempt(
|
|
|
12930
13162
|
);
|
|
12931
13163
|
const completed = await client.query<{ run_id: string }>(
|
|
12932
13164
|
`
|
|
12933
|
-
WITH completed AS (
|
|
13165
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, completed AS (
|
|
12934
13166
|
UPDATE ${tableName('attempts', options)}
|
|
12935
13167
|
SET status = 'completed',
|
|
12936
13168
|
terminalization_mode = 'compatibility_wake',
|
|
@@ -12967,6 +13199,7 @@ export async function completePostgresSchedulerAttempt(
|
|
|
12967
13199
|
)
|
|
12968
13200
|
END,
|
|
12969
13201
|
updated_at = now()
|
|
13202
|
+
FROM (SELECT count(*) FROM custody_attempts) AS attempt_locks
|
|
12970
13203
|
WHERE run_id = $1
|
|
12971
13204
|
AND attempt = $2
|
|
12972
13205
|
AND status = 'running'
|
|
@@ -13207,7 +13440,7 @@ export async function failPostgresSchedulerAttempt(
|
|
|
13207
13440
|
);
|
|
13208
13441
|
const failed = await client.query<{ run_id: string }>(
|
|
13209
13442
|
`
|
|
13210
|
-
WITH failed AS (
|
|
13443
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, failed AS (
|
|
13211
13444
|
UPDATE ${tableName('attempts', options)}
|
|
13212
13445
|
SET status = 'failed',
|
|
13213
13446
|
lease_expires_at = NULL,
|
|
@@ -13254,6 +13487,7 @@ export async function failPostgresSchedulerAttempt(
|
|
|
13254
13487
|
)
|
|
13255
13488
|
END,
|
|
13256
13489
|
updated_at = now()
|
|
13490
|
+
FROM (SELECT count(*) FROM custody_attempts) AS attempt_locks
|
|
13257
13491
|
WHERE run_id = $1
|
|
13258
13492
|
AND attempt = $2
|
|
13259
13493
|
AND status = 'running'
|
|
@@ -13541,7 +13775,7 @@ export async function cancelPostgresSchedulerRun(
|
|
|
13541
13775
|
launch_json: PlaySchedulerSubmitInput;
|
|
13542
13776
|
}>(
|
|
13543
13777
|
`
|
|
13544
|
-
WITH cancelled_run AS (
|
|
13778
|
+
WITH ${runtimeSandboxCustodyLocksSql('run.run_id = $1', options)}, cancelled_run AS (
|
|
13545
13779
|
UPDATE ${tableName('runs', options)} AS target
|
|
13546
13780
|
SET status = 'cancelled',
|
|
13547
13781
|
terminal_result_json = NULL,
|
|
@@ -13550,6 +13784,7 @@ export async function cancelPostgresSchedulerRun(
|
|
|
13550
13784
|
wait_deadline = NULL,
|
|
13551
13785
|
finished_at = now(),
|
|
13552
13786
|
updated_at = now()
|
|
13787
|
+
FROM (SELECT count(*) FROM custody_attempts) AS attempt_locks
|
|
13553
13788
|
WHERE target.run_id = $1
|
|
13554
13789
|
AND target.status IN ('queued', 'running', 'waiting')
|
|
13555
13790
|
${strandedEligibility}
|
|
@@ -16914,8 +17149,12 @@ export async function readPostgresSchedulerRunStatus(
|
|
|
16914
17149
|
runId: string,
|
|
16915
17150
|
options?: Pick<PostgresSchedulerOptions, 'schema'> & {
|
|
16916
17151
|
includeDetails?: boolean;
|
|
17152
|
+
includeAdmissionScope?: boolean;
|
|
16917
17153
|
},
|
|
16918
17154
|
): Promise<PostgresSchedulerRunStatusSnapshot | null> {
|
|
17155
|
+
const admissionScopeSelection = options?.includeAdmissionScope
|
|
17156
|
+
? ", launch_json ->> 'definitionScope' AS definition_scope"
|
|
17157
|
+
: '';
|
|
16919
17158
|
if (options?.includeDetails === false) {
|
|
16920
17159
|
// An admission projection gap needs lifecycle truth only. Launch, result,
|
|
16921
17160
|
// suspension and error JSON may contain row/call-sized detail: never even
|
|
@@ -16933,11 +17172,12 @@ export async function readPostgresSchedulerRunStatus(
|
|
|
16933
17172
|
| 'updated_at'
|
|
16934
17173
|
| 'started_at'
|
|
16935
17174
|
| 'finished_at'
|
|
17175
|
+
| 'definition_scope'
|
|
16936
17176
|
>
|
|
16937
17177
|
>(
|
|
16938
17178
|
`
|
|
16939
17179
|
SELECT run_id, org_id, status, play_name, graph_hash, runtime_profile,
|
|
16940
|
-
created_at, updated_at, started_at, finished_at
|
|
17180
|
+
created_at, updated_at, started_at, finished_at${admissionScopeSelection}
|
|
16941
17181
|
FROM ${tableName('runs', options)}
|
|
16942
17182
|
WHERE run_id = $1
|
|
16943
17183
|
`,
|
|
@@ -16948,6 +17188,10 @@ export async function readPostgresSchedulerRunStatus(
|
|
|
16948
17188
|
return {
|
|
16949
17189
|
runId: row.run_id,
|
|
16950
17190
|
orgId: row.org_id ?? '',
|
|
17191
|
+
...(options.includeAdmissionScope &&
|
|
17192
|
+
(row.definition_scope === 'org' || row.definition_scope === 'system')
|
|
17193
|
+
? { definitionScope: row.definition_scope }
|
|
17194
|
+
: {}),
|
|
16951
17195
|
status: row.status,
|
|
16952
17196
|
playName: row.play_name,
|
|
16953
17197
|
graphHash: row.graph_hash,
|
|
@@ -16973,7 +17217,7 @@ export async function readPostgresSchedulerRunStatus(
|
|
|
16973
17217
|
`
|
|
16974
17218
|
SELECT run_id, org_id, status, play_name, graph_hash, runtime_profile,
|
|
16975
17219
|
launch_json, suspension_json, terminal_result_json, terminal_error_json,
|
|
16976
|
-
runtime_timing_json, created_at, updated_at, started_at, finished_at
|
|
17220
|
+
runtime_timing_json, created_at, updated_at, started_at, finished_at${admissionScopeSelection}
|
|
16977
17221
|
FROM ${tableName('runs', options)}
|
|
16978
17222
|
WHERE run_id = $1
|
|
16979
17223
|
`,
|
|
@@ -16990,6 +17234,10 @@ export async function readPostgresSchedulerRunStatus(
|
|
|
16990
17234
|
return {
|
|
16991
17235
|
runId: row.run_id,
|
|
16992
17236
|
orgId: row.org_id ?? '',
|
|
17237
|
+
...(options?.includeAdmissionScope &&
|
|
17238
|
+
(row.definition_scope === 'org' || row.definition_scope === 'system')
|
|
17239
|
+
? { definitionScope: row.definition_scope }
|
|
17240
|
+
: {}),
|
|
16993
17241
|
status: row.status,
|
|
16994
17242
|
playName: row.play_name,
|
|
16995
17243
|
graphHash: row.graph_hash,
|
|
@@ -18810,9 +19058,14 @@ type RunLedgerOutboxDrainScope = {
|
|
|
18810
19058
|
leaseOwner: string;
|
|
18811
19059
|
targetEventId: string;
|
|
18812
19060
|
nextClaimed: PostgresSchedulerOutboxEvent[];
|
|
19061
|
+
};
|
|
19062
|
+
|
|
19063
|
+
type RunLedgerOutboxAuthorityScope = {
|
|
18813
19064
|
authority: {
|
|
19065
|
+
runId: string;
|
|
19066
|
+
leaseOwner: string;
|
|
18814
19067
|
runtimeApi: WorkerRuntimeApiContext;
|
|
18815
|
-
expiresAtMs: number;
|
|
19068
|
+
expiresAtMs: number | null;
|
|
18816
19069
|
} | null;
|
|
18817
19070
|
};
|
|
18818
19071
|
|
|
@@ -18826,6 +19079,7 @@ async function dispatchRunLedgerOutboxThroughEventWithScope(
|
|
|
18826
19079
|
},
|
|
18827
19080
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
18828
19081
|
scope?: RunLedgerOutboxDrainScope,
|
|
19082
|
+
authorityScope: RunLedgerOutboxAuthorityScope = { authority: null },
|
|
18829
19083
|
): Promise<PostgresSchedulerOutboxDrainResult> {
|
|
18830
19084
|
const runId = input.runId?.trim();
|
|
18831
19085
|
if (!runId) {
|
|
@@ -18841,6 +19095,11 @@ async function dispatchRunLedgerOutboxThroughEventWithScope(
|
|
|
18841
19095
|
input.maxEvents === undefined
|
|
18842
19096
|
? null
|
|
18843
19097
|
: Math.max(1, Math.min(32, input.maxEvents));
|
|
19098
|
+
const leaseOwner =
|
|
19099
|
+
input.leaseOwner?.trim() ||
|
|
19100
|
+
scope?.leaseOwner ||
|
|
19101
|
+
`run-ledger-outbox-dispatch:${randomUUID()}`;
|
|
19102
|
+
const scopedInput = { ...input, leaseOwner };
|
|
18844
19103
|
const batchSize = RUN_LEDGER_PROJECTION_PREFIX_MAX_FACTS;
|
|
18845
19104
|
const eventIds: string[] = [];
|
|
18846
19105
|
const failedEventIds: string[] = [];
|
|
@@ -18855,13 +19114,14 @@ async function dispatchRunLedgerOutboxThroughEventWithScope(
|
|
|
18855
19114
|
const result = await dispatchRunLedgerOutboxBatchWithScope(
|
|
18856
19115
|
withClient,
|
|
18857
19116
|
{
|
|
18858
|
-
...
|
|
19117
|
+
...scopedInput,
|
|
18859
19118
|
waitForRunLock: true,
|
|
18860
19119
|
continueThroughTerminal: false,
|
|
18861
19120
|
limit: remaining === null ? batchSize : Math.min(batchSize, remaining),
|
|
18862
19121
|
},
|
|
18863
19122
|
options,
|
|
18864
19123
|
scope,
|
|
19124
|
+
authorityScope,
|
|
18865
19125
|
);
|
|
18866
19126
|
attempted += result.attempted;
|
|
18867
19127
|
projected += result.projected;
|
|
@@ -18940,7 +19200,13 @@ export async function dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope(
|
|
|
18940
19200
|
input: RunLedgerOutboxDispatchInput & { waitForRunLock?: boolean },
|
|
18941
19201
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
18942
19202
|
): Promise<PostgresSchedulerOutboxProjectionResult> {
|
|
18943
|
-
return dispatchRunLedgerOutboxBatchWithScope(
|
|
19203
|
+
return dispatchRunLedgerOutboxBatchWithScope(
|
|
19204
|
+
withClient,
|
|
19205
|
+
input,
|
|
19206
|
+
options,
|
|
19207
|
+
undefined,
|
|
19208
|
+
{ authority: null },
|
|
19209
|
+
);
|
|
18944
19210
|
}
|
|
18945
19211
|
|
|
18946
19212
|
async function dispatchRunLedgerOutboxBatchWithScope(
|
|
@@ -18950,6 +19216,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
18950
19216
|
input: RunLedgerOutboxDispatchInput & { waitForRunLock?: boolean },
|
|
18951
19217
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
18952
19218
|
scope?: RunLedgerOutboxDrainScope,
|
|
19219
|
+
authorityScope: RunLedgerOutboxAuthorityScope = { authority: null },
|
|
18953
19220
|
): Promise<PostgresSchedulerOutboxProjectionResult> {
|
|
18954
19221
|
const dispatchStartedAtMs = Date.now();
|
|
18955
19222
|
const leaseOwner =
|
|
@@ -19126,23 +19393,45 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
19126
19393
|
) {
|
|
19127
19394
|
throw new Error('Run-ledger continuation is outside its dispatch scope.');
|
|
19128
19395
|
}
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19396
|
+
// Minted executor authority is reused only inside this finite run/owner
|
|
19397
|
+
// drain and only while it can cover the HTTP request plus its SQL renewal.
|
|
19398
|
+
const reuseMarginMs =
|
|
19399
|
+
Math.max(
|
|
19400
|
+
1,
|
|
19401
|
+
Math.floor(
|
|
19402
|
+
input.runtimeApi?.requestTimeoutMs ??
|
|
19403
|
+
RUNTIME_CAPACITY_POLICY.receiptGateway.requestTimeoutMs,
|
|
19404
|
+
),
|
|
19405
|
+
) + RUNTIME_RELIABILITY_POLICY.schedulerDatabase.queryTimeoutMs;
|
|
19406
|
+
const cachedAuthority = authorityScope.authority;
|
|
19132
19407
|
const gatewayRuntimeApi =
|
|
19133
19408
|
tokenAuthority === 'gateway'
|
|
19134
|
-
?
|
|
19135
|
-
|
|
19136
|
-
|
|
19137
|
-
|
|
19138
|
-
|
|
19139
|
-
|
|
19140
|
-
|
|
19141
|
-
|
|
19142
|
-
|
|
19143
|
-
|
|
19144
|
-
|
|
19409
|
+
? cachedAuthority?.runId === first.runId &&
|
|
19410
|
+
cachedAuthority.leaseOwner === leaseOwner &&
|
|
19411
|
+
cachedAuthority.expiresAtMs !== null &&
|
|
19412
|
+
cachedAuthority.expiresAtMs > Date.now() + reuseMarginMs
|
|
19413
|
+
? cachedAuthority.runtimeApi
|
|
19414
|
+
: await loadPostgresSchedulerRuntimeApiForRun(
|
|
19415
|
+
withClient,
|
|
19416
|
+
first.runId,
|
|
19417
|
+
first.leaseOwner
|
|
19418
|
+
? { eventId: first.eventId, leaseOwner: first.leaseOwner }
|
|
19419
|
+
: null,
|
|
19420
|
+
tokenAuthority,
|
|
19421
|
+
options,
|
|
19422
|
+
input.runtimeApi?.signal,
|
|
19423
|
+
)
|
|
19145
19424
|
: null;
|
|
19425
|
+
if (
|
|
19426
|
+
gatewayRuntimeApi &&
|
|
19427
|
+
cachedAuthority?.runId === first.runId &&
|
|
19428
|
+
cachedAuthority.leaseOwner === leaseOwner &&
|
|
19429
|
+
cachedAuthority.runtimeApi.baseUrl !== gatewayRuntimeApi.baseUrl
|
|
19430
|
+
) {
|
|
19431
|
+
throw new Error(
|
|
19432
|
+
'Run Ledger dispatch origin changed within an immutable launch.',
|
|
19433
|
+
);
|
|
19434
|
+
}
|
|
19146
19435
|
const resolvedRuntimeApi =
|
|
19147
19436
|
gatewayRuntimeApi ??
|
|
19148
19437
|
input.runtimeApi ??
|
|
@@ -19186,12 +19475,48 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
19186
19475
|
const tokenExpiresAtMs = runtimeApiTokenExpiresAtMs(
|
|
19187
19476
|
runtimeApi.executorToken,
|
|
19188
19477
|
);
|
|
19189
|
-
if (
|
|
19190
|
-
|
|
19478
|
+
if (tokenAuthority === 'gateway' && gatewayRuntimeApi) {
|
|
19479
|
+
authorityScope.authority = {
|
|
19480
|
+
runId: first.runId,
|
|
19481
|
+
leaseOwner,
|
|
19482
|
+
runtimeApi,
|
|
19483
|
+
expiresAtMs: tokenExpiresAtMs,
|
|
19484
|
+
};
|
|
19191
19485
|
}
|
|
19192
19486
|
authorityReadyAtMs = Date.now();
|
|
19193
|
-
const renewDelivery = () =>
|
|
19194
|
-
|
|
19487
|
+
const renewDelivery = async () => {
|
|
19488
|
+
const currentAuthority = authorityScope.authority;
|
|
19489
|
+
if (
|
|
19490
|
+
tokenAuthority === 'gateway' &&
|
|
19491
|
+
currentAuthority?.runId === first.runId &&
|
|
19492
|
+
currentAuthority.leaseOwner === leaseOwner &&
|
|
19493
|
+
currentAuthority.expiresAtMs !== null &&
|
|
19494
|
+
currentAuthority.expiresAtMs <= Date.now() + reuseMarginMs
|
|
19495
|
+
) {
|
|
19496
|
+
const refreshed = await loadPostgresSchedulerRuntimeApiForRun(
|
|
19497
|
+
withClient,
|
|
19498
|
+
first.runId,
|
|
19499
|
+
{ eventId: first.eventId, leaseOwner },
|
|
19500
|
+
tokenAuthority,
|
|
19501
|
+
options,
|
|
19502
|
+
runtimeApi.signal,
|
|
19503
|
+
);
|
|
19504
|
+
if (refreshed.baseUrl !== runtimeApi.baseUrl) {
|
|
19505
|
+
throw new Error(
|
|
19506
|
+
'Run Ledger dispatch origin changed within an immutable launch.',
|
|
19507
|
+
);
|
|
19508
|
+
}
|
|
19509
|
+
runtimeApi.executorToken = refreshed.executorToken;
|
|
19510
|
+
runtimeApi.vercelProtectionBypassToken =
|
|
19511
|
+
refreshed.vercelProtectionBypassToken;
|
|
19512
|
+
authorityScope.authority = {
|
|
19513
|
+
runId: first.runId,
|
|
19514
|
+
leaseOwner,
|
|
19515
|
+
runtimeApi,
|
|
19516
|
+
expiresAtMs: runtimeApiTokenExpiresAtMs(refreshed.executorToken),
|
|
19517
|
+
};
|
|
19518
|
+
}
|
|
19519
|
+
await withClient((client) =>
|
|
19195
19520
|
renewPostgresRunLedgerDelivery(
|
|
19196
19521
|
client,
|
|
19197
19522
|
{
|
|
@@ -19202,6 +19527,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
19202
19527
|
options,
|
|
19203
19528
|
),
|
|
19204
19529
|
);
|
|
19530
|
+
};
|
|
19205
19531
|
// A pending start is always claimed alone because later events require its
|
|
19206
19532
|
// snapshot. It cannot share the append endpoint, so retain that mutation
|
|
19207
19533
|
// as its own exact delivery.
|
|
@@ -19299,6 +19625,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
19299
19625
|
withClient,
|
|
19300
19626
|
{ input, delivered, scope: acknowledgement.continuation },
|
|
19301
19627
|
options,
|
|
19628
|
+
authorityScope,
|
|
19302
19629
|
);
|
|
19303
19630
|
} catch (error) {
|
|
19304
19631
|
await releasePendingContinuation();
|
|
@@ -19404,6 +19731,7 @@ async function continueRunLedgerOutboxThroughTerminal(
|
|
|
19404
19731
|
scope: RunLedgerOutboxDrainScope;
|
|
19405
19732
|
},
|
|
19406
19733
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
19734
|
+
authorityScope: RunLedgerOutboxAuthorityScope = { authority: null },
|
|
19407
19735
|
): Promise<PostgresSchedulerOutboxProjectionResult> {
|
|
19408
19736
|
const drained = await dispatchRunLedgerOutboxThroughEventWithScope(
|
|
19409
19737
|
withClient,
|
|
@@ -19415,6 +19743,7 @@ async function continueRunLedgerOutboxThroughTerminal(
|
|
|
19415
19743
|
},
|
|
19416
19744
|
options,
|
|
19417
19745
|
input.scope,
|
|
19746
|
+
authorityScope,
|
|
19418
19747
|
);
|
|
19419
19748
|
return {
|
|
19420
19749
|
attempted: input.delivered.attempted + drained.attempted,
|
|
@@ -19430,7 +19759,10 @@ async function continueRunLedgerOutboxThroughTerminal(
|
|
|
19430
19759
|
function runtimeApiTokenExpiresAtMs(token: string): number | null {
|
|
19431
19760
|
try {
|
|
19432
19761
|
const expiresAt = decodeJwt(token).exp;
|
|
19433
|
-
return typeof expiresAt === 'number' &&
|
|
19762
|
+
return typeof expiresAt === 'number' &&
|
|
19763
|
+
Number.isSafeInteger(expiresAt) &&
|
|
19764
|
+
expiresAt > 0 &&
|
|
19765
|
+
Number.isSafeInteger(expiresAt * 1_000)
|
|
19434
19766
|
? expiresAt * 1_000
|
|
19435
19767
|
: null;
|
|
19436
19768
|
} catch {
|
|
@@ -19514,18 +19846,11 @@ async function acknowledgeRunLedgerPrefixWithContinuation(
|
|
|
19514
19846
|
options,
|
|
19515
19847
|
);
|
|
19516
19848
|
if (nextClaimed.length > 0) {
|
|
19517
|
-
const expiresAtMs = runtimeApiTokenExpiresAtMs(
|
|
19518
|
-
input.runtimeApi.executorToken,
|
|
19519
|
-
);
|
|
19520
19849
|
continuation = input.scope ?? {
|
|
19521
19850
|
runId,
|
|
19522
19851
|
leaseOwner: input.leaseOwner,
|
|
19523
19852
|
targetEventId,
|
|
19524
19853
|
nextClaimed: [],
|
|
19525
|
-
authority:
|
|
19526
|
-
input.input.tokenAuthority === 'gateway' && expiresAtMs !== null
|
|
19527
|
-
? { runtimeApi: input.runtimeApi, expiresAtMs }
|
|
19528
|
-
: null,
|
|
19529
19854
|
};
|
|
19530
19855
|
continuation.nextClaimed = nextClaimed;
|
|
19531
19856
|
input.continuation.current = continuation;
|
|
@@ -20127,6 +20452,9 @@ function parsePostgresSchedulerCronSourcePin(
|
|
|
20127
20452
|
return {
|
|
20128
20453
|
...pin,
|
|
20129
20454
|
orgId: pin.orgId,
|
|
20455
|
+
...(pin.definitionScope === 'org' || pin.definitionScope === 'system'
|
|
20456
|
+
? { definitionScope: pin.definitionScope }
|
|
20457
|
+
: {}),
|
|
20130
20458
|
userId: typeof pin.userId === 'string' ? pin.userId : null,
|
|
20131
20459
|
playName: pin.playName,
|
|
20132
20460
|
revisionId: typeof pin.revisionId === 'string' ? pin.revisionId : null,
|