deepline 0.3.243 → 0.3.244
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/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +7 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +4 -2
- package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +43 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +8 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +13 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +2 -3
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +40 -13
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +4 -1
- package/dist/bundling-sources/shared_libs/plays/execution-pipeline.ts +37 -11
- package/dist/bundling-sources/shared_libs/plays/retained-pipeline-graph.ts +291 -0
- package/dist/bundling-sources/shared_libs/plays/static-pipeline-storage-codec.ts +53 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/install-integrity.json +1 -0
- 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
|
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
|
|
|
200
200
|
// getters keep their established compatibility behavior.
|
|
201
201
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
202
202
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
203
|
-
version: '0.3.
|
|
203
|
+
version: '0.3.244',
|
|
204
204
|
updateSummary:
|
|
205
205
|
'Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.',
|
|
206
206
|
packageCapabilities: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { prepareRetainedPlayPipelinesForTransport } from '../plays/execution-pipeline';
|
|
1
2
|
import { createWriteStream } from 'node:fs';
|
|
2
3
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
4
|
import { stat } from 'node:fs/promises';
|
|
@@ -206,6 +207,7 @@ type RuntimeApiRequest =
|
|
|
206
207
|
executionProfile?: string | null;
|
|
207
208
|
maxCreditsPerRun?: number | null;
|
|
208
209
|
staticPipeline?: unknown;
|
|
210
|
+
retainedPipelineGraph?: unknown;
|
|
209
211
|
source?: 'published' | 'ad_hoc' | 'draft';
|
|
210
212
|
inputFileId?: string;
|
|
211
213
|
inputBytes?: number;
|
|
@@ -262,6 +264,7 @@ type RuntimeApiRequest =
|
|
|
262
264
|
runtimeHarnessWorkerName?: string | null;
|
|
263
265
|
maxCreditsPerRun?: number | null;
|
|
264
266
|
staticPipeline?: unknown;
|
|
267
|
+
retainedPipelineGraph?: unknown;
|
|
265
268
|
source?: 'published' | 'ad_hoc' | 'draft';
|
|
266
269
|
triggerSource?: 'webhook' | 'cron' | 'sql_listener' | 'api';
|
|
267
270
|
inputFileId?: string;
|
|
@@ -1448,7 +1451,9 @@ async function postAppRuntimeApi<TResponse>(
|
|
|
1448
1451
|
// attempts (that identity is what makes a receipt retry safe), so a second
|
|
1449
1452
|
// `JSON.stringify` of a megabyte payload would be pure cost.
|
|
1450
1453
|
const serializationStartedAt = Date.now();
|
|
1451
|
-
const serializedBody = JSON.stringify(
|
|
1454
|
+
const serializedBody = JSON.stringify(
|
|
1455
|
+
prepareRetainedPlayPipelinesForTransport(body),
|
|
1456
|
+
);
|
|
1452
1457
|
const requestBodySerializeMs = Math.max(
|
|
1453
1458
|
0,
|
|
1454
1459
|
Date.now() - serializationStartedAt,
|
|
@@ -2503,6 +2508,7 @@ export async function startRunViaAppRuntime(
|
|
|
2503
2508
|
executionProfile?: string | null;
|
|
2504
2509
|
maxCreditsPerRun?: number | null;
|
|
2505
2510
|
staticPipeline?: unknown;
|
|
2511
|
+
retainedPipelineGraph?: unknown;
|
|
2506
2512
|
source?: 'published' | 'ad_hoc' | 'draft';
|
|
2507
2513
|
inputFileId?: string;
|
|
2508
2514
|
inputBytes?: number;
|
|
@@ -14173,11 +14173,13 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
14173
14173
|
});
|
|
14174
14174
|
return result as TOutput;
|
|
14175
14175
|
} catch (childError) {
|
|
14176
|
-
|
|
14176
|
+
if (!isControlledPlaySuspension(childError)) {
|
|
14177
|
+
this.recordInlineChildFailure(resolvedName, childError);
|
|
14178
|
+
}
|
|
14177
14179
|
throw childError;
|
|
14178
14180
|
}
|
|
14179
14181
|
} catch (error) {
|
|
14180
|
-
if (
|
|
14182
|
+
if (isControlledPlaySuspension(error)) {
|
|
14181
14183
|
throw error;
|
|
14182
14184
|
}
|
|
14183
14185
|
if (rowStore) {
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { deployed, readDeployedObject } from '@deepline/deployed-contracts';
|
|
2
|
+
import {
|
|
3
|
+
type RetainedPipelineCarrier,
|
|
4
|
+
hydrateRetainedPlayPipelines,
|
|
5
|
+
prepareRetainedPlayPipelinesForTransport,
|
|
6
|
+
} from '../plays/execution-pipeline';
|
|
1
7
|
import type { PlayBundleArtifact } from '../plays/artifact-types';
|
|
2
8
|
import type {
|
|
3
9
|
PlayCheckpoint,
|
|
@@ -177,7 +183,7 @@ export type PlayRunnerBudgetChargeResult = {
|
|
|
177
183
|
counters: Record<string, number>;
|
|
178
184
|
};
|
|
179
185
|
|
|
180
|
-
export interface PlayRunnerContextConfig {
|
|
186
|
+
export interface PlayRunnerContextConfig extends RetainedPipelineCarrier {
|
|
181
187
|
executorToken?: string;
|
|
182
188
|
baseUrl?: string;
|
|
183
189
|
/**
|
|
@@ -447,3 +453,39 @@ export type PlayRunnerRowOutcomeSummary = {
|
|
|
447
453
|
/** Rows omitted because a newer Runtime Sheet write took precedence. */
|
|
448
454
|
supersededRows?: number;
|
|
449
455
|
};
|
|
456
|
+
|
|
457
|
+
export const RETAINED_PLAY_PIPELINE_CONTRACT = deployed.object({
|
|
458
|
+
id: 'retained-play-pipeline',
|
|
459
|
+
unknown: 'preserve',
|
|
460
|
+
fields: {
|
|
461
|
+
retainedPipelineGraph: deployed.optional(deployed.record(), {
|
|
462
|
+
whenAbsent:
|
|
463
|
+
'read the historical inline staticPipeline or stored staticPipelineV2',
|
|
464
|
+
}),
|
|
465
|
+
staticPipeline: deployed.optional(deployed.json(), {
|
|
466
|
+
whenAbsent:
|
|
467
|
+
'read the named retained pipeline root, otherwise no pipeline',
|
|
468
|
+
}),
|
|
469
|
+
},
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
/** Runner envelope ownership stays here; the shared codec owns only contracts. */
|
|
473
|
+
export function preparePlayRunnerConfigForTransport(
|
|
474
|
+
config: PlayRunnerExecutionConfig,
|
|
475
|
+
): PlayRunnerExecutionConfig {
|
|
476
|
+
return {
|
|
477
|
+
...config,
|
|
478
|
+
context: prepareRetainedPlayPipelinesForTransport(config.context),
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export function hydratePlayRunnerConfig(
|
|
483
|
+
config: PlayRunnerExecutionConfig,
|
|
484
|
+
): PlayRunnerExecutionConfig {
|
|
485
|
+
return {
|
|
486
|
+
...config,
|
|
487
|
+
context: hydrateRetainedPlayPipelines(
|
|
488
|
+
readDeployedObject(RETAINED_PLAY_PIPELINE_CONTRACT, config.context).value,
|
|
489
|
+
) as unknown as PlayRunnerContextConfig,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hydratePlayRunnerConfig } from '../protocol';
|
|
1
2
|
import { appendFileSync, createReadStream, writeFileSync } from 'node:fs';
|
|
2
3
|
import { readFile } from 'node:fs/promises';
|
|
3
4
|
import { dirname, isAbsolute, resolve } from 'node:path';
|
|
@@ -1908,6 +1909,7 @@ async function run(
|
|
|
1908
1909
|
config: PlayRunnerExecutionConfig,
|
|
1909
1910
|
options?: ExecutePlayRunnerOptions,
|
|
1910
1911
|
): Promise<PlayRunnerResult> {
|
|
1912
|
+
config = hydratePlayRunnerConfig(config);
|
|
1911
1913
|
const runStartedAt = Date.now();
|
|
1912
1914
|
const runnerRunAttempt =
|
|
1913
1915
|
typeof config.context.runAttempt === 'number' &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { preparePlayRunnerConfigForTransport } from '../../protocol';
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { readFile } from 'node:fs/promises';
|
|
3
4
|
import { gzipSync } from 'node:zlib';
|
|
@@ -695,7 +696,7 @@ export async function stageRunnerPayload(input: {
|
|
|
695
696
|
runnerCode: bundle,
|
|
696
697
|
artifactBundledCode: compactedArtifact.bundledCode,
|
|
697
698
|
artifactSourceMap: input.config.artifact.sourceMap,
|
|
698
|
-
config: remoteConfig,
|
|
699
|
+
config: preparePlayRunnerConfigForTransport(remoteConfig),
|
|
699
700
|
crashPusherCode:
|
|
700
701
|
buildDaytonaCrashTerminalPusherSource(runtimeLimitSeconds),
|
|
701
702
|
}),
|
package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { preparePlayRunnerConfigForTransport } from '../../protocol';
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { spawn } from 'node:child_process';
|
|
3
4
|
import { cp, mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
@@ -407,7 +408,13 @@ export const localProcessPlayRunnerBackend: PlayRunnerBackend = {
|
|
|
407
408
|
},
|
|
408
409
|
async () => {
|
|
409
410
|
await writeFile(runnerPath, bundle, 'utf-8');
|
|
410
|
-
await writeFile(
|
|
411
|
+
await writeFile(
|
|
412
|
+
configPath,
|
|
413
|
+
JSON.stringify(
|
|
414
|
+
preparePlayRunnerConfigForTransport(localConfig),
|
|
415
|
+
),
|
|
416
|
+
'utf-8',
|
|
417
|
+
);
|
|
411
418
|
},
|
|
412
419
|
);
|
|
413
420
|
logLocalRunnerPerf(
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
prepareRetainedPlayPipelinesForTransport,
|
|
3
|
+
hydrateRetainedPlayPipelines,
|
|
4
|
+
} from '../plays/execution-pipeline';
|
|
1
5
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
6
|
import {
|
|
3
7
|
createRuntimePool,
|
|
@@ -514,6 +518,7 @@ type RuntimeApiActionRequest =
|
|
|
514
518
|
| {
|
|
515
519
|
action: 'resolve_play';
|
|
516
520
|
playRef: string;
|
|
521
|
+
acceptRetainedPipelineGraph?: boolean;
|
|
517
522
|
}
|
|
518
523
|
| {
|
|
519
524
|
action: 'ensure_sheet';
|
|
@@ -784,7 +789,7 @@ async function postRuntimeApi<TResponse>(
|
|
|
784
789
|
response = await fetch(url, {
|
|
785
790
|
method: 'POST',
|
|
786
791
|
headers: resolveRuntimeApiHeaders(context, vercelHeaders),
|
|
787
|
-
body: JSON.stringify(body),
|
|
792
|
+
body: JSON.stringify(prepareRetainedPlayPipelinesForTransport(body)),
|
|
788
793
|
signal: context.abortSignal
|
|
789
794
|
? AbortSignal.any([context.abortSignal, abortController.signal])
|
|
790
795
|
: abortController.signal,
|
|
@@ -3579,13 +3584,19 @@ export async function resolveRuntimeReferencedPlay(
|
|
|
3579
3584
|
context: RuntimeApiContext,
|
|
3580
3585
|
playRef: string,
|
|
3581
3586
|
): Promise<ResolvedRuntimePlay | null> {
|
|
3582
|
-
const
|
|
3587
|
+
const wire = await postRuntimeApi<{
|
|
3583
3588
|
play: ResolvedRuntimePlay | null;
|
|
3584
3589
|
manifest?: { staticPipeline?: PlayStaticPipeline | null } | null;
|
|
3585
3590
|
}>(context, {
|
|
3586
3591
|
action: 'resolve_play',
|
|
3587
3592
|
playRef,
|
|
3593
|
+
acceptRetainedPipelineGraph: true,
|
|
3588
3594
|
});
|
|
3595
|
+
const response = {
|
|
3596
|
+
...wire,
|
|
3597
|
+
play: hydrateRetainedPlayPipelines(wire.play),
|
|
3598
|
+
manifest: hydrateRetainedPlayPipelines(wire.manifest),
|
|
3599
|
+
};
|
|
3589
3600
|
if (!response.play) {
|
|
3590
3601
|
return null;
|
|
3591
3602
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RetainedPipelineCarrier } from '../plays/execution-pipeline';
|
|
1
2
|
/**
|
|
2
3
|
* Scheduler-backend interface — owns play workflow lifecycle.
|
|
3
4
|
*
|
|
@@ -39,7 +40,7 @@ export type PlaySchedulerBackendId =
|
|
|
39
40
|
|
|
40
41
|
export type { PlayRunInputPayload };
|
|
41
42
|
|
|
42
|
-
export type PlaySchedulerSubmitInput = {
|
|
43
|
+
export type PlaySchedulerSubmitInput = RetainedPipelineCarrier & {
|
|
43
44
|
runId: string;
|
|
44
45
|
/**
|
|
45
46
|
* Admit an exact replay only. This is an ephemeral admission instruction:
|
|
@@ -92,8 +93,6 @@ export type PlaySchedulerSubmitInput = {
|
|
|
92
93
|
/** Immutable scheduler/worker/runner ABI snapshot (not a Git SHA). */
|
|
93
94
|
runtimeProtocolVersion?: PlayRuntimeProtocolVersion | null;
|
|
94
95
|
input: PlayRunInputPayload;
|
|
95
|
-
/** Bounded launch metadata used only by the asynchronous ledger projector. */
|
|
96
|
-
staticPipeline?: unknown;
|
|
97
96
|
inputSummary?: Record<string, unknown>;
|
|
98
97
|
/** Convex metadata for the exact input saved before scheduler submission. */
|
|
99
98
|
inputFileId?: string;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
retainedPlayPipelineFields,
|
|
3
|
+
hydrateRetainedPlayPipelines,
|
|
4
|
+
prepareRetainedPlayPipelinesForTransport,
|
|
5
|
+
} from '../../plays/execution-pipeline';
|
|
1
6
|
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
2
7
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
8
|
import { dirname, isAbsolute, join, relative, sep } from 'node:path';
|
|
@@ -4963,7 +4968,9 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
4963
4968
|
'replayedFromRunId', launch_payload.launch_json ->> 'replayedFromRunId',
|
|
4964
4969
|
'secretRefs', launch_payload.launch_json -> 'secretRefs',
|
|
4965
4970
|
'inputSummary', launch_payload.launch_json -> 'inputSummary'
|
|
4966
|
-
))
|
|
4971
|
+
)) || CASE WHEN launch_payload.launch_json ? 'retainedPipelineGraph'
|
|
4972
|
+
THEN jsonb_build_object('retainedPipelineGraph', launch_payload.launch_json -> 'retainedPipelineGraph')
|
|
4973
|
+
ELSE '{}'::jsonb END,
|
|
4967
4974
|
${causalOutboxCreatedAt('run_insert.run_id', options)}
|
|
4968
4975
|
FROM run_insert
|
|
4969
4976
|
CROSS JOIN launch_payload
|
|
@@ -5016,7 +5023,7 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
5016
5023
|
input.graphHash,
|
|
5017
5024
|
input.runtimeBackend,
|
|
5018
5025
|
input.artifactStorageKey,
|
|
5019
|
-
stringifyPostgresJson(input),
|
|
5026
|
+
stringifyPostgresJson(prepareRetainedPlayPipelinesForTransport(input)),
|
|
5020
5027
|
postgresSchedulerNotifyChannel('queue', options),
|
|
5021
5028
|
JSON.stringify({ runId: input.runId, playName: input.playName }),
|
|
5022
5029
|
releaseAdmissionKey,
|
|
@@ -5418,6 +5425,7 @@ export type PostgresSchedulerCronSourcePin = {
|
|
|
5418
5425
|
artifactHash: string | null;
|
|
5419
5426
|
graphHash: string | null;
|
|
5420
5427
|
staticPipeline: unknown | null;
|
|
5428
|
+
retainedPipelineGraph?: unknown;
|
|
5421
5429
|
input: PlaySchedulerSubmitInput['input'];
|
|
5422
5430
|
source: 'published' | 'draft';
|
|
5423
5431
|
schedulerSchema: string | null;
|
|
@@ -5442,7 +5450,7 @@ export function postgresSchedulerCronSourcePinFromLaunch(
|
|
|
5442
5450
|
artifactKind,
|
|
5443
5451
|
artifactHash: launch.artifactHash || null,
|
|
5444
5452
|
graphHash: launch.graphHash || null,
|
|
5445
|
-
|
|
5453
|
+
...retainedPlayPipelineFields(launch.staticPipeline ?? null, launch),
|
|
5446
5454
|
input: launch.input,
|
|
5447
5455
|
source: launch.source === 'draft' ? 'draft' : 'published',
|
|
5448
5456
|
schedulerSchema: launch.schedulerSchema ?? null,
|
|
@@ -5621,7 +5629,9 @@ export async function seedPostgresSchedulerCronSchedule(
|
|
|
5621
5629
|
input.dueAtMs,
|
|
5622
5630
|
input.cron.trim(),
|
|
5623
5631
|
input.timezone?.trim() || null,
|
|
5624
|
-
stringifyPostgresJson(
|
|
5632
|
+
stringifyPostgresJson(
|
|
5633
|
+
prepareRetainedPlayPipelinesForTransport(sourcePin),
|
|
5634
|
+
),
|
|
5625
5635
|
input.queueName,
|
|
5626
5636
|
task.taskName,
|
|
5627
5637
|
stringifyPostgresJson(task.params),
|
|
@@ -6038,7 +6048,9 @@ export async function firePostgresSchedulerCronSchedule(
|
|
|
6038
6048
|
'asyncAncestryPlayIds', launch_payload.launch_json -> 'asyncAncestryPlayIds',
|
|
6039
6049
|
'secretRefs', launch_payload.launch_json -> 'secretRefs',
|
|
6040
6050
|
'inputSummary', launch_payload.launch_json -> 'inputSummary'
|
|
6041
|
-
))
|
|
6051
|
+
)) || CASE WHEN launch_payload.launch_json ? 'retainedPipelineGraph'
|
|
6052
|
+
THEN jsonb_build_object('retainedPipelineGraph', launch_payload.launch_json -> 'retainedPipelineGraph')
|
|
6053
|
+
ELSE '{}'::jsonb END,
|
|
6042
6054
|
${causalOutboxCreatedAt('run_insert.run_id', options)}
|
|
6043
6055
|
FROM run_insert
|
|
6044
6056
|
CROSS JOIN launch_payload
|
|
@@ -6078,7 +6090,7 @@ export async function firePostgresSchedulerCronSchedule(
|
|
|
6078
6090
|
schedule.dueAtMs,
|
|
6079
6091
|
successorDueAtMs,
|
|
6080
6092
|
launch.runId,
|
|
6081
|
-
stringifyPostgresJson(launch),
|
|
6093
|
+
stringifyPostgresJson(prepareRetainedPlayPipelinesForTransport(launch)),
|
|
6082
6094
|
input.queueName,
|
|
6083
6095
|
playTask.taskName,
|
|
6084
6096
|
stringifyPostgresJson(playTask.params),
|
|
@@ -7463,7 +7475,7 @@ export async function claimPostgresSchedulerOverdueDetachedRunnerCeilings(
|
|
|
7463
7475
|
runId: row.run_id,
|
|
7464
7476
|
attempt: row.attempt,
|
|
7465
7477
|
leaseToken: row.lease_token,
|
|
7466
|
-
launch: row.launch_json,
|
|
7478
|
+
launch: parseLaunchJson(row.launch_json),
|
|
7467
7479
|
suspension: row.suspension_json,
|
|
7468
7480
|
}));
|
|
7469
7481
|
}
|
|
@@ -13924,7 +13936,10 @@ export function buildPostgresSchedulerRunnerContext(
|
|
|
13924
13936
|
toolResponseReceiptRevision: toolResponseReceiptRevisionFromLaunch(
|
|
13925
13937
|
launch.contractSnapshot,
|
|
13926
13938
|
),
|
|
13927
|
-
|
|
13939
|
+
...retainedPlayPipelineFields(
|
|
13940
|
+
staticPipelineFromContractSnapshot(launch.contractSnapshot),
|
|
13941
|
+
launch,
|
|
13942
|
+
),
|
|
13928
13943
|
sandboxRuntimeLimits: sandboxRuntimeLimitsFromContractSnapshot(
|
|
13929
13944
|
launch.contractSnapshot,
|
|
13930
13945
|
),
|
|
@@ -16221,7 +16236,9 @@ export async function appendPostgresRunLedgerStart(
|
|
|
16221
16236
|
runId: input.runId,
|
|
16222
16237
|
eventId: `run-start-callback:${input.runId}`,
|
|
16223
16238
|
eventType: 'run.started',
|
|
16224
|
-
payload: stableStringify(
|
|
16239
|
+
payload: stableStringify(
|
|
16240
|
+
prepareRetainedPlayPipelinesForTransport(input.start),
|
|
16241
|
+
),
|
|
16225
16242
|
},
|
|
16226
16243
|
options,
|
|
16227
16244
|
);
|
|
@@ -18093,6 +18110,7 @@ async function projectPostgresSchedulerCreatedEvent(
|
|
|
18093
18110
|
runtimeApi: WorkerRuntimeApiContext,
|
|
18094
18111
|
event: PostgresSchedulerOutboxEvent,
|
|
18095
18112
|
): Promise<void> {
|
|
18113
|
+
event = { ...event, payload: hydrateRetainedPlayPipelines(event.payload) };
|
|
18096
18114
|
const value = (key: string) => stringPayloadField(event.payload, key);
|
|
18097
18115
|
const number = (key: string) => numberPayloadField(event.payload, key);
|
|
18098
18116
|
const raw = (key: string) => payloadField(event.payload, key);
|
|
@@ -18153,7 +18171,10 @@ async function projectPostgresSchedulerCreatedEvent(
|
|
|
18153
18171
|
runtimeWorkflowName: value('runtimeWorkflowName'),
|
|
18154
18172
|
runtimeHarnessWorkerName: value('runtimeHarnessWorkerName'),
|
|
18155
18173
|
maxCreditsPerRun: number('maxCreditsPerRun'),
|
|
18156
|
-
|
|
18174
|
+
...retainedPlayPipelineFields(
|
|
18175
|
+
raw('staticPipeline'),
|
|
18176
|
+
event.payload as { retainedPipelineGraph?: unknown },
|
|
18177
|
+
),
|
|
18157
18178
|
source: sourcePayloadField(event.payload, 'source'),
|
|
18158
18179
|
...(triggerSource === 'api' ||
|
|
18159
18180
|
triggerSource === 'webhook' ||
|
|
@@ -18179,6 +18200,9 @@ async function projectPostgresSchedulerStartEvent(
|
|
|
18179
18200
|
event: PostgresSchedulerOutboxEvent,
|
|
18180
18201
|
launch: (PlaySchedulerSubmitInput & { firstClaimLatencyMs?: number }) | null,
|
|
18181
18202
|
): Promise<void> {
|
|
18203
|
+
const payload = hydrateRetainedPlayPipelines(
|
|
18204
|
+
event.payload as Record<string, unknown>,
|
|
18205
|
+
);
|
|
18182
18206
|
await startRunViaAppRuntime(runtimeApi, {
|
|
18183
18207
|
deliveryLeaseOwner: event.leaseOwner ?? undefined,
|
|
18184
18208
|
idempotencyKey: buildRunLedgerStartIdempotencyKey({
|
|
@@ -18198,7 +18222,7 @@ async function projectPostgresSchedulerStartEvent(
|
|
|
18198
18222
|
schedulerSchema: stringPayloadField(event.payload, 'schedulerSchema'),
|
|
18199
18223
|
executionProfile: stringPayloadField(event.payload, 'executionProfile'),
|
|
18200
18224
|
maxCreditsPerRun: numberPayloadField(event.payload, 'maxCreditsPerRun'),
|
|
18201
|
-
|
|
18225
|
+
...retainedPlayPipelineFields(payload.staticPipeline, payload),
|
|
18202
18226
|
source: sourcePayloadField(event.payload, 'source'),
|
|
18203
18227
|
inputFileId:
|
|
18204
18228
|
launch?.inputFileId ??
|
|
@@ -18619,7 +18643,7 @@ function parseLaunchJson(value: unknown): PlaySchedulerSubmitInput {
|
|
|
18619
18643
|
'Postgres scheduler launch_json is missing required fields.',
|
|
18620
18644
|
);
|
|
18621
18645
|
}
|
|
18622
|
-
return launch as PlaySchedulerSubmitInput;
|
|
18646
|
+
return hydrateRetainedPlayPipelines(launch as PlaySchedulerSubmitInput);
|
|
18623
18647
|
}
|
|
18624
18648
|
|
|
18625
18649
|
function parsePostgresSchedulerCronSourcePin(
|
|
@@ -18628,7 +18652,9 @@ function parsePostgresSchedulerCronSourcePin(
|
|
|
18628
18652
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
18629
18653
|
throw new Error('Cron source pin is not an object.');
|
|
18630
18654
|
}
|
|
18631
|
-
const pin =
|
|
18655
|
+
const pin = hydrateRetainedPlayPipelines(
|
|
18656
|
+
value as Partial<PostgresSchedulerCronSourcePin>,
|
|
18657
|
+
);
|
|
18632
18658
|
if (
|
|
18633
18659
|
typeof pin.orgId !== 'string' ||
|
|
18634
18660
|
typeof pin.playName !== 'string' ||
|
|
@@ -18639,6 +18665,7 @@ function parsePostgresSchedulerCronSourcePin(
|
|
|
18639
18665
|
throw new Error('Cron source pin is missing required immutable fields.');
|
|
18640
18666
|
}
|
|
18641
18667
|
return {
|
|
18668
|
+
...pin,
|
|
18642
18669
|
orgId: pin.orgId,
|
|
18643
18670
|
userId: typeof pin.userId === 'string' ? pin.userId : null,
|
|
18644
18671
|
playName: pin.playName,
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hydrateRetainedPlayPipelines } from '../../plays/execution-pipeline';
|
|
1
2
|
/**
|
|
2
3
|
* Runtime receipt gateway dispatch.
|
|
3
4
|
*
|
|
@@ -866,7 +867,9 @@ export function createReceiptGatewayDispatcher(input: {
|
|
|
866
867
|
{ status: 400 },
|
|
867
868
|
);
|
|
868
869
|
}
|
|
869
|
-
const body =
|
|
870
|
+
const body = hydrateRetainedPlayPipelines(
|
|
871
|
+
rawBody as ReceiptGatewayActionBody,
|
|
872
|
+
);
|
|
870
873
|
const scopeError = requireReceiptScope(scope, body);
|
|
871
874
|
if (scopeError) return scopeError;
|
|
872
875
|
const runId = String(body.runId || scope.runId);
|
|
@@ -1,24 +1,41 @@
|
|
|
1
|
+
import type { RetainedPipelineCarrier } from './retained-pipeline-graph';
|
|
1
2
|
import type { PlayStaticPipeline } from './static-pipeline';
|
|
2
3
|
import { staticPipelineStorageCodec } from './static-pipeline-storage-codec';
|
|
3
4
|
|
|
5
|
+
export {
|
|
6
|
+
retainedPlayPipelineFields,
|
|
7
|
+
type RetainedPlayContract,
|
|
8
|
+
type RetainedPipelineCarrier,
|
|
9
|
+
encodeRetainedPlayPipelines,
|
|
10
|
+
hydrateRetainedPlayPipelines,
|
|
11
|
+
prepareRetainedPlayPipelinesForTransport,
|
|
12
|
+
type RetainedPipelineGraph,
|
|
13
|
+
} from './retained-pipeline-graph';
|
|
14
|
+
|
|
4
15
|
/**
|
|
5
16
|
* An in-process execution snapshot, deliberately distinct from display graphs
|
|
6
|
-
* and Convex's bounded V1 mirror.
|
|
7
|
-
*
|
|
17
|
+
* and Convex's bounded V1 mirror. Boundary adapters use the shared retained
|
|
18
|
+
* contract codec above; JSON serialization of the hydrated pipeline expands
|
|
19
|
+
* shared child definitions and is not a valid transport.
|
|
8
20
|
*/
|
|
9
21
|
export class PlayExecutionPipeline {
|
|
10
22
|
readonly #pipeline: PlayStaticPipeline | null;
|
|
11
23
|
|
|
12
|
-
private constructor(
|
|
24
|
+
private constructor(
|
|
25
|
+
pipeline: PlayStaticPipeline | null,
|
|
26
|
+
readonly retainedPipelineGraph?: unknown,
|
|
27
|
+
) {
|
|
13
28
|
this.#pipeline = pipeline;
|
|
14
29
|
}
|
|
15
30
|
|
|
16
31
|
/** Read the entire storage carrier, so an existing V2 can never be dropped. */
|
|
17
|
-
static fromStored(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
static fromStored(
|
|
33
|
+
record: RetainedPipelineCarrier & { staticPipelineV2?: unknown },
|
|
34
|
+
): PlayExecutionPipeline {
|
|
35
|
+
return new PlayExecutionPipeline(
|
|
36
|
+
staticPipelineStorageCodec.read(record),
|
|
37
|
+
record.retainedPipelineGraph,
|
|
38
|
+
);
|
|
22
39
|
}
|
|
23
40
|
|
|
24
41
|
/** Only for complete compiler/admitted-artifact graphs, never a stored field. */
|
|
@@ -58,13 +75,22 @@ export function readPlayExecutionPipeline(
|
|
|
58
75
|
|
|
59
76
|
/** Execution readers cannot see (and accidentally forward) the stored mirror. */
|
|
60
77
|
export function readStoredPlayExecutionSnapshot<
|
|
61
|
-
T extends {
|
|
78
|
+
T extends {
|
|
79
|
+
staticPipeline?: unknown;
|
|
80
|
+
staticPipelineV2?: unknown;
|
|
81
|
+
retainedPipelineGraph?: unknown;
|
|
82
|
+
},
|
|
62
83
|
>(
|
|
63
84
|
record: T,
|
|
64
|
-
): Omit<T, 'staticPipeline' | 'staticPipelineV2'> & {
|
|
85
|
+
): Omit<T, 'staticPipeline' | 'staticPipelineV2' | 'retainedPipelineGraph'> & {
|
|
65
86
|
executionPipeline: PlayExecutionPipeline;
|
|
66
87
|
} {
|
|
67
|
-
const {
|
|
88
|
+
const {
|
|
89
|
+
staticPipeline: _v1,
|
|
90
|
+
staticPipelineV2: _v2,
|
|
91
|
+
retainedPipelineGraph: _graph,
|
|
92
|
+
...metadata
|
|
93
|
+
} = record;
|
|
68
94
|
return {
|
|
69
95
|
...metadata,
|
|
70
96
|
executionPipeline: PlayExecutionPipeline.fromStored(record),
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lossless transport for retained execution graphs. A call site remains a
|
|
3
|
+
* distinct node; equal immutable definition content is stored once. References
|
|
4
|
+
* are scoped to this envelope, never resolved against a mutable Play registry.
|
|
5
|
+
*
|
|
6
|
+
* This is an additive named representation. Readers must be deployed before
|
|
7
|
+
* WRITE_RETAINED_PIPELINE_GRAPHS is enabled in a separate release.
|
|
8
|
+
*/
|
|
9
|
+
export const WRITE_RETAINED_PIPELINE_GRAPHS = false;
|
|
10
|
+
|
|
11
|
+
type Scalar = null | boolean | number | string;
|
|
12
|
+
type GraphValue = Scalar | { ref: number };
|
|
13
|
+
type GraphNode = { array: GraphValue[] } | { object: [string, GraphValue][] };
|
|
14
|
+
|
|
15
|
+
export type RetainedPipelineGraph = {
|
|
16
|
+
nodes: GraphNode[];
|
|
17
|
+
roots: Record<string, GraphValue>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** The owned execution contract; caller envelopes choose their own adapter. */
|
|
21
|
+
export type RetainedPlayContract = {
|
|
22
|
+
retainedPipelineGraph?: unknown;
|
|
23
|
+
staticPipeline?: unknown;
|
|
24
|
+
authoringContract?: { staticPipeline?: unknown } | null;
|
|
25
|
+
contractSnapshot?: {
|
|
26
|
+
staticPipeline?: unknown;
|
|
27
|
+
authoringContract?: { staticPipeline?: unknown } | null;
|
|
28
|
+
} | null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type RetainedPipelineCarrier = Pick<
|
|
32
|
+
RetainedPlayContract,
|
|
33
|
+
'staticPipeline' | 'retainedPipelineGraph'
|
|
34
|
+
>;
|
|
35
|
+
|
|
36
|
+
// Named roots have fixed meaning. This is not a recursive JSON serializer:
|
|
37
|
+
// customer inputs, checkpoints, runner configs and API responses are not
|
|
38
|
+
// searched for magic property names. Their owners explicitly pass a contract.
|
|
39
|
+
const PIPELINE_ROOT_PATHS = {
|
|
40
|
+
pipeline: [],
|
|
41
|
+
authoring: ['authoringContract'],
|
|
42
|
+
admitted: ['contractSnapshot'],
|
|
43
|
+
admittedAuthoring: ['contractSnapshot', 'authoringContract'],
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
function contractAt(input: Record<string, unknown>, path: readonly string[]) {
|
|
47
|
+
let owner = input;
|
|
48
|
+
for (const key of path) {
|
|
49
|
+
if (!record(owner[key])) return undefined;
|
|
50
|
+
owner = owner[key];
|
|
51
|
+
}
|
|
52
|
+
return owner;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function updateContract(
|
|
56
|
+
input: Record<string, unknown>,
|
|
57
|
+
path: readonly string[],
|
|
58
|
+
pipeline: unknown,
|
|
59
|
+
remove: boolean,
|
|
60
|
+
): Record<string, unknown> {
|
|
61
|
+
const result = { ...input };
|
|
62
|
+
let owner = result;
|
|
63
|
+
for (const key of path) {
|
|
64
|
+
if (Object.prototype.hasOwnProperty.call(owner, key) && !record(owner[key]))
|
|
65
|
+
invalid('invalid contract container');
|
|
66
|
+
const child = record(owner[key]) ? { ...owner[key] } : {};
|
|
67
|
+
owner[key] = child;
|
|
68
|
+
owner = child;
|
|
69
|
+
}
|
|
70
|
+
if (remove) delete owner.staticPipeline;
|
|
71
|
+
else owner.staticPipeline = pipeline;
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function record(value: unknown): value is Record<string, unknown> {
|
|
76
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function invalid(detail: string): never {
|
|
80
|
+
throw new Error(`Invalid retained Play pipeline graph: ${detail}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Explicit encoder, also used by fixtures before production writer enable. */
|
|
84
|
+
export function encodeRetainedPlayPipelines<T>(input: T): T {
|
|
85
|
+
if (!record(input)) return input;
|
|
86
|
+
// Repeated serialization must not expand a previously encoded envelope.
|
|
87
|
+
const prior =
|
|
88
|
+
input.retainedPipelineGraph === undefined
|
|
89
|
+
? null
|
|
90
|
+
: readGraph(input.retainedPipelineGraph);
|
|
91
|
+
const source = prior ? hydrateContractRoots(input, prior.roots) : input;
|
|
92
|
+
// Retain existing node IDs and all additive graph/node metadata. A reader
|
|
93
|
+
// that forwards a newer envelope must not rebuild away fields it ignores.
|
|
94
|
+
const nodes: GraphNode[] = prior
|
|
95
|
+
? [...(input.retainedPipelineGraph as RetainedPipelineGraph).nodes]
|
|
96
|
+
: [];
|
|
97
|
+
const interned = new Map<string, number>();
|
|
98
|
+
const objects = new WeakMap<object, number>();
|
|
99
|
+
const visiting = new WeakSet<object>();
|
|
100
|
+
const roots: RetainedPipelineGraph['roots'] = prior
|
|
101
|
+
? { ...(input.retainedPipelineGraph as RetainedPipelineGraph).roots }
|
|
102
|
+
: {};
|
|
103
|
+
for (let id = 0; id < nodes.length; id += 1) {
|
|
104
|
+
interned.set(JSON.stringify(nodes[id]), id);
|
|
105
|
+
const value = prior!.values[id];
|
|
106
|
+
if (value !== null && typeof value === 'object') objects.set(value, id);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function encode(value: unknown): GraphValue {
|
|
110
|
+
if (value === null) return null;
|
|
111
|
+
if (typeof value === 'string' || typeof value === 'boolean') return value;
|
|
112
|
+
if (typeof value === 'number') return Number.isFinite(value) ? value : null;
|
|
113
|
+
if (typeof value !== 'object') invalid('non-JSON pipeline value');
|
|
114
|
+
const cached = objects.get(value);
|
|
115
|
+
if (cached !== undefined) return { ref: cached };
|
|
116
|
+
if (visiting.has(value)) invalid('cyclic pipeline');
|
|
117
|
+
visiting.add(value);
|
|
118
|
+
const prototype = Object.getPrototypeOf(value);
|
|
119
|
+
if (
|
|
120
|
+
!Array.isArray(value) &&
|
|
121
|
+
prototype !== Object.prototype &&
|
|
122
|
+
prototype !== null
|
|
123
|
+
) {
|
|
124
|
+
invalid('pipeline must contain plain JSON objects');
|
|
125
|
+
}
|
|
126
|
+
const node: GraphNode = Array.isArray(value)
|
|
127
|
+
? { array: Array.from(value, (entry) => encode(entry ?? null)) }
|
|
128
|
+
: {
|
|
129
|
+
object: Object.entries(value)
|
|
130
|
+
.filter(([, entry]) => entry !== undefined)
|
|
131
|
+
.map(([key, entry]) => [key, encode(entry)]),
|
|
132
|
+
};
|
|
133
|
+
// Node signatures contain references, never recursively expanded children.
|
|
134
|
+
const signature = JSON.stringify(node);
|
|
135
|
+
let id = interned.get(signature);
|
|
136
|
+
if (id === undefined) {
|
|
137
|
+
id = nodes.length;
|
|
138
|
+
nodes.push(node);
|
|
139
|
+
interned.set(signature, id);
|
|
140
|
+
}
|
|
141
|
+
visiting.delete(value);
|
|
142
|
+
objects.set(value, id);
|
|
143
|
+
return { ref: id };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let result: Record<string, unknown> = { ...source };
|
|
147
|
+
for (const [name, path] of Object.entries(PIPELINE_ROOT_PATHS)) {
|
|
148
|
+
const owner = contractAt(source, path);
|
|
149
|
+
if (
|
|
150
|
+
owner &&
|
|
151
|
+
Object.prototype.hasOwnProperty.call(owner, 'staticPipeline') &&
|
|
152
|
+
owner.staticPipeline !== undefined
|
|
153
|
+
) {
|
|
154
|
+
roots[name] = encode(owner.staticPipeline);
|
|
155
|
+
result = updateContract(result, path, undefined, true);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (!Object.keys(roots).length) return input;
|
|
159
|
+
return {
|
|
160
|
+
...result,
|
|
161
|
+
retainedPipelineGraph: {
|
|
162
|
+
...(record(input.retainedPipelineGraph)
|
|
163
|
+
? input.retainedPipelineGraph
|
|
164
|
+
: {}),
|
|
165
|
+
nodes,
|
|
166
|
+
roots,
|
|
167
|
+
},
|
|
168
|
+
} as T;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function readGraph(graph: unknown): {
|
|
172
|
+
roots: Record<string, unknown>;
|
|
173
|
+
values: unknown[];
|
|
174
|
+
} {
|
|
175
|
+
if (!record(graph) || !Array.isArray(graph.nodes) || !record(graph.roots)) {
|
|
176
|
+
invalid('expected nodes and roots');
|
|
177
|
+
}
|
|
178
|
+
const values: unknown[] = [];
|
|
179
|
+
function decode(value: unknown): unknown {
|
|
180
|
+
if (
|
|
181
|
+
value === null ||
|
|
182
|
+
typeof value === 'string' ||
|
|
183
|
+
typeof value === 'boolean'
|
|
184
|
+
)
|
|
185
|
+
return value;
|
|
186
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
187
|
+
if (
|
|
188
|
+
!record(value) ||
|
|
189
|
+
Object.keys(value).length !== 1 ||
|
|
190
|
+
!Number.isSafeInteger(value.ref) ||
|
|
191
|
+
(value.ref as number) < 0 ||
|
|
192
|
+
(value.ref as number) >= values.length
|
|
193
|
+
) {
|
|
194
|
+
invalid('reference must name a preceding node');
|
|
195
|
+
}
|
|
196
|
+
return values[value.ref as number];
|
|
197
|
+
}
|
|
198
|
+
for (const node of graph.nodes) {
|
|
199
|
+
if (!record(node)) invalid('expected node object');
|
|
200
|
+
if (Array.isArray(node.array) && node.object === undefined) {
|
|
201
|
+
values.push(node.array.map(decode));
|
|
202
|
+
} else if (Array.isArray(node.object) && node.array === undefined) {
|
|
203
|
+
const entries: [string, unknown][] = [];
|
|
204
|
+
const keys = new Set<string>();
|
|
205
|
+
for (const entry of node.object) {
|
|
206
|
+
if (
|
|
207
|
+
!Array.isArray(entry) ||
|
|
208
|
+
entry.length !== 2 ||
|
|
209
|
+
typeof entry[0] !== 'string' ||
|
|
210
|
+
keys.has(entry[0])
|
|
211
|
+
) {
|
|
212
|
+
invalid('invalid or duplicate object entry');
|
|
213
|
+
}
|
|
214
|
+
keys.add(entry[0]);
|
|
215
|
+
entries.push([entry[0], decode(entry[1])]);
|
|
216
|
+
}
|
|
217
|
+
values.push(Object.fromEntries(entries));
|
|
218
|
+
} else invalid('expected array or object node');
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
roots: Object.fromEntries(
|
|
222
|
+
Object.entries(graph.roots).map(([name, value]) => [name, decode(value)]),
|
|
223
|
+
),
|
|
224
|
+
values,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Old envelopes pass through unchanged; malformed explicit graphs fail loudly. */
|
|
229
|
+
export function hydrateRetainedPlayPipelines<T>(input: T): T {
|
|
230
|
+
if (!record(input) || input.retainedPipelineGraph === undefined) return input;
|
|
231
|
+
return hydrateContractRoots(
|
|
232
|
+
input,
|
|
233
|
+
readGraph(input.retainedPipelineGraph).roots,
|
|
234
|
+
) as T;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function hydrateContractRoots(
|
|
238
|
+
input: Record<string, unknown>,
|
|
239
|
+
roots: Record<string, unknown>,
|
|
240
|
+
): Record<string, unknown> {
|
|
241
|
+
let result: Record<string, unknown> = { ...input };
|
|
242
|
+
for (const [name, path] of Object.entries(PIPELINE_ROOT_PATHS)) {
|
|
243
|
+
if (!Object.prototype.hasOwnProperty.call(roots, name)) continue;
|
|
244
|
+
const pipeline = roots[name];
|
|
245
|
+
if (
|
|
246
|
+
pipeline !== null &&
|
|
247
|
+
(!record(pipeline) ||
|
|
248
|
+
!Array.isArray(pipeline.fields) ||
|
|
249
|
+
!Array.isArray(pipeline.substeps))
|
|
250
|
+
) {
|
|
251
|
+
invalid(`root ${name} must be a complete pipeline or null`);
|
|
252
|
+
}
|
|
253
|
+
result = updateContract(result, path, pipeline, false);
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** Production writers remain inert until the separate reader rollout completes. */
|
|
259
|
+
export function prepareRetainedPlayPipelinesForTransport<T>(input: T): T {
|
|
260
|
+
// Reader-only builds must preserve new representations when forwarding
|
|
261
|
+
// them. The rollout switch controls creation from legacy envelopes only.
|
|
262
|
+
return WRITE_RETAINED_PIPELINE_GRAPHS ||
|
|
263
|
+
(record(input) && input.retainedPipelineGraph !== undefined)
|
|
264
|
+
? encodeRetainedPlayPipelines(input)
|
|
265
|
+
: input;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Project one retained pipeline into a new envelope without losing its format. */
|
|
269
|
+
export function retainedPlayPipelineFields<T>(
|
|
270
|
+
pipeline: T,
|
|
271
|
+
source: RetainedPipelineCarrier,
|
|
272
|
+
): { staticPipeline: T; retainedPipelineGraph?: RetainedPipelineGraph } {
|
|
273
|
+
if (source.retainedPipelineGraph === undefined)
|
|
274
|
+
return { staticPipeline: pipeline };
|
|
275
|
+
readGraph(source.retainedPipelineGraph);
|
|
276
|
+
const graph = source.retainedPipelineGraph as RetainedPipelineGraph;
|
|
277
|
+
// This is an explicit projection to one pipeline, not a reinterpretation of
|
|
278
|
+
// the old root. Keep unknown roles and metadata through the projection.
|
|
279
|
+
const roots = Object.fromEntries(
|
|
280
|
+
Object.entries(graph.roots).filter(
|
|
281
|
+
([name]) =>
|
|
282
|
+
!Object.prototype.hasOwnProperty.call(PIPELINE_ROOT_PATHS, name),
|
|
283
|
+
),
|
|
284
|
+
);
|
|
285
|
+
return hydrateRetainedPlayPipelines(
|
|
286
|
+
encodeRetainedPlayPipelines({
|
|
287
|
+
staticPipeline: pipeline,
|
|
288
|
+
retainedPipelineGraph: { ...graph, roots },
|
|
289
|
+
}),
|
|
290
|
+
);
|
|
291
|
+
}
|
|
@@ -3,7 +3,58 @@ import {
|
|
|
3
3
|
createStoredStaticPipelineV2,
|
|
4
4
|
hydrateStoredStaticPipelineV2,
|
|
5
5
|
readStoredStaticPipeline,
|
|
6
|
+
createStaticPipelineV1CompatibilityProjection,
|
|
7
|
+
type PlayStaticPipeline,
|
|
6
8
|
} from './static-pipeline';
|
|
9
|
+
import {
|
|
10
|
+
retainedPlayPipelineFields,
|
|
11
|
+
encodeRetainedPlayPipelines,
|
|
12
|
+
hydrateRetainedPlayPipelines,
|
|
13
|
+
WRITE_RETAINED_PIPELINE_GRAPHS,
|
|
14
|
+
type RetainedPipelineGraph,
|
|
15
|
+
type RetainedPipelineCarrier,
|
|
16
|
+
} from './retained-pipeline-graph';
|
|
17
|
+
|
|
18
|
+
function readExecutionPipeline(
|
|
19
|
+
record: RetainedPipelineCarrier & { staticPipelineV2?: unknown },
|
|
20
|
+
): PlayStaticPipeline | null {
|
|
21
|
+
if (record.retainedPipelineGraph !== undefined) {
|
|
22
|
+
const hydrated = hydrateRetainedPlayPipelines({
|
|
23
|
+
retainedPipelineGraph: record.retainedPipelineGraph,
|
|
24
|
+
}) as { staticPipeline?: PlayStaticPipeline | null };
|
|
25
|
+
if (hydrated.staticPipeline === undefined)
|
|
26
|
+
throw new Error('Retained execution graph is missing its pipeline root.');
|
|
27
|
+
return hydrated.staticPipeline;
|
|
28
|
+
}
|
|
29
|
+
return readStoredStaticPipeline(record);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Runs use the shared graph after all storage readers have been deployed. */
|
|
33
|
+
function executionStorageFields(
|
|
34
|
+
pipeline: PlayStaticPipeline | null | undefined,
|
|
35
|
+
carrier?: RetainedPipelineCarrier,
|
|
36
|
+
): {
|
|
37
|
+
staticPipeline?: PlayStaticPipeline | null;
|
|
38
|
+
staticPipelineV2?: ReturnType<typeof createStoredStaticPipelineV2>;
|
|
39
|
+
retainedPipelineGraph?: RetainedPipelineGraph;
|
|
40
|
+
} {
|
|
41
|
+
if (
|
|
42
|
+
(!WRITE_RETAINED_PIPELINE_GRAPHS &&
|
|
43
|
+
carrier?.retainedPipelineGraph === undefined) ||
|
|
44
|
+
pipeline === undefined
|
|
45
|
+
) {
|
|
46
|
+
return createStaticPipelineStorageFields(pipeline);
|
|
47
|
+
}
|
|
48
|
+
const compact = encodeRetainedPlayPipelines(
|
|
49
|
+
retainedPlayPipelineFields(pipeline, carrier ?? {}),
|
|
50
|
+
) as unknown as {
|
|
51
|
+
retainedPipelineGraph: RetainedPipelineGraph;
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
staticPipeline: createStaticPipelineV1CompatibilityProjection(pipeline),
|
|
55
|
+
retainedPipelineGraph: compact.retainedPipelineGraph,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
7
58
|
|
|
8
59
|
export {
|
|
9
60
|
isStoredStaticPipelineV2IntegrityError,
|
|
@@ -23,5 +74,6 @@ export const staticPipelineStorageCodec = Object.freeze({
|
|
|
23
74
|
flatten: createStoredStaticPipelineV2,
|
|
24
75
|
hydrate: hydrateStoredStaticPipelineV2,
|
|
25
76
|
storageFields: createStaticPipelineStorageFields,
|
|
26
|
-
read:
|
|
77
|
+
read: readExecutionPipeline,
|
|
78
|
+
executionStorageFields,
|
|
27
79
|
});
|
package/dist/cli/index.js
CHANGED
|
@@ -3473,7 +3473,7 @@ var SDK_RELEASE = {
|
|
|
3473
3473
|
// getters keep their established compatibility behavior.
|
|
3474
3474
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3475
3475
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3476
|
-
version: "0.3.
|
|
3476
|
+
version: "0.3.244",
|
|
3477
3477
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3478
3478
|
packageCapabilities: {
|
|
3479
3479
|
updatePreferences: 1
|
package/dist/cli/index.mjs
CHANGED
|
@@ -3468,7 +3468,7 @@ var SDK_RELEASE = {
|
|
|
3468
3468
|
// getters keep their established compatibility behavior.
|
|
3469
3469
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3470
3470
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3471
|
-
version: "0.3.
|
|
3471
|
+
version: "0.3.244",
|
|
3472
3472
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3473
3473
|
packageCapabilities: {
|
|
3474
3474
|
updatePreferences: 1
|
package/dist/index.js
CHANGED
|
@@ -1286,7 +1286,7 @@ var SDK_RELEASE = {
|
|
|
1286
1286
|
// getters keep their established compatibility behavior.
|
|
1287
1287
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1288
1288
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
1289
|
-
version: "0.3.
|
|
1289
|
+
version: "0.3.244",
|
|
1290
1290
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
1291
1291
|
packageCapabilities: {
|
|
1292
1292
|
updatePreferences: 1
|
package/dist/index.mjs
CHANGED
|
@@ -1190,7 +1190,7 @@ var SDK_RELEASE = {
|
|
|
1190
1190
|
// getters keep their established compatibility behavior.
|
|
1191
1191
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1192
1192
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
1193
|
-
version: "0.3.
|
|
1193
|
+
version: "0.3.244",
|
|
1194
1194
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
1195
1195
|
packageCapabilities: {
|
|
1196
1196
|
updatePreferences: 1
|
|
@@ -506,6 +506,7 @@
|
|
|
506
506
|
"dist/bundling-sources/shared_libs/plays/play-grep-search.ts",
|
|
507
507
|
"dist/bundling-sources/shared_libs/plays/play-reference.ts",
|
|
508
508
|
"dist/bundling-sources/shared_libs/plays/resolve-static-pipeline.ts",
|
|
509
|
+
"dist/bundling-sources/shared_libs/plays/retained-pipeline-graph.ts",
|
|
509
510
|
"dist/bundling-sources/shared_libs/plays/row-identity.ts",
|
|
510
511
|
"dist/bundling-sources/shared_libs/plays/run-input-summary.ts",
|
|
511
512
|
"dist/bundling-sources/shared_libs/plays/run-summary-types.ts",
|
package/dist/release.d.mts
CHANGED
|
@@ -149,7 +149,7 @@ type SdkRelease = {
|
|
|
149
149
|
supportPolicy: SdkSupportPolicy;
|
|
150
150
|
};
|
|
151
151
|
declare const SDK_RELEASE: {
|
|
152
|
-
readonly version: "0.3.
|
|
152
|
+
readonly version: "0.3.244";
|
|
153
153
|
readonly updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.";
|
|
154
154
|
readonly packageCapabilities: {
|
|
155
155
|
readonly updatePreferences: 1;
|
package/dist/release.d.ts
CHANGED
|
@@ -149,7 +149,7 @@ type SdkRelease = {
|
|
|
149
149
|
supportPolicy: SdkSupportPolicy;
|
|
150
150
|
};
|
|
151
151
|
declare const SDK_RELEASE: {
|
|
152
|
-
readonly version: "0.3.
|
|
152
|
+
readonly version: "0.3.244";
|
|
153
153
|
readonly updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.";
|
|
154
154
|
readonly packageCapabilities: {
|
|
155
155
|
readonly updatePreferences: 1;
|
package/dist/release.js
CHANGED
|
@@ -74,7 +74,7 @@ var SDK_RELEASE = {
|
|
|
74
74
|
// getters keep their established compatibility behavior.
|
|
75
75
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
76
76
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
77
|
-
version: "0.3.
|
|
77
|
+
version: "0.3.244",
|
|
78
78
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
79
79
|
packageCapabilities: {
|
|
80
80
|
updatePreferences: 1
|
package/dist/release.mjs
CHANGED
|
@@ -48,7 +48,7 @@ var SDK_RELEASE = {
|
|
|
48
48
|
// getters keep their established compatibility behavior.
|
|
49
49
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
50
50
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
51
|
-
version: "0.3.
|
|
51
|
+
version: "0.3.244",
|
|
52
52
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
53
53
|
packageCapabilities: {
|
|
54
54
|
updatePreferences: 1
|