deepline 0.3.469 → 0.3.471
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-core.ts +5 -0
- package/dist/bundling-sources/sdk/src/index.ts +1 -0
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +1 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/types.ts +22 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-admission-outcome.ts +34 -8
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +173 -32
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +3 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +36 -1
- package/dist/cli/auth-2MMOFS3O.js +41 -0
- package/dist/cli/{auth-HHMOHWIF.mjs → auth-MUCIXHJF.mjs} +5 -5
- package/dist/cli/{billing-26PU55WM.js → billing-BQQNTCTV.js} +82 -81
- package/dist/cli/{billing-KQORGOK4.mjs → billing-QGCTDE2N.mjs} +9 -8
- package/dist/cli/{chunk-YCIQYY5F.mjs → chunk-2KBRY5CA.mjs} +3 -3
- package/dist/cli/{chunk-WFI46NX4.mjs → chunk-3PT2HJKC.mjs} +1 -1
- package/dist/cli/{chunk-PKCDG6W5.mjs → chunk-4OAA43RX.mjs} +3 -3
- package/dist/cli/{chunk-E55WWSW4.js → chunk-4PT2WZD2.js} +26 -26
- package/dist/cli/{chunk-GFHBE35X.js → chunk-5QWGL2QO.js} +93 -93
- package/dist/cli/{chunk-HNP5V5BN.js → chunk-6DTW6JND.js} +6 -2
- package/dist/cli/{chunk-E6O62X6Z.mjs → chunk-AMUSZHCE.mjs} +2 -2
- package/dist/cli/{chunk-I5ZF67WP.mjs → chunk-ATKFOOVD.mjs} +5 -5
- package/dist/cli/{chunk-RC7X6KBQ.js → chunk-CR2F3JZN.js} +51 -51
- package/dist/cli/{chunk-SNAPSOK7.js → chunk-DFMFYOML.js} +10 -10
- package/dist/cli/{chunk-ODOFLA34.js → chunk-DK5Y5BD3.js} +4 -4
- package/dist/cli/{chunk-GVRTIZJN.mjs → chunk-DV4V5IWI.mjs} +5 -5
- package/dist/cli/{chunk-5WQM5HAQ.mjs → chunk-E2SHDT7T.mjs} +2 -2
- package/dist/cli/{chunk-SXTMM4DA.js → chunk-E3WTQ3JI.js} +14 -14
- package/dist/cli/{chunk-D7DUKSFS.mjs → chunk-EHVVDHNU.mjs} +1 -1
- package/dist/cli/{chunk-WCKFCSRX.mjs → chunk-EYKMITTY.mjs} +4 -4
- package/dist/cli/{chunk-FA3G556U.mjs → chunk-FJBGBPYY.mjs} +2 -2
- package/dist/cli/{chunk-UI2UC3OD.mjs → chunk-FVGT5EBA.mjs} +1 -1
- package/dist/cli/{chunk-YSRQJ4M3.js → chunk-FX3QM6WN.js} +3 -3
- package/dist/cli/{chunk-KOBMP4ZD.js → chunk-G6RQXAJ2.js} +1 -1
- package/dist/cli/{chunk-LBG7M2UO.js → chunk-GPSVXVDZ.js} +8 -8
- package/dist/cli/{chunk-I7TGFUQJ.mjs → chunk-IE5KAVTI.mjs} +3 -3
- package/dist/cli/{chunk-RXG2KE3N.mjs → chunk-IPFUDUSY.mjs} +4 -4
- package/dist/cli/{chunk-L34QVDRW.js → chunk-J2NYCUTK.js} +24 -24
- package/dist/cli/{chunk-JKVRBCZL.js → chunk-JDMR33HS.js} +1 -0
- package/dist/cli/{chunk-HB2M7RWZ.mjs → chunk-K5USD25Z.mjs} +10 -10
- package/dist/cli/{chunk-6SZNOJSR.js → chunk-KSUGLTX3.js} +6 -6
- package/dist/cli/{chunk-3G4MRUY7.js → chunk-MLQJVAVS.js} +3 -3
- package/dist/cli/{chunk-URGJLSJX.mjs → chunk-MV6HL67R.mjs} +2 -2
- package/dist/cli/{chunk-ZZ3WOBZQ.js → chunk-NBPNYD54.js} +16 -16
- package/dist/cli/{chunk-FAG4DFUC.mjs → chunk-NELMCOWK.mjs} +1 -0
- package/dist/cli/{chunk-ZWZKQBJJ.js → chunk-NLT3CFVJ.js} +2 -2
- package/dist/cli/{chunk-KPFO7CQM.js → chunk-NPJY5QRC.js} +53 -53
- package/dist/cli/{chunk-PAY27R7P.mjs → chunk-OYHCMKZM.mjs} +3 -3
- package/dist/cli/{chunk-T3OOWRPX.mjs → chunk-PVEEGJFN.mjs} +1 -1
- package/dist/cli/{chunk-NWAFIAHT.js → chunk-RUWBAU6V.js} +8 -8
- package/dist/cli/{chunk-2BBBUZVW.js → chunk-RWCTGSD7.js} +3 -3
- package/dist/cli/{chunk-2OFJVQ7L.mjs → chunk-RYGJWMWL.mjs} +1 -1
- package/dist/cli/{chunk-D464JW3N.mjs → chunk-RZHUHL53.mjs} +19 -1
- package/dist/cli/{chunk-4CJLSC6I.mjs → chunk-SIQV6UYG.mjs} +4 -4
- package/dist/cli/{chunk-XXIAG42J.js → chunk-TWRK4NOU.js} +36 -36
- package/dist/cli/{chunk-N6QVWV5R.mjs → chunk-U5RGCQWJ.mjs} +2 -2
- package/dist/cli/{chunk-FVYAEBGO.mjs → chunk-V2WMJXU6.mjs} +6 -2
- package/dist/cli/{chunk-X7MME4NT.js → chunk-VDRGX2XL.js} +5 -5
- package/dist/cli/{chunk-TEYQKQAQ.js → chunk-VGIAOWCD.js} +5 -5
- package/dist/cli/{chunk-CUCH65D3.mjs → chunk-VVY3HGFM.mjs} +2 -2
- package/dist/cli/{chunk-7S33CZMU.js → chunk-WDXJUZCY.js} +2 -2
- package/dist/cli/{chunk-7JY5HB23.js → chunk-YRM5TPXL.js} +8 -8
- package/dist/cli/{chunk-WG3KGAII.js → chunk-Z52WEIBR.js} +19 -1
- package/dist/cli/{chunk-VERY76VG.mjs → chunk-ZAF54BQK.mjs} +1 -1
- package/dist/cli/{chunk-2GMJDL3C.js → chunk-ZHM7VCKH.js} +21 -21
- package/dist/cli/{chunk-DI3K3PJE.mjs → chunk-ZMJOSD7R.mjs} +1 -1
- package/dist/cli/command-docs.js +2 -2
- package/dist/cli/command-docs.mjs +1 -1
- package/dist/cli/{csv-DVAQAKEI.mjs → csv-Q6BSRCBJ.mjs} +4 -4
- package/dist/cli/{csv-RTWPHENL.js → csv-UE7RZDUV.js} +13 -13
- package/dist/cli/{db-OFAOD5AT.mjs → db-FI6XXB2H.mjs} +7 -7
- package/dist/cli/{db-BY4Y6CQ3.js → db-T7A7EE3D.js} +28 -28
- package/dist/cli/{describe-QOO27KPQ.mjs → describe-4GGU6NU3.mjs} +18 -18
- package/dist/cli/describe-UM2VGRY7.js +48 -0
- package/dist/cli/describe-core.d.mts +3 -3
- package/dist/cli/describe-core.d.ts +3 -3
- package/dist/cli/{executions-QHGGAQOE.js → executions-4I6F5RMS.js} +9 -9
- package/dist/cli/{executions-EUHFCB47.mjs → executions-S46XI7NX.mjs} +7 -7
- package/dist/cli/{feedback-47CCLALE.mjs → feedback-3LJ7NZE7.mjs} +4 -4
- package/dist/cli/{feedback-5G4CUZFN.js → feedback-VEGUNKSP.js} +8 -8
- package/dist/cli/git-EVWKNIUA.js +25 -0
- package/dist/cli/{git-5I2AXG4O.mjs → git-W7SFD7AA.mjs} +5 -5
- package/dist/cli/index.js +139 -139
- package/dist/cli/index.mjs +41 -41
- package/dist/cli/{legacy-noops-5OBXYGLC.js → legacy-noops-3EMB5SJH.js} +8 -8
- package/dist/cli/{legacy-noops-AJYRHCWF.mjs → legacy-noops-FIR5PSHG.mjs} +5 -5
- package/dist/cli/{monitors-IWFCIY3H.mjs → monitors-4DKW25PV.mjs} +8 -8
- package/dist/cli/{monitors-5CWZZ7D7.js → monitors-53LPJH6R.js} +92 -92
- package/dist/cli/{org-7EP6FXX6.mjs → org-6ZV2DBGI.mjs} +7 -7
- package/dist/cli/{org-7HCL5RO7.js → org-CYLJFX4Q.js} +73 -73
- package/dist/cli/{pages-GTECAV7A.js → pages-42E3WIMH.js} +18 -18
- package/dist/cli/{pages-UJWA7YNZ.mjs → pages-V3LEXCRL.mjs} +7 -7
- package/dist/cli/{play-MMGWGTTZ.js → play-O3OY556F.js} +556 -516
- package/dist/cli/{play-X3SYW37L.mjs → play-X7REMNNG.mjs} +63 -23
- package/dist/cli/{providers-ZBCQLB5Y.mjs → providers-L2DJVAXN.mjs} +7 -7
- package/dist/cli/{providers-VQL4X4VL.js → providers-NZ7TISS3.js} +10 -10
- package/dist/cli/{quickstart-SIFBA4UU.js → quickstart-IKNGAQRO.js} +6 -6
- package/dist/cli/{quickstart-TIPHHFSA.mjs → quickstart-ROWMAUXQ.mjs} +4 -4
- package/dist/cli/{run-XKSIVFEN.js → run-JG6DLOYR.js} +37 -37
- package/dist/cli/{run-4L6ZW53Z.mjs → run-PJI577J2.mjs} +23 -23
- package/dist/cli/{search-6HLAN32O.mjs → search-DOVJ745X.mjs} +8 -8
- package/dist/cli/search-RHKW5GSR.js +32 -0
- package/dist/cli/{secrets-4HTY4MSI.mjs → secrets-OKDFNCRJ.mjs} +7 -7
- package/dist/cli/{secrets-KYRIVDA6.js → secrets-R5LWXIG6.js} +16 -16
- package/dist/cli/{sessions-JEV4COUF.mjs → sessions-KX4C2CKS.mjs} +5 -5
- package/dist/cli/{sessions-EVKRTCFM.js → sessions-L3DSAY2T.js} +6 -6
- package/dist/cli/{settings-WFZNZVHF.js → settings-NKTNNTAP.js} +79 -79
- package/dist/cli/{settings-QSABRUHQ.mjs → settings-W3SMDBYS.mjs} +12 -12
- package/dist/cli/{setup-JFEGYAMU.js → setup-5WZEXWQR.js} +44 -44
- package/dist/cli/{setup-KG22OTJO.mjs → setup-7KFKKW2W.mjs} +9 -9
- package/dist/cli/skills-UFAABPCQ.js +31 -0
- package/dist/cli/{skills-5XJM7UBQ.mjs → skills-X5TLATOL.mjs} +7 -7
- package/dist/cli/{tools-2AMQKFP4.mjs → tools-27J5EOKO.mjs} +17 -17
- package/dist/cli/tools-IVU3BCIY.js +55 -0
- package/dist/cli/{update-KEN737KZ.mjs → update-EWL477FJ.mjs} +9 -9
- package/dist/cli/update-G7HFHKPG.js +33 -0
- package/dist/cli/{workflow-T622YRL4.js → workflow-GFNGGHJE.js} +18 -18
- package/dist/cli/{workflow-L6Q5H3OO.mjs → workflow-YXR6YMT2.mjs} +8 -8
- package/dist/{client-B3tlWsw7.d.ts → client-DIpVmXcj.d.ts} +1 -1
- package/dist/{client-CdJR18SJ.d.mts → client-DitOgp8N.d.mts} +1 -1
- package/dist/{client-core-ByJD7QXj.d.mts → client-core-COZteOww.d.mts} +28 -2
- package/dist/{client-core-CxHBKfE5.d.ts → client-core-k543Fg6D.d.ts} +28 -2
- package/dist/{compiler-manifest-D5dARg3M.d.ts → compiler-manifest-Zwm9yqOA.d.mts} +39 -0
- package/dist/{compiler-manifest-D5dARg3M.d.mts → compiler-manifest-Zwm9yqOA.d.ts} +39 -0
- package/dist/{errors-BtHHzWL8.d.ts → errors-CsYwlpn4.d.ts} +1 -1
- package/dist/{errors-BveMVPwA.d.mts → errors-nEsqNLL8.d.mts} +1 -1
- package/dist/{index-C6sovoYP.d.ts → index-9pUZqkPH.d.ts} +1 -1
- package/dist/{index-BboApDGD.d.mts → index-CXF2jtza.d.mts} +1 -1
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +10 -10
- package/dist/index.mjs +7 -7
- package/dist/install-integrity.json +112 -112
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +1 -1
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/plays/run-request.js +2 -2
- package/dist/plays/run-request.mjs +1 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/dist/server.d.mts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +6 -6
- package/dist/server.mjs +4 -4
- package/package.json +1 -1
- package/dist/cli/auth-LEYK6ZW7.js +0 -41
- package/dist/cli/describe-FS5CSJTO.js +0 -48
- package/dist/cli/git-IWVY3SXC.js +0 -25
- package/dist/cli/search-2WGVKZ2E.js +0 -32
- package/dist/cli/skills-6DY62DEQ.js +0 -31
- package/dist/cli/tools-ENIGWVGY.js +0 -55
- package/dist/cli/update-XZBBPRDV.js +0 -33
|
@@ -2072,6 +2072,11 @@ export type TargetBillingPlan = {
|
|
|
2072
2072
|
| 'legacy-growth-v1';
|
|
2073
2073
|
name: string;
|
|
2074
2074
|
recurring_price_usd: number;
|
|
2075
|
+
/**
|
|
2076
|
+
* The first month's fee for switching to this plan when a first-month
|
|
2077
|
+
* discount is offered; null or absent means the list price.
|
|
2078
|
+
*/
|
|
2079
|
+
first_month_price_usd?: number | null;
|
|
2075
2080
|
interval: 'month' | 'year';
|
|
2076
2081
|
included_credits: number;
|
|
2077
2082
|
/** Offered benefit terms; omitted by older API deployments. */
|
|
@@ -453,6 +453,7 @@ export function normalizePlayRunStart(
|
|
|
453
453
|
...(runPackage.run.dashboardUrl
|
|
454
454
|
? { dashboardUrl: runPackage.run.dashboardUrl }
|
|
455
455
|
: {}),
|
|
456
|
+
...(runPackage.rateLimited ? { rateLimited: runPackage.rateLimited } : {}),
|
|
456
457
|
...(isTerminalPlayRunLifecycleStatus(status)
|
|
457
458
|
? raw.finalStatusView === 'full' && raw.runId === runPackage.run.id
|
|
458
459
|
? { finalStatus: raw, finalStatusView: 'full' as const }
|
|
@@ -205,7 +205,7 @@ export const SDK_RELEASE = {
|
|
|
205
205
|
// getters keep their established compatibility behavior.
|
|
206
206
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
207
207
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
208
|
-
version: '0.3.
|
|
208
|
+
version: '0.3.471',
|
|
209
209
|
updateSummary: {
|
|
210
210
|
introducedIn: '0.3.90',
|
|
211
211
|
summary:
|
|
@@ -847,6 +847,22 @@ export type PlayRunDatasetActions = {
|
|
|
847
847
|
};
|
|
848
848
|
};
|
|
849
849
|
|
|
850
|
+
/**
|
|
851
|
+
* Present when no run started because the Play's `rateLimit` window is held.
|
|
852
|
+
* The response then describes `latestRunId`, an earlier run, not a new one.
|
|
853
|
+
*/
|
|
854
|
+
export interface PlayRunRateLimited {
|
|
855
|
+
code: 'PLAY_RUN_RATE_LIMITED';
|
|
856
|
+
latestRunId: string;
|
|
857
|
+
/** ISO time the latest run started its window. */
|
|
858
|
+
latestRunStartedAt: string;
|
|
859
|
+
/** ISO time the next run can start. */
|
|
860
|
+
nextAllowedAt: string;
|
|
861
|
+
everySeconds: number;
|
|
862
|
+
/** One-line explanation to show the caller. */
|
|
863
|
+
message: string;
|
|
864
|
+
}
|
|
865
|
+
|
|
850
866
|
/**
|
|
851
867
|
* Compact canonical run package for SDK/CLI consumers: stable metadata,
|
|
852
868
|
* output handles and follow-up actions without dashboard internals.
|
|
@@ -856,6 +872,8 @@ export interface PlayRunPackage {
|
|
|
856
872
|
schemaVersion: 1;
|
|
857
873
|
/** Package discriminator. */
|
|
858
874
|
kind: 'play_run';
|
|
875
|
+
/** Set when this package is the latest run returned instead of a new one. */
|
|
876
|
+
rateLimited?: PlayRunRateLimited;
|
|
859
877
|
/** Retained return structure with dataset references, not flattened output previews. */
|
|
860
878
|
result?: unknown;
|
|
861
879
|
/** Full-only values are omitted as a whole, never replaced with partial authored data. */
|
|
@@ -1266,6 +1284,8 @@ export interface RerunPlayRunResult {
|
|
|
1266
1284
|
* servers.
|
|
1267
1285
|
*/
|
|
1268
1286
|
deduplicated?: boolean;
|
|
1287
|
+
/** Set when no rerun started; `runId` is then the Play's latest run. */
|
|
1288
|
+
rateLimited?: PlayRunRateLimited;
|
|
1269
1289
|
next: { inspect: string; input: string };
|
|
1270
1290
|
}
|
|
1271
1291
|
|
|
@@ -1902,6 +1922,8 @@ export interface PlayRunStart {
|
|
|
1902
1922
|
finalStatusView?: 'full';
|
|
1903
1923
|
/** Canonical compact run package returned by current SDK/API responses. */
|
|
1904
1924
|
package?: PlayRunPackage;
|
|
1925
|
+
/** Set when no run started; `workflowId` is then the Play's latest run. */
|
|
1926
|
+
rateLimited?: PlayRunRateLimited;
|
|
1905
1927
|
}
|
|
1906
1928
|
|
|
1907
1929
|
/**
|
|
@@ -15565,7 +15565,9 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
15565
15565
|
this.steps.push(step);
|
|
15566
15566
|
}
|
|
15567
15567
|
this.log(
|
|
15568
|
-
|
|
15568
|
+
launched.rateLimited
|
|
15569
|
+
? `ctx.runPlayAsync(${normalizedKey}): ${launched.rateLimited.message}`
|
|
15570
|
+
: `ctx.runPlayAsync(${normalizedKey}): admitted ${resolvedName} as ${launched.runId}`,
|
|
15569
15571
|
);
|
|
15570
15572
|
return launched;
|
|
15571
15573
|
}
|
|
@@ -40,6 +40,14 @@ export const PLAY_RUN_LAUNCH_CONFLICT = 'PLAY_RUN_LAUNCH_CONFLICT' as const;
|
|
|
40
40
|
export const PLAY_RUNTIME_CALLBACK_UNCONFIGURED =
|
|
41
41
|
'PLAY_RUNTIME_CALLBACK_UNCONFIGURED' as const;
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* The Play's declared `rateLimit` already started a run in the current
|
|
45
|
+
* window. The source is settled as skipped: no Run, no retry, not a DLQ item.
|
|
46
|
+
*/
|
|
47
|
+
export const PLAY_RUN_RATE_LIMITED = 'PLAY_RUN_RATE_LIMITED' as const;
|
|
48
|
+
|
|
49
|
+
export type PlayAdmissionSkippedCode = typeof PLAY_RUN_RATE_LIMITED;
|
|
50
|
+
|
|
43
51
|
export type PlayAdmissionBlockedCode =
|
|
44
52
|
| typeof PLAY_ADMISSION_PAYLOAD_UNREADABLE
|
|
45
53
|
| typeof PLAY_SECRET_UNAVAILABLE
|
|
@@ -63,6 +71,12 @@ export type PlayAdmissionFailure =
|
|
|
63
71
|
disposition: 'blocked';
|
|
64
72
|
code: PlayAdmissionBlockedCode;
|
|
65
73
|
message: string;
|
|
74
|
+
}
|
|
75
|
+
| {
|
|
76
|
+
/** Settle the source terminally without a Run; nothing to repair or retry. */
|
|
77
|
+
disposition: 'skipped';
|
|
78
|
+
code: PlayAdmissionSkippedCode;
|
|
79
|
+
message: string;
|
|
66
80
|
};
|
|
67
81
|
|
|
68
82
|
const TERMINAL_PRE_ADMISSION_CODES = new Set<PlayAdmissionBlockedCode>([
|
|
@@ -87,18 +101,23 @@ function blocked(code: PlayAdmissionBlockedCode): PlayAdmissionFailure {
|
|
|
87
101
|
};
|
|
88
102
|
}
|
|
89
103
|
|
|
104
|
+
const PLAY_RUN_RATE_LIMITED_MESSAGE =
|
|
105
|
+
"Rate limited: this Play's rateLimit already started a run in the current window, so this delivery started no run. It is not retried.";
|
|
106
|
+
|
|
90
107
|
/**
|
|
91
|
-
* The customer-facing reason for a blocked source. A deferred batch settles by
|
|
108
|
+
* The customer-facing reason for a blocked or skipped source. A deferred batch settles by
|
|
92
109
|
* code alone, so the reason must be derivable from the stable code.
|
|
93
110
|
*/
|
|
94
111
|
export function playAdmissionBlockedMessage(code: string): string {
|
|
95
|
-
return code ===
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
return code === PLAY_RUN_RATE_LIMITED
|
|
113
|
+
? PLAY_RUN_RATE_LIMITED_MESSAGE
|
|
114
|
+
: code === PLAY_SECRET_UNAVAILABLE
|
|
115
|
+
? 'The Play configuration is unavailable. Repair it, then retry this delivery.'
|
|
116
|
+
: code === PLAY_RUN_LAUNCH_CONFLICT
|
|
117
|
+
? 'This run identity is already bound to a different launch. Repair the trigger identity before retrying this delivery.'
|
|
118
|
+
: code === PLAY_RUNTIME_CALLBACK_UNCONFIGURED
|
|
119
|
+
? 'This deployment has no public runtime callback URL, so Play workers cannot report progress. Configure the callback (local dev: start the dev tunnel), then retry this delivery.'
|
|
120
|
+
: 'This delivery needs attention before it can be retried.';
|
|
102
121
|
}
|
|
103
122
|
|
|
104
123
|
/**
|
|
@@ -135,6 +154,13 @@ export function classifyPlayAdmissionFailure(
|
|
|
135
154
|
return blocked(PLAY_SECRET_UNAVAILABLE);
|
|
136
155
|
}
|
|
137
156
|
const code = stableErrorCode(error);
|
|
157
|
+
if (code === PLAY_RUN_RATE_LIMITED) {
|
|
158
|
+
return {
|
|
159
|
+
disposition: 'skipped',
|
|
160
|
+
code,
|
|
161
|
+
message: PLAY_RUN_RATE_LIMITED_MESSAGE,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
138
164
|
if (
|
|
139
165
|
code !== null &&
|
|
140
166
|
TERMINAL_PRE_ADMISSION_CODES.has(code as PlayAdmissionBlockedCode)
|
package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts
CHANGED
|
@@ -21,6 +21,8 @@ import { emitPlayRunLaunchConflictTelemetry } from '../../runtime-telemetry';
|
|
|
21
21
|
export function createPostgresPlayRunAdmissionPorts(input: {
|
|
22
22
|
client: PostgresSchedulerQueryClient;
|
|
23
23
|
schema?: string;
|
|
24
|
+
/** The admitting app will immediately attempt its leased local projection. */
|
|
25
|
+
reserveCreatedProjection?: boolean;
|
|
24
26
|
}): PlayRunAdmissionPorts {
|
|
25
27
|
const options = input.schema ? { schema: input.schema } : undefined;
|
|
26
28
|
return {
|
|
@@ -35,6 +37,7 @@ export function createPostgresPlayRunAdmissionPorts(input: {
|
|
|
35
37
|
options,
|
|
36
38
|
admission.queueName,
|
|
37
39
|
admission.recoverExistingTask === true,
|
|
40
|
+
{ reserveCreatedProjection: input.reserveCreatedProjection },
|
|
38
41
|
);
|
|
39
42
|
} catch (error) {
|
|
40
43
|
if (isLaunchConflict(error)) {
|
|
@@ -453,6 +453,9 @@ export function createAbsurdSchedulerBackend(
|
|
|
453
453
|
createPostgresPlayRunAdmissionPorts({
|
|
454
454
|
client,
|
|
455
455
|
schema: normalizedSchedulerOptions.schema,
|
|
456
|
+
reserveCreatedProjection: Boolean(
|
|
457
|
+
process.env.VERCEL?.trim(),
|
|
458
|
+
),
|
|
456
459
|
}),
|
|
457
460
|
).admit({
|
|
458
461
|
launch: input,
|
|
@@ -5007,6 +5007,7 @@ export async function submitPostgresAbsurdPlayRun(
|
|
|
5007
5007
|
options: Pick<PostgresSchedulerOptions, 'schema'> | undefined,
|
|
5008
5008
|
queueName: string,
|
|
5009
5009
|
recoverExistingTask = false,
|
|
5010
|
+
projection?: { reserveCreatedProjection?: boolean },
|
|
5010
5011
|
): Promise<{
|
|
5011
5012
|
taskId: string | null;
|
|
5012
5013
|
runCreated: boolean;
|
|
@@ -5030,6 +5031,7 @@ export async function submitPostgresAbsurdPlayRun(
|
|
|
5030
5031
|
queueName,
|
|
5031
5032
|
...task,
|
|
5032
5033
|
recoverExistingTask,
|
|
5034
|
+
reserveCreatedProjection: projection?.reserveCreatedProjection === true,
|
|
5033
5035
|
},
|
|
5034
5036
|
);
|
|
5035
5037
|
const taskId = submitted.absurdTaskId;
|
|
@@ -5125,6 +5127,7 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
5125
5127
|
params: unknown;
|
|
5126
5128
|
options: unknown;
|
|
5127
5129
|
recoverExistingTask?: boolean;
|
|
5130
|
+
reserveCreatedProjection?: boolean;
|
|
5128
5131
|
},
|
|
5129
5132
|
/**
|
|
5130
5133
|
* Set only on the single re-admission after the current build proved the
|
|
@@ -5138,6 +5141,11 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
5138
5141
|
taskRecoveryRequired: boolean;
|
|
5139
5142
|
}> {
|
|
5140
5143
|
const requestedInput = input;
|
|
5144
|
+
const createdProjectionLease =
|
|
5145
|
+
absurdTask?.reserveCreatedProjection === true &&
|
|
5146
|
+
input.requiresRunCreatedProjection === true
|
|
5147
|
+
? postgresSchedulerInlineCreatedProjectionLease(input.runId)
|
|
5148
|
+
: null;
|
|
5141
5149
|
// Persist the ABI with every new launch. Null is reserved for genuinely
|
|
5142
5150
|
// historic rows already in storage, where readers interpret it as legacy.
|
|
5143
5151
|
input = {
|
|
@@ -5445,7 +5453,8 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
5445
5453
|
-- durable run, its task, and the launch envelope together. Persist the
|
|
5446
5454
|
-- causal run.created fact here; projection is deliberately async.
|
|
5447
5455
|
INSERT INTO ${tableName('outbox', options)} (
|
|
5448
|
-
event_id, run_id, event_type, payload_json, created_at
|
|
5456
|
+
event_id, run_id, event_type, payload_json, created_at,
|
|
5457
|
+
lease_owner, lease_expires_at
|
|
5449
5458
|
)
|
|
5450
5459
|
SELECT
|
|
5451
5460
|
'run-created:' || run_insert.run_id,
|
|
@@ -5498,7 +5507,9 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
5498
5507
|
)) || CASE WHEN launch_payload.launch_json ? 'retainedPipelineGraph'
|
|
5499
5508
|
THEN jsonb_build_object('retainedPipelineGraph', launch_payload.launch_json -> 'retainedPipelineGraph')
|
|
5500
5509
|
ELSE '{}'::jsonb END,
|
|
5501
|
-
${causalOutboxCreatedAt('run_insert.run_id', options)}
|
|
5510
|
+
${causalOutboxCreatedAt('run_insert.run_id', options)},
|
|
5511
|
+
${createdProjectionLease ? escapeLiteral(createdProjectionLease.leaseOwner) : 'NULL::text'},
|
|
5512
|
+
${createdProjectionLease ? `now() + interval '${createdProjectionLease.leaseSeconds} seconds'` : 'NULL::timestamptz'}
|
|
5502
5513
|
FROM run_insert
|
|
5503
5514
|
CROSS JOIN launch_payload
|
|
5504
5515
|
-- Old Vercel launchers do not carry the immutable admission envelope.
|
|
@@ -6319,6 +6330,32 @@ function cronOccurrenceLaunch(input: {
|
|
|
6319
6330
|
});
|
|
6320
6331
|
}
|
|
6321
6332
|
|
|
6333
|
+
function cronSuccessorDueAtMs(schedule: PostgresSchedulerCronSchedule): number {
|
|
6334
|
+
let successorDueAtMs: number;
|
|
6335
|
+
try {
|
|
6336
|
+
successorDueAtMs = advanceWorkflowCronSchedule(
|
|
6337
|
+
schedule.cron,
|
|
6338
|
+
Math.max(Date.now(), schedule.dueAtMs),
|
|
6339
|
+
schedule.timezone,
|
|
6340
|
+
);
|
|
6341
|
+
} catch (error) {
|
|
6342
|
+
throw new PostgresSchedulerCronScheduleConfigurationError(
|
|
6343
|
+
`Cron schedule "${schedule.scheduleId}" has an invalid pinned expression or timezone: ${
|
|
6344
|
+
error instanceof Error ? error.message : String(error)
|
|
6345
|
+
}`,
|
|
6346
|
+
);
|
|
6347
|
+
}
|
|
6348
|
+
if (
|
|
6349
|
+
!Number.isSafeInteger(successorDueAtMs) ||
|
|
6350
|
+
successorDueAtMs <= schedule.dueAtMs
|
|
6351
|
+
) {
|
|
6352
|
+
throw new PostgresSchedulerCronScheduleConfigurationError(
|
|
6353
|
+
`Cron schedule "${schedule.scheduleId}" did not produce a future successor occurrence.`,
|
|
6354
|
+
);
|
|
6355
|
+
}
|
|
6356
|
+
return successorDueAtMs;
|
|
6357
|
+
}
|
|
6358
|
+
|
|
6322
6359
|
export type FirePostgresSchedulerCronScheduleInput = {
|
|
6323
6360
|
scheduleId: string;
|
|
6324
6361
|
generation: number;
|
|
@@ -6377,28 +6414,7 @@ export async function firePostgresSchedulerCronSchedule(
|
|
|
6377
6414
|
) {
|
|
6378
6415
|
return { status: 'superseded' };
|
|
6379
6416
|
}
|
|
6380
|
-
|
|
6381
|
-
try {
|
|
6382
|
-
successorDueAtMs = advanceWorkflowCronSchedule(
|
|
6383
|
-
schedule.cron,
|
|
6384
|
-
Math.max(Date.now(), schedule.dueAtMs),
|
|
6385
|
-
schedule.timezone,
|
|
6386
|
-
);
|
|
6387
|
-
} catch (error) {
|
|
6388
|
-
throw new PostgresSchedulerCronScheduleConfigurationError(
|
|
6389
|
-
`Cron schedule "${schedule.scheduleId}" has an invalid pinned expression or timezone: ${
|
|
6390
|
-
error instanceof Error ? error.message : String(error)
|
|
6391
|
-
}`,
|
|
6392
|
-
);
|
|
6393
|
-
}
|
|
6394
|
-
if (
|
|
6395
|
-
!Number.isSafeInteger(successorDueAtMs) ||
|
|
6396
|
-
successorDueAtMs <= schedule.dueAtMs
|
|
6397
|
-
) {
|
|
6398
|
-
throw new PostgresSchedulerCronScheduleConfigurationError(
|
|
6399
|
-
`Cron schedule "${schedule.scheduleId}" did not produce a future successor occurrence.`,
|
|
6400
|
-
);
|
|
6401
|
-
}
|
|
6417
|
+
const successorDueAtMs = cronSuccessorDueAtMs(schedule);
|
|
6402
6418
|
const launch = cronOccurrenceLaunch({
|
|
6403
6419
|
schedule,
|
|
6404
6420
|
launch: input.launch,
|
|
@@ -6713,6 +6729,110 @@ export async function firePostgresSchedulerCronSchedule(
|
|
|
6713
6729
|
return { status: 'superseded' };
|
|
6714
6730
|
}
|
|
6715
6731
|
|
|
6732
|
+
/**
|
|
6733
|
+
* Advance a cron cursor past an occurrence that deliberately starts no Run (a
|
|
6734
|
+
* Play's `rateLimit` window is held). Under the same schedule lock and fences
|
|
6735
|
+
* as `firePostgresSchedulerCronSchedule`, it spawns only the successor timer,
|
|
6736
|
+
* so the schedule keeps ticking. A replay after commit is `superseded`.
|
|
6737
|
+
*/
|
|
6738
|
+
export async function skipPostgresSchedulerCronOccurrence(
|
|
6739
|
+
client: PostgresSchedulerQueryClient,
|
|
6740
|
+
input: Pick<
|
|
6741
|
+
FirePostgresSchedulerCronScheduleInput,
|
|
6742
|
+
'scheduleId' | 'generation' | 'fireGeneration' | 'dueAtMs' | 'queueName'
|
|
6743
|
+
>,
|
|
6744
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
6745
|
+
): Promise<
|
|
6746
|
+
{ status: 'skipped'; successorDueAtMs: number } | { status: 'superseded' }
|
|
6747
|
+
> {
|
|
6748
|
+
assertPostgresSchedulerCronScheduleInput(input);
|
|
6749
|
+
const schedule = await readPostgresSchedulerCronSchedule(
|
|
6750
|
+
client,
|
|
6751
|
+
input.scheduleId,
|
|
6752
|
+
options,
|
|
6753
|
+
);
|
|
6754
|
+
if (
|
|
6755
|
+
!schedule ||
|
|
6756
|
+
schedule.state !== 'active' ||
|
|
6757
|
+
schedule.generation !== input.generation ||
|
|
6758
|
+
schedule.dueAtMs !== input.dueAtMs ||
|
|
6759
|
+
schedule.currentFireGeneration !== input.fireGeneration
|
|
6760
|
+
) {
|
|
6761
|
+
return { status: 'superseded' };
|
|
6762
|
+
}
|
|
6763
|
+
const successorDueAtMs = cronSuccessorDueAtMs(schedule);
|
|
6764
|
+
const successorTask = buildAbsurdCronFireTask({
|
|
6765
|
+
scheduleId: schedule.scheduleId,
|
|
6766
|
+
generation: schedule.generation,
|
|
6767
|
+
fireGeneration: 1,
|
|
6768
|
+
dueAtMs: successorDueAtMs,
|
|
6769
|
+
schedulerSchema:
|
|
6770
|
+
options?.schema ?? schedule.sourcePin.schedulerSchema ?? null,
|
|
6771
|
+
orgId: schedule.sourcePin.orgId,
|
|
6772
|
+
});
|
|
6773
|
+
const result = await client.query<{ advanced: boolean }>(
|
|
6774
|
+
`
|
|
6775
|
+
WITH schedule_lock AS MATERIALIZED (
|
|
6776
|
+
SELECT pg_advisory_xact_lock(
|
|
6777
|
+
${POSTGRES_SCHEDULER_RELEASE_ADMISSION_LOCK_NAMESPACE},
|
|
6778
|
+
${quoteIdent(schemaName(options))}.runtime_release_admission_lock_id(
|
|
6779
|
+
'cron-schedule:' || $1::text
|
|
6780
|
+
)
|
|
6781
|
+
)
|
|
6782
|
+
), matching_schedule AS MATERIALIZED (
|
|
6783
|
+
SELECT schedule.schedule_id
|
|
6784
|
+
FROM schedule_lock
|
|
6785
|
+
JOIN ${tableName(POSTGRES_SCHEDULER_CRON_SCHEDULES_TABLE, options)} AS schedule
|
|
6786
|
+
ON schedule.schedule_id = $1::text
|
|
6787
|
+
WHERE schedule.generation = $2::bigint
|
|
6788
|
+
AND schedule.state = 'active'
|
|
6789
|
+
AND schedule.current_due_at = to_timestamp($3::double precision / 1000.0)
|
|
6790
|
+
AND schedule.current_fire_generation = $4::bigint
|
|
6791
|
+
FOR UPDATE
|
|
6792
|
+
), successor_task_spawn AS MATERIALIZED (
|
|
6793
|
+
SELECT spawned.task_id::text AS task_id
|
|
6794
|
+
FROM matching_schedule
|
|
6795
|
+
CROSS JOIN LATERAL absurd.spawn_task(
|
|
6796
|
+
$6::text,
|
|
6797
|
+
$7::text,
|
|
6798
|
+
$8::jsonb,
|
|
6799
|
+
$9::jsonb
|
|
6800
|
+
) AS spawned
|
|
6801
|
+
), schedule_advance AS (
|
|
6802
|
+
UPDATE ${tableName(POSTGRES_SCHEDULER_CRON_SCHEDULES_TABLE, options)} AS schedule
|
|
6803
|
+
SET current_due_at = to_timestamp($5::double precision / 1000.0),
|
|
6804
|
+
current_fire_task_id = (SELECT task_id FROM successor_task_spawn),
|
|
6805
|
+
current_fire_generation = 1,
|
|
6806
|
+
current_fire_queue_name = $6::text,
|
|
6807
|
+
last_fired_at = clock_timestamp(),
|
|
6808
|
+
updated_at = now()
|
|
6809
|
+
WHERE schedule.schedule_id = $1::text
|
|
6810
|
+
AND schedule.generation = $2::bigint
|
|
6811
|
+
AND schedule.state = 'active'
|
|
6812
|
+
AND schedule.current_due_at = to_timestamp($3::double precision / 1000.0)
|
|
6813
|
+
AND schedule.current_fire_generation = $4::bigint
|
|
6814
|
+
AND EXISTS (SELECT 1 FROM successor_task_spawn)
|
|
6815
|
+
RETURNING schedule.schedule_id
|
|
6816
|
+
)
|
|
6817
|
+
SELECT EXISTS (SELECT 1 FROM schedule_advance) AS advanced
|
|
6818
|
+
`,
|
|
6819
|
+
[
|
|
6820
|
+
schedule.scheduleId,
|
|
6821
|
+
schedule.generation,
|
|
6822
|
+
schedule.dueAtMs,
|
|
6823
|
+
schedule.currentFireGeneration,
|
|
6824
|
+
successorDueAtMs,
|
|
6825
|
+
input.queueName,
|
|
6826
|
+
successorTask.taskName,
|
|
6827
|
+
stringifyPostgresJson(successorTask.params),
|
|
6828
|
+
stringifyPostgresJson(successorTask.options),
|
|
6829
|
+
],
|
|
6830
|
+
);
|
|
6831
|
+
return result.rows[0]?.advanced === true
|
|
6832
|
+
? { status: 'skipped', successorDueAtMs }
|
|
6833
|
+
: { status: 'superseded' };
|
|
6834
|
+
}
|
|
6835
|
+
|
|
6716
6836
|
/** Fence a malformed/invalid timer so it cannot repeatedly consume workers. */
|
|
6717
6837
|
export async function blockPostgresSchedulerCronSchedule(
|
|
6718
6838
|
client: PostgresSchedulerQueryClient,
|
|
@@ -22182,6 +22302,29 @@ export function postgresSchedulerCancellationOutboxLease(runId: string): {
|
|
|
22182
22302
|
};
|
|
22183
22303
|
}
|
|
22184
22304
|
|
|
22305
|
+
/**
|
|
22306
|
+
* The admitting app can project its own run.created without an HTTP round trip.
|
|
22307
|
+
* Reserve that first delivery in the admission commit, before NOTIFY lets the
|
|
22308
|
+
* remote projector race it. An app lost before delivery leaves at most this
|
|
22309
|
+
* short lease; ordinary inline claims retain their existing deadline/release.
|
|
22310
|
+
* This is delivery ownership only, never execution admission or authority.
|
|
22311
|
+
*/
|
|
22312
|
+
export function postgresSchedulerInlineCreatedProjectionLease(runId: string): {
|
|
22313
|
+
leaseOwner: string;
|
|
22314
|
+
leaseSeconds: number;
|
|
22315
|
+
} {
|
|
22316
|
+
const normalizedRunId = runId.trim();
|
|
22317
|
+
if (!normalizedRunId) {
|
|
22318
|
+
throw new Error('Inline created projection requires a run id.');
|
|
22319
|
+
}
|
|
22320
|
+
return {
|
|
22321
|
+
leaseOwner: `run-created-inline:${createHash('sha256')
|
|
22322
|
+
.update(normalizedRunId)
|
|
22323
|
+
.digest('hex')}`,
|
|
22324
|
+
leaseSeconds: 2,
|
|
22325
|
+
};
|
|
22326
|
+
}
|
|
22327
|
+
|
|
22185
22328
|
export type RunLedgerOutboxDispatchInput = {
|
|
22186
22329
|
/** App-owned transport; launch authority and routing still come from the lease. */
|
|
22187
22330
|
appRuntimeFetch?: typeof fetch;
|
|
@@ -22842,14 +22985,12 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
22842
22985
|
// The caller's deadline elapsed while this checkout was queued. Its
|
|
22843
22986
|
// attempt is already abandoned, so taking a lease now could only keep
|
|
22844
22987
|
// the durable projector off the row until that lease expires. Claim
|
|
22845
|
-
// nothing
|
|
22846
|
-
if (
|
|
22847
|
-
//
|
|
22848
|
-
//
|
|
22849
|
-
//
|
|
22850
|
-
//
|
|
22851
|
-
// back invocation it matches no row. A failure propagates, so the
|
|
22852
|
-
// attempt is never reported as settled.
|
|
22988
|
+
// nothing, and hand back any initial reservation of the named head.
|
|
22989
|
+
if (abandonedHeadEventId) {
|
|
22990
|
+
// Admission may already have reserved this head, even on the first
|
|
22991
|
+
// checkout. A retried checkout can also follow an ambiguous COMMIT.
|
|
22992
|
+
// Release only this owner's lease; an absent or replaced owner is a
|
|
22993
|
+
// no-op. Failure propagates so the attempt cannot report settlement.
|
|
22853
22994
|
await releasePostgresSchedulerOutboxLease(
|
|
22854
22995
|
client,
|
|
22855
22996
|
[abandonedHeadEventId],
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
postgresSchedulerNotifyChannel,
|
|
15
15
|
readPostgresSchedulerOutboxAdmissionHints,
|
|
16
16
|
readPostgresSchedulerOutboxNextDueAt,
|
|
17
|
+
postgresSchedulerInlineCreatedProjectionLease,
|
|
17
18
|
type PostgresSchedulerOptions,
|
|
18
19
|
type PostgresSchedulerOutboxProjectionResult,
|
|
19
20
|
type RunLedgerOutboxDeliveredRow,
|
|
@@ -1060,6 +1061,8 @@ export async function deliverRunCreatedOutboxEventInline(input: {
|
|
|
1060
1061
|
{
|
|
1061
1062
|
runId,
|
|
1062
1063
|
headEventId: `run-created:${runId}`,
|
|
1064
|
+
leaseOwner:
|
|
1065
|
+
postgresSchedulerInlineCreatedProjectionLease(runId).leaseOwner,
|
|
1063
1066
|
limit: 1,
|
|
1064
1067
|
leaseSeconds: RUN_CREATED_INLINE_DELIVERY_LEASE_SECONDS,
|
|
1065
1068
|
tokenAuthority: input.tokenAuthority,
|
|
@@ -795,6 +795,7 @@ export const PLAY_AUTHORING_BINDING_FIELDS = {
|
|
|
795
795
|
'compatibility',
|
|
796
796
|
'cron',
|
|
797
797
|
'inline',
|
|
798
|
+
'rateLimit',
|
|
798
799
|
'runtime',
|
|
799
800
|
'secrets',
|
|
800
801
|
'sqlListeners',
|
|
@@ -864,6 +865,14 @@ export type PlayAuthoringBindings<TInput = Record<string, unknown>> = {
|
|
|
864
865
|
timeout?: string;
|
|
865
866
|
size?: 'standard';
|
|
866
867
|
};
|
|
868
|
+
/**
|
|
869
|
+
* Start at most one run of this Play per window, whatever started it.
|
|
870
|
+
* Inside the window a caller gets the latest run, marked rate limited;
|
|
871
|
+
* webhook, cron, and listener starts are skipped and never retried.
|
|
872
|
+
*/
|
|
873
|
+
rateLimit?: {
|
|
874
|
+
every: string;
|
|
875
|
+
};
|
|
867
876
|
webhook?: {
|
|
868
877
|
hmac?: {
|
|
869
878
|
algorithm?: 'sha256';
|
|
@@ -1291,6 +1300,11 @@ export type PlayRunId = string & {
|
|
|
1291
1300
|
*/
|
|
1292
1301
|
export type AsyncPlayRunRef = Readonly<{
|
|
1293
1302
|
runId: PlayRunId;
|
|
1303
|
+
/**
|
|
1304
|
+
* Set when the child's `rateLimit` window was held: no child started and
|
|
1305
|
+
* `runId` is that Play's latest run.
|
|
1306
|
+
*/
|
|
1307
|
+
rateLimited?: { latestRunId: string; nextAllowedAt: string; message: string };
|
|
1294
1308
|
}>;
|
|
1295
1309
|
|
|
1296
1310
|
export type PlayAuthoringAsyncCallOptions = Readonly<{
|
|
@@ -2934,6 +2948,24 @@ export const PLAY_AUTHORING_FIELD_REGISTRY = {
|
|
|
2934
2948
|
errorMessage:
|
|
2935
2949
|
'runtime.timeout must be a static duration such as "90m" or "2h".',
|
|
2936
2950
|
},
|
|
2951
|
+
'rateLimit.every': {
|
|
2952
|
+
schema: Type.String({ pattern: '^\\d+\\s*[smh]$' }),
|
|
2953
|
+
fixtures: {
|
|
2954
|
+
valid: '5m',
|
|
2955
|
+
invalid: '5 minutes',
|
|
2956
|
+
absent: undefined,
|
|
2957
|
+
unresolved: { expression: 'every' },
|
|
2958
|
+
edition1: '5m',
|
|
2959
|
+
},
|
|
2960
|
+
referenceType: 'string',
|
|
2961
|
+
required: false,
|
|
2962
|
+
resolution: 'static-required',
|
|
2963
|
+
issueCode: 'play_authoring_binding_invalid',
|
|
2964
|
+
description:
|
|
2965
|
+
'Start at most one run per window, such as 30s, 5m, or 1h (10s to 24h).',
|
|
2966
|
+
errorMessage:
|
|
2967
|
+
'rateLimit.every must be a static duration from "10s" to "24h", such as "5m".',
|
|
2968
|
+
},
|
|
2937
2969
|
'runtime.size': {
|
|
2938
2970
|
schema: Type.Literal('standard'),
|
|
2939
2971
|
fixtures: {
|
|
@@ -3251,6 +3283,8 @@ export type AdmittedPlayAuthoringContract = {
|
|
|
3251
3283
|
bindings: PlayAuthoringBindingsSnapshot | null;
|
|
3252
3284
|
billingLimit: { maxCreditsPerRun: number } | null;
|
|
3253
3285
|
runtimeLimit: PlaySandboxRuntimeLimits;
|
|
3286
|
+
/** Absent on artifacts admitted before `rateLimit` existed: unlimited. */
|
|
3287
|
+
rateLimit?: { everySeconds: number };
|
|
3254
3288
|
allowedSecrets: string[];
|
|
3255
3289
|
};
|
|
3256
3290
|
|
|
@@ -3396,6 +3430,7 @@ export const PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
|
|
|
3396
3430
|
` inline?: ${cloudReferenceType('inline')};`,
|
|
3397
3431
|
` billing?: { maxCreditsPerRun?: ${cloudReferenceType('billing.maxCreditsPerRun')} };`,
|
|
3398
3432
|
` runtime?: { timeout?: ${cloudReferenceType('runtime.timeout')}; size?: ${cloudReferenceType('runtime.size')} };`,
|
|
3433
|
+
` rateLimit?: { every: ${cloudReferenceType('rateLimit.every')} };`,
|
|
3399
3434
|
` webhook?: { hmac?: { algorithm?: ${cloudReferenceType('bindings.webhook.hmac.algorithm')}; header?: ${cloudReferenceType('bindings.webhook.hmac.header')}; signaturePrefix?: ${cloudReferenceType('bindings.webhook.hmac.signaturePrefix')}; secretEnv: ${cloudReferenceType('bindings.webhook.hmac.secretEnv')} }; auth?: { type: ${cloudReferenceType('bindings.webhook.auth.type')}; headerFamily: ${cloudReferenceType('bindings.webhook.auth.headerFamily')}; signingSecrets: readonly ${cloudReferenceType('bindings.webhook.auth.signingSecrets[]')}[]; toleranceSeconds?: ${cloudReferenceType('bindings.webhook.auth.toleranceSeconds')} } };`,
|
|
3400
3435
|
` cron?: { schedule: ${cloudReferenceType('bindings.cron.schedule')}; timezone?: ${cloudReferenceType('bindings.cron.timezone')}; input?: PlayCronInput<TInput> };`,
|
|
3401
3436
|
' sqlListeners?: readonly SqlListenerDeclaration[];',
|
|
@@ -3420,7 +3455,7 @@ export const PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
|
|
|
3420
3455
|
`export type PlayAsyncCallOptions = { description: ${cloudReferenceType('ctx.runPlayAsync.options.description')} };`,
|
|
3421
3456
|
'declare const PLAY_RUN_ID_BRAND: unique symbol;',
|
|
3422
3457
|
"export type PlayRunId = string & { readonly [PLAY_RUN_ID_BRAND]: 'PlayRunId' };",
|
|
3423
|
-
'export type AsyncPlayRunRef = Readonly<{ runId: PlayRunId }>;',
|
|
3458
|
+
'export type AsyncPlayRunRef = Readonly<{ runId: PlayRunId; rateLimited?: { latestRunId: string; nextAllowedAt: string; message: string } }>;',
|
|
3424
3459
|
`export type RuntimeStepOptions = { semanticKey?: ${cloudReferenceType('ctx.step.semanticKey')}; staleAfterSeconds?: ${cloudReferenceType('ctx.step.staleAfterSeconds')} };`,
|
|
3425
3460
|
`export type FetchOptions = { staleAfterSeconds?: ${cloudReferenceType('ctx.fetch.staleAfterSeconds')}; transient?: boolean };`,
|
|
3426
3461
|
"export type CallFreshnessMetadata = { requestedStaleAfterSeconds: number | null; effectiveStaleAfterSeconds: number | null; source: 'executed' | 'operation_recovery' | 'reusable_result' | 'live_observation'; resultAgeMs: number; completedAt: number; operationReceiptKey?: string; unavailableReason?: string };",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var _chunkCR2F3JZNjs = require('./chunk-CR2F3JZN.js');
|
|
17
|
+
require('./chunk-YRM5TPXL.js');
|
|
18
|
+
require('./chunk-MLQJVAVS.js');
|
|
19
|
+
require('./chunk-DK5Y5BD3.js');
|
|
20
|
+
require('./chunk-ALJJRZNJ.js');
|
|
21
|
+
require('./chunk-XNYIZMNQ.js');
|
|
22
|
+
require('./chunk-DIAWYWT5.js');
|
|
23
|
+
require('./chunk-G6RQXAJ2.js');
|
|
24
|
+
require('./chunk-OG64RBAC.js');
|
|
25
|
+
require('./chunk-COGTRVWW.js');
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
exports.EXIT_WORKSPACE_MISMATCH = _chunkCR2F3JZNjs.EXIT_WORKSPACE_MISMATCH; exports.authStatusLine = _chunkCR2F3JZNjs.authStatusLine; exports.clearPendingClaim = _chunkCR2F3JZNjs.clearPendingClaim; exports.clearSatisfiedPendingClaim = _chunkCR2F3JZNjs.clearSatisfiedPendingClaim; exports.handleRegister = _chunkCR2F3JZNjs.handleRegister; exports.handleStatus = _chunkCR2F3JZNjs.handleStatus; exports.handleWait = _chunkCR2F3JZNjs.handleWait; exports.httpJson = _chunkCR2F3JZNjs.httpJson; exports.readPendingAuthClaim = _chunkCR2F3JZNjs.readPendingAuthClaim; exports.readStatusBanner = _chunkCR2F3JZNjs.readStatusBanner; exports.registerAuthCommands = _chunkCR2F3JZNjs.registerAuthCommands; exports.reportSetupCompleted = _chunkCR2F3JZNjs.reportSetupCompleted; exports.resolvePendingAuthClaimForResume = _chunkCR2F3JZNjs.resolvePendingAuthClaimForResume; exports.statusBannerLine = _chunkCR2F3JZNjs.statusBannerLine;
|
|
@@ -13,14 +13,14 @@ import {
|
|
|
13
13
|
reportSetupCompleted,
|
|
14
14
|
resolvePendingAuthClaimForResume,
|
|
15
15
|
statusBannerLine
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-2KBRY5CA.mjs";
|
|
17
|
+
import "./chunk-OYHCMKZM.mjs";
|
|
18
|
+
import "./chunk-FVGT5EBA.mjs";
|
|
19
|
+
import "./chunk-ZMJOSD7R.mjs";
|
|
20
20
|
import "./chunk-4QF2K7TM.mjs";
|
|
21
21
|
import "./chunk-DLIRSHV6.mjs";
|
|
22
22
|
import "./chunk-HBL4PM5Q.mjs";
|
|
23
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-3PT2HJKC.mjs";
|
|
24
24
|
import "./chunk-WZYKRD7T.mjs";
|
|
25
25
|
import "./chunk-KRD6H754.mjs";
|
|
26
26
|
export {
|