windmill-client 1.804.0 → 1.806.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +47 -1
- package/dist/client.mjs +128 -44
- package/dist/core/OpenAPI.mjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +307 -47
- package/dist/services.gen.d.ts +103 -3
- package/dist/services.gen.mjs +178 -2
- package/dist/types.gen.d.ts +384 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -126,7 +126,7 @@ const OpenAPI = {
|
|
|
126
126
|
PASSWORD: void 0,
|
|
127
127
|
TOKEN: getEnv$1("WM_TOKEN"),
|
|
128
128
|
USERNAME: void 0,
|
|
129
|
-
VERSION: "1.
|
|
129
|
+
VERSION: "1.806.0",
|
|
130
130
|
WITH_CREDENTIALS: !getEnv$1("WM_RAW_APP"),
|
|
131
131
|
interceptors: {
|
|
132
132
|
request: new Interceptors(),
|
|
@@ -1655,6 +1655,59 @@ var GitSyncService = class {
|
|
|
1655
1655
|
});
|
|
1656
1656
|
}
|
|
1657
1657
|
/**
|
|
1658
|
+
* List the GitLab projects a token can sync
|
|
1659
|
+
* Lists the projects the supplied GitLab token can push to, so a git repository resource can be filled in without hand-writing a project path. The token is used for this call only and is never stored. Requires workspace admin.
|
|
1660
|
+
* @param data The data for the request.
|
|
1661
|
+
* @param data.workspace
|
|
1662
|
+
* @param data.requestBody
|
|
1663
|
+
* @returns GitlabProject the projects the token can sync
|
|
1664
|
+
* @throws ApiError
|
|
1665
|
+
*/
|
|
1666
|
+
static listGitlabProjects(data) {
|
|
1667
|
+
return request(OpenAPI, {
|
|
1668
|
+
method: "POST",
|
|
1669
|
+
url: "/w/{workspace}/git_sync/gitlab/projects",
|
|
1670
|
+
path: { workspace: data.workspace },
|
|
1671
|
+
body: data.requestBody,
|
|
1672
|
+
mediaType: "application/json"
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* Where a repository's credential comes from
|
|
1677
|
+
* Whether Windmill holds this repository's access token, and which host it talks to. `held` means this workspace stores it, `borrowed` means an ancestor does and it is not this workspace's to replace. Both absent means the repository authenticates with whatever its URL carries. Returns no secret. Requires workspace admin.
|
|
1678
|
+
* @param data The data for the request.
|
|
1679
|
+
* @param data.workspace
|
|
1680
|
+
* @param data.path Path of the git repository resource, with or without the `$res:` prefix. A path rather than a URL, because a resource URL may carry a token and a URL in a query string lands in logs.
|
|
1681
|
+
* @returns unknown where the credential comes from
|
|
1682
|
+
* @throws ApiError
|
|
1683
|
+
*/
|
|
1684
|
+
static getCredentialOrigin(data) {
|
|
1685
|
+
return request(OpenAPI, {
|
|
1686
|
+
method: "GET",
|
|
1687
|
+
url: "/w/{workspace}/git_sync/credential/origin",
|
|
1688
|
+
path: { workspace: data.workspace },
|
|
1689
|
+
query: { path: data.path }
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Store the credential for a git repository
|
|
1694
|
+
* Stores the access token a git repository authenticates with, so it does not have to be written into the repository URL or a workspace variable. The token is write-only: it is served only to a git-sync job that presents its own job token, and a fork of this workspace reads this copy instead of holding one of its own. Requires workspace admin.
|
|
1695
|
+
* @param data The data for the request.
|
|
1696
|
+
* @param data.workspace
|
|
1697
|
+
* @param data.requestBody
|
|
1698
|
+
* @returns string the credential was stored
|
|
1699
|
+
* @throws ApiError
|
|
1700
|
+
*/
|
|
1701
|
+
static setGitCredential(data) {
|
|
1702
|
+
return request(OpenAPI, {
|
|
1703
|
+
method: "POST",
|
|
1704
|
+
url: "/w/{workspace}/git_sync/credential",
|
|
1705
|
+
path: { workspace: data.workspace },
|
|
1706
|
+
body: data.requestBody,
|
|
1707
|
+
mediaType: "application/json"
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
/**
|
|
1658
1711
|
* GHES installation callback
|
|
1659
1712
|
* Register a self-managed GitHub App installation from GitHub Enterprise Server
|
|
1660
1713
|
* @param data The data for the request.
|
|
@@ -1950,11 +2003,11 @@ var WorkspaceService = class {
|
|
|
1950
2003
|
});
|
|
1951
2004
|
}
|
|
1952
2005
|
/**
|
|
1953
|
-
* get
|
|
2006
|
+
* get the git credential for a git-sync job (GitHub App token, or the credential stored for the repository)
|
|
1954
2007
|
* @param data The data for the request.
|
|
1955
2008
|
* @param data.workspace
|
|
1956
2009
|
* @param data.requestBody jwt job token
|
|
1957
|
-
* @returns unknown
|
|
2010
|
+
* @returns unknown git credential
|
|
1958
2011
|
* @throws ApiError
|
|
1959
2012
|
*/
|
|
1960
2013
|
static getGithubAppToken(data) {
|
|
@@ -5677,6 +5730,52 @@ var ResourceService = class {
|
|
|
5677
5730
|
});
|
|
5678
5731
|
}
|
|
5679
5732
|
/**
|
|
5733
|
+
* count the workspace's resources per resource type
|
|
5734
|
+
* @param data The data for the request.
|
|
5735
|
+
* @param data.workspace
|
|
5736
|
+
* @returns unknown resource count per resource_type
|
|
5737
|
+
* @throws ApiError
|
|
5738
|
+
*/
|
|
5739
|
+
static listResourceCountsByType(data) {
|
|
5740
|
+
return request(OpenAPI, {
|
|
5741
|
+
method: "GET",
|
|
5742
|
+
url: "/w/{workspace}/resources/type/resource_counts",
|
|
5743
|
+
path: { workspace: data.workspace }
|
|
5744
|
+
});
|
|
5745
|
+
}
|
|
5746
|
+
/**
|
|
5747
|
+
* list what the hub knows about its resource types
|
|
5748
|
+
* @param data The data for the request.
|
|
5749
|
+
* @param data.workspace
|
|
5750
|
+
* @returns unknown each hub resource type with its integration and pick count, empty if the hub answers neither read
|
|
5751
|
+
* @throws ApiError
|
|
5752
|
+
*/
|
|
5753
|
+
static listHubResourceTypeInfo(data) {
|
|
5754
|
+
return request(OpenAPI, {
|
|
5755
|
+
method: "GET",
|
|
5756
|
+
url: "/w/{workspace}/resources/type/hub/info",
|
|
5757
|
+
path: { workspace: data.workspace }
|
|
5758
|
+
});
|
|
5759
|
+
}
|
|
5760
|
+
/**
|
|
5761
|
+
* record a hub resource type pick
|
|
5762
|
+
* @param data The data for the request.
|
|
5763
|
+
* @param data.workspace
|
|
5764
|
+
* @param data.name
|
|
5765
|
+
* @returns unknown whether the hub recorded the pick
|
|
5766
|
+
* @throws ApiError
|
|
5767
|
+
*/
|
|
5768
|
+
static pickHubResourceType(data) {
|
|
5769
|
+
return request(OpenAPI, {
|
|
5770
|
+
method: "POST",
|
|
5771
|
+
url: "/w/{workspace}/resources/type/hub/pick/{name}",
|
|
5772
|
+
path: {
|
|
5773
|
+
workspace: data.workspace,
|
|
5774
|
+
name: data.name
|
|
5775
|
+
}
|
|
5776
|
+
});
|
|
5777
|
+
}
|
|
5778
|
+
/**
|
|
5680
5779
|
* query resource types by similarity
|
|
5681
5780
|
* @param data The data for the request.
|
|
5682
5781
|
* @param data.workspace
|
|
@@ -11013,6 +11112,29 @@ var JobService = class {
|
|
|
11013
11112
|
});
|
|
11014
11113
|
}
|
|
11015
11114
|
/**
|
|
11115
|
+
* Get relations' project column lineage as one run saw it
|
|
11116
|
+
* The same answer as `assets/column_lineage`, for the project version a single job ran — including the dbt editor's parse of its own buffer, whose graph belongs to that job and is reachable no other way. One project answers here, the one the run is of, since the graph this annotates is that project's too. Authorized through the job, the same gate as `dbt_graph`. Reaching the run is not on its own enough to read the project: a caller with no access to the script gets its relations and `ref()` edges from `dbt_graph` and an empty answer here, exactly as that endpoint redacts the model's SQL.
|
|
11117
|
+
*
|
|
11118
|
+
* @param data The data for the request.
|
|
11119
|
+
* @param data.workspace
|
|
11120
|
+
* @param data.id The job whose graph the lineage is read from
|
|
11121
|
+
* @param data.assetPath The `dbt://` relations whose lineage to return. Repeated, once per relation, and answered as one union. At least one, and at most 1000 — a request naming none, or more than that, is refused rather than answered with an empty component.
|
|
11122
|
+
*
|
|
11123
|
+
* @returns DbtColumnLineage the relations' column-level lineage
|
|
11124
|
+
* @throws ApiError
|
|
11125
|
+
*/
|
|
11126
|
+
static getDbtRunColumnLineage(data) {
|
|
11127
|
+
return request(OpenAPI, {
|
|
11128
|
+
method: "GET",
|
|
11129
|
+
url: "/w/{workspace}/jobs/dbt_column_lineage/{id}",
|
|
11130
|
+
path: {
|
|
11131
|
+
workspace: data.workspace,
|
|
11132
|
+
id: data.id
|
|
11133
|
+
},
|
|
11134
|
+
query: { asset_path: data.assetPath }
|
|
11135
|
+
});
|
|
11136
|
+
}
|
|
11137
|
+
/**
|
|
11016
11138
|
* List the per-relation progress one job has recorded so far
|
|
11017
11139
|
* Live materialization state for the relations a single job writes, keyed by relation. Polled while a run is in flight so a graph can move a node as its model completes. Authorized through the job, so a caller who may not read it is refused rather than told the run has no progress. An empty list means the job exists and has recorded nothing yet, or is unknown to this workspace.
|
|
11018
11140
|
*
|
|
@@ -12966,6 +13088,33 @@ var NativeTriggerService = class {
|
|
|
12966
13088
|
});
|
|
12967
13089
|
}
|
|
12968
13090
|
/**
|
|
13091
|
+
* set enabled state of native trigger
|
|
13092
|
+
* Enables or disables a native trigger. A disabled trigger stays registered on the
|
|
13093
|
+
* external service but starts no job when it fires.
|
|
13094
|
+
* Requires write access to the script or flow that the trigger is associated with.
|
|
13095
|
+
*
|
|
13096
|
+
* @param data The data for the request.
|
|
13097
|
+
* @param data.workspace
|
|
13098
|
+
* @param data.serviceName
|
|
13099
|
+
* @param data.externalId The external ID of the trigger from the external service
|
|
13100
|
+
* @param data.requestBody updated enabled state
|
|
13101
|
+
* @returns string native trigger enabled state updated
|
|
13102
|
+
* @throws ApiError
|
|
13103
|
+
*/
|
|
13104
|
+
static setNativeTriggerEnabled(data) {
|
|
13105
|
+
return request(OpenAPI, {
|
|
13106
|
+
method: "POST",
|
|
13107
|
+
url: "/w/{workspace}/native_triggers/{service_name}/setenabled/{external_id}",
|
|
13108
|
+
path: {
|
|
13109
|
+
workspace: data.workspace,
|
|
13110
|
+
service_name: data.serviceName,
|
|
13111
|
+
external_id: data.externalId
|
|
13112
|
+
},
|
|
13113
|
+
body: data.requestBody,
|
|
13114
|
+
mediaType: "application/json"
|
|
13115
|
+
});
|
|
13116
|
+
}
|
|
13117
|
+
/**
|
|
12969
13118
|
* list native triggers
|
|
12970
13119
|
* Lists all native triggers for the specified service in the workspace.
|
|
12971
13120
|
* @param data The data for the request.
|
|
@@ -16751,6 +16900,33 @@ var AssetService = class {
|
|
|
16751
16900
|
});
|
|
16752
16901
|
}
|
|
16753
16902
|
/**
|
|
16903
|
+
* Column-level lineage of a set of dbt relations
|
|
16904
|
+
* The direct (`copy` / `mod`) column-to-column lineage the given relations' columns sit in — the connected component around them, from the engine's static analysis. Not their own edges, which would stop one hop out since a column trace walks transitively, and not a whole project's, which carries model families the selection cannot reach.
|
|
16905
|
+
* Several relations, answered as one union, because one selection reaches several: a script's output column can derive from columns of several dbt models. Unpinned, the component crosses projects — a relation one project produces is another's source — and the caller's access is decided again for every project it reaches, so a trace ends where their grants do. A pinned answer, by version here or by job on the run route, is one project's.
|
|
16906
|
+
* Its own endpoint rather than a field on the asset graph: the graph is folder-wide and polled by a run page, while this is rendered for one selection at a time. Empty for projects that did not opt into the analysis pass (`column_lineage: true`), which is the ordinary case. The indirect `scan` kind is stored but never served: it reaches every output column of its model.
|
|
16907
|
+
*
|
|
16908
|
+
* @param data The data for the request.
|
|
16909
|
+
* @param data.workspace
|
|
16910
|
+
* @param data.assetPath The `dbt://` relations whose lineage to return. Repeated, once per relation, and answered as one union. At least one, and at most 1000 — a request naming none, or more than that, is refused rather than answered with an empty component.
|
|
16911
|
+
*
|
|
16912
|
+
* @param data.dbtScriptHash The deployed version a view is drawing, when it is drawing one — the dbt editor, which shows a single project as of a single deploy. A version-pinned answer is that version's project alone, the same as a job-pinned one, and only the unpinned answer crosses projects: a pin says which stored graph is on screen, and another project's live graph is not part of it.
|
|
16913
|
+
* A run's or an editor buffer's own graph is not reachable here: that pins to a job, and costs the job-read gate — see `jobs/dbt_column_lineage/{id}`.
|
|
16914
|
+
*
|
|
16915
|
+
* @returns DbtColumnLineage the relations' column-level lineage
|
|
16916
|
+
* @throws ApiError
|
|
16917
|
+
*/
|
|
16918
|
+
static getDbtColumnLineage(data) {
|
|
16919
|
+
return request(OpenAPI, {
|
|
16920
|
+
method: "GET",
|
|
16921
|
+
url: "/w/{workspace}/assets/column_lineage",
|
|
16922
|
+
path: { workspace: data.workspace },
|
|
16923
|
+
query: {
|
|
16924
|
+
asset_path: data.assetPath,
|
|
16925
|
+
dbt_script_hash: data.dbtScriptHash
|
|
16926
|
+
}
|
|
16927
|
+
});
|
|
16928
|
+
}
|
|
16929
|
+
/**
|
|
16754
16930
|
* List every workspace DuckDB macro (deployed `// macros` libraries)
|
|
16755
16931
|
* @param data The data for the request.
|
|
16756
16932
|
* @param data.workspace
|
|
@@ -18975,6 +19151,35 @@ function checkpointableResult(value) {
|
|
|
18975
19151
|
function jsonRoundTrip(value) {
|
|
18976
19152
|
return JSON.parse(encodeCheckpointPayload({ value: checkpointableResult(value) })).value;
|
|
18977
19153
|
}
|
|
19154
|
+
/** The worker deserializes a sleep into a `u32` of seconds and fails the whole
|
|
19155
|
+
* job on anything wider, so a delay a multiplier has run away with has to be
|
|
19156
|
+
* capped here rather than sent. */
|
|
19157
|
+
const MAX_SLEEP_SECONDS = 4294967295;
|
|
19158
|
+
/** Every attempt claims its keys before the first one is dispatched, so an
|
|
19159
|
+
* unbounded `attempts` is a workflow that hangs allocating rather than a very
|
|
19160
|
+
* patient one. */
|
|
19161
|
+
const MAX_RETRY_ATTEMPTS = 100;
|
|
19162
|
+
/** Rejected where the policy is written, so a workflow fails at its first line
|
|
19163
|
+
* rather than mid-run on a replay. */
|
|
19164
|
+
function assertUsableRetry(retry) {
|
|
19165
|
+
if (retry === void 0) return;
|
|
19166
|
+
const { attempts } = retry;
|
|
19167
|
+
if (!Number.isInteger(attempts) || attempts < 0 || attempts > MAX_RETRY_ATTEMPTS) throw new Error(`retry.attempts must be a whole number between 0 and ${MAX_RETRY_ATTEMPTS}, got ${attempts}`);
|
|
19168
|
+
}
|
|
19169
|
+
/** How many retries the policy asks for, defended against a value that reached
|
|
19170
|
+
* `_nextStep` without going through `assertUsableRetry`. */
|
|
19171
|
+
function retryAttempts(retry) {
|
|
19172
|
+
const attempts = Math.trunc(retry?.attempts ?? 0) || 0;
|
|
19173
|
+
return Math.min(Math.max(attempts, 0), MAX_RETRY_ATTEMPTS);
|
|
19174
|
+
}
|
|
19175
|
+
/** Seconds to wait before retry number `attempt` (0 is the first retry). */
|
|
19176
|
+
function retryDelaySeconds(retry, attempt) {
|
|
19177
|
+
const base = retry.delay ?? 0;
|
|
19178
|
+
if (!(base > 0)) return 0;
|
|
19179
|
+
const grown = base * Math.pow(retry.multiplier ?? 1, attempt);
|
|
19180
|
+
const seconds = Math.floor(Math.min(retry.max_delay ?? grown, grown, MAX_SLEEP_SECONDS));
|
|
19181
|
+
return seconds > 0 ? seconds : 0;
|
|
19182
|
+
}
|
|
18978
19183
|
/** A step key travels as one path segment when its URLs are minted, so it must be
|
|
18979
19184
|
* non-empty and free of `/` and dot segments — otherwise `waitForApproval` would
|
|
18980
19185
|
* accept a key `getApprovalUrls` can never address. */
|
|
@@ -19006,6 +19211,11 @@ var WorkflowCtx = class {
|
|
|
19006
19211
|
* into a `complete` — the parent would then record the caught branch's value as
|
|
19007
19212
|
* a successful step. Boxed: the thrown value may be any falsy value. */
|
|
19008
19213
|
_pendingStepFailure = null;
|
|
19214
|
+
/** Failed tasks whose rejection nothing has consumed, by step key. An unawaited
|
|
19215
|
+
* task is still dispatched and still fails, but nothing drives the rejecting
|
|
19216
|
+
* thenable it returned. The first `.then()` on that thenable drops the entry,
|
|
19217
|
+
* so what remains is only what the body never looked at. */
|
|
19218
|
+
_unobservedTaskFailures = new Map();
|
|
19009
19219
|
/** When set, the task matching this key executes its inner function directly */
|
|
19010
19220
|
_executingKey;
|
|
19011
19221
|
/** Serializes fast-path POSTs across concurrent step() calls within one
|
|
@@ -19039,52 +19249,90 @@ var WorkflowCtx = class {
|
|
|
19039
19249
|
}
|
|
19040
19250
|
_nextStep(name, script, args = {}, dispatch_type = "inline", options) {
|
|
19041
19251
|
this._rethrowSwallowed();
|
|
19042
|
-
const
|
|
19043
|
-
|
|
19044
|
-
|
|
19045
|
-
|
|
19046
|
-
|
|
19047
|
-
|
|
19048
|
-
|
|
19049
|
-
|
|
19050
|
-
|
|
19252
|
+
const stepName = name || script || "step";
|
|
19253
|
+
const maxRetries = retryAttempts(options?.retry);
|
|
19254
|
+
const baseKey = this._allocKey(stepName);
|
|
19255
|
+
const attemptKeys = [baseKey];
|
|
19256
|
+
const backoffKeys = [];
|
|
19257
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
19258
|
+
backoffKeys.push(this._allocKey(`${baseKey}#retry${i + 2}`));
|
|
19259
|
+
attemptKeys.push(this._allocKey(`${baseKey}#${i + 2}`));
|
|
19260
|
+
}
|
|
19261
|
+
for (let attempt = 0;; attempt++) {
|
|
19262
|
+
const key = attemptKeys[attempt];
|
|
19263
|
+
if (key in this.completed) {
|
|
19264
|
+
const value = this.completed[key];
|
|
19265
|
+
if (value && typeof value === "object" && value.__wmill_error) {
|
|
19266
|
+
if (attempt < maxRetries) {
|
|
19267
|
+
this._retryBackoff(backoffKeys[attempt], baseKey, options.retry, attempt);
|
|
19268
|
+
continue;
|
|
19269
|
+
}
|
|
19270
|
+
const err = taskErrorFromMarker(value, `Task '${name}' failed`);
|
|
19271
|
+
this._unobservedTaskFailures.set(baseKey, err);
|
|
19272
|
+
return { then: (_resolve, reject) => {
|
|
19273
|
+
this._unobservedTaskFailures.delete(baseKey);
|
|
19274
|
+
if (reject) reject(err);
|
|
19275
|
+
else throw err;
|
|
19276
|
+
} };
|
|
19277
|
+
}
|
|
19278
|
+
return { then: (resolve$1) => resolve$1(value) };
|
|
19051
19279
|
}
|
|
19052
|
-
|
|
19280
|
+
if (this._executingKey === key) return {
|
|
19281
|
+
then: (resolve$1) => resolve$1(null),
|
|
19282
|
+
_execute_directly: true
|
|
19283
|
+
};
|
|
19284
|
+
if (this._executingKey !== null) return { then: () => new Promise(() => {}) };
|
|
19285
|
+
const stepInfo = {
|
|
19286
|
+
name: name || key,
|
|
19287
|
+
script: script || key,
|
|
19288
|
+
args,
|
|
19289
|
+
key,
|
|
19290
|
+
dispatch_type
|
|
19291
|
+
};
|
|
19292
|
+
if (options) {
|
|
19293
|
+
if (options.timeout !== void 0) stepInfo.timeout = options.timeout;
|
|
19294
|
+
if (options.tag !== void 0) stepInfo.tag = options.tag;
|
|
19295
|
+
if (options.cache_ttl !== void 0) stepInfo.cache_ttl = options.cache_ttl;
|
|
19296
|
+
if (options.priority !== void 0) stepInfo.priority = options.priority;
|
|
19297
|
+
if (options.concurrency_limit !== void 0) stepInfo.concurrent_limit = options.concurrency_limit;
|
|
19298
|
+
if (options.concurrency_key !== void 0) stepInfo.concurrency_key = options.concurrency_key;
|
|
19299
|
+
if (options.concurrency_time_window_s !== void 0) stepInfo.concurrency_time_window_s = options.concurrency_time_window_s;
|
|
19300
|
+
}
|
|
19301
|
+
this.pending.push(stepInfo);
|
|
19302
|
+
return { then: () => {
|
|
19303
|
+
if (this._suspended) return new Promise(() => {});
|
|
19304
|
+
this._suspended = true;
|
|
19305
|
+
const steps = [...this.pending];
|
|
19306
|
+
this.pending = [];
|
|
19307
|
+
const names = steps.map((s) => s.name).join(", ");
|
|
19308
|
+
console.log(`\n--- WAC: ${names} ---`);
|
|
19309
|
+
this._raiseSuspend({
|
|
19310
|
+
mode: steps.length > 1 ? "parallel" : "sequential",
|
|
19311
|
+
steps
|
|
19312
|
+
});
|
|
19313
|
+
} };
|
|
19053
19314
|
}
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19057
|
-
|
|
19058
|
-
|
|
19059
|
-
|
|
19060
|
-
|
|
19061
|
-
|
|
19062
|
-
|
|
19315
|
+
}
|
|
19316
|
+
/** Wait out the backoff between two attempts of a retried task, as a durable
|
|
19317
|
+
* sleep, and return once there is nothing to wait for — no delay configured,
|
|
19318
|
+
* or the sleep already in the checkpoint.
|
|
19319
|
+
*
|
|
19320
|
+
* Raises where it stands, the way `_sleep` does, rather than handing back a
|
|
19321
|
+
* thenable: a task call the body never awaits is still dispatched (the runner
|
|
19322
|
+
* flushes `pending`), so a backoff that only fired when awaited would drop
|
|
19323
|
+
* the retry and let the round report the workflow complete. */
|
|
19324
|
+
_retryBackoff(key, baseKey, retry, attempt) {
|
|
19325
|
+
const seconds = retryDelaySeconds(retry, attempt);
|
|
19326
|
+
if (seconds < 1) return;
|
|
19327
|
+
if (key in this.completed) return;
|
|
19328
|
+
if (this._executingKey !== null) return;
|
|
19329
|
+
console.log(`\n--- WAC: sleep(${key}, ${seconds}s) before retrying ${baseKey} ---`);
|
|
19330
|
+
this._raiseSuspend({
|
|
19331
|
+
mode: "sleep",
|
|
19063
19332
|
key,
|
|
19064
|
-
|
|
19065
|
-
|
|
19066
|
-
|
|
19067
|
-
if (options.timeout !== void 0) stepInfo.timeout = options.timeout;
|
|
19068
|
-
if (options.tag !== void 0) stepInfo.tag = options.tag;
|
|
19069
|
-
if (options.cache_ttl !== void 0) stepInfo.cache_ttl = options.cache_ttl;
|
|
19070
|
-
if (options.priority !== void 0) stepInfo.priority = options.priority;
|
|
19071
|
-
if (options.concurrency_limit !== void 0) stepInfo.concurrent_limit = options.concurrency_limit;
|
|
19072
|
-
if (options.concurrency_key !== void 0) stepInfo.concurrency_key = options.concurrency_key;
|
|
19073
|
-
if (options.concurrency_time_window_s !== void 0) stepInfo.concurrency_time_window_s = options.concurrency_time_window_s;
|
|
19074
|
-
}
|
|
19075
|
-
this.pending.push(stepInfo);
|
|
19076
|
-
return { then: () => {
|
|
19077
|
-
if (this._suspended) return new Promise(() => {});
|
|
19078
|
-
this._suspended = true;
|
|
19079
|
-
const steps = [...this.pending];
|
|
19080
|
-
this.pending = [];
|
|
19081
|
-
const names = steps.map((s) => s.name).join(", ");
|
|
19082
|
-
console.log(`\n--- WAC: ${names} ---`);
|
|
19083
|
-
this._raiseSuspend({
|
|
19084
|
-
mode: steps.length > 1 ? "parallel" : "sequential",
|
|
19085
|
-
steps
|
|
19086
|
-
});
|
|
19087
|
-
} };
|
|
19333
|
+
seconds,
|
|
19334
|
+
steps: []
|
|
19335
|
+
});
|
|
19088
19336
|
}
|
|
19089
19337
|
/** Return and clear any pending (unawaited) steps. */
|
|
19090
19338
|
_flushPending() {
|
|
@@ -19251,6 +19499,13 @@ var WorkflowCtx = class {
|
|
|
19251
19499
|
this._pendingStepFailure = null;
|
|
19252
19500
|
return f;
|
|
19253
19501
|
}
|
|
19502
|
+
/** Report the task failures the body never looked at, and forget them. Which
|
|
19503
|
+
* rounds may call this is the runner's constraint, stated where it is enforced. */
|
|
19504
|
+
_warnUnobservedTaskFailures() {
|
|
19505
|
+
if (this._executingKey !== null) return;
|
|
19506
|
+
for (const [key, err] of this._unobservedTaskFailures) console.log(`\n--- WAC: task '${key}' failed but was never awaited, so the workflow result does not reflect it: ${err.message} ---`);
|
|
19507
|
+
this._unobservedTaskFailures.clear();
|
|
19508
|
+
}
|
|
19254
19509
|
};
|
|
19255
19510
|
async function sleep(seconds) {
|
|
19256
19511
|
const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
|
|
@@ -19276,9 +19531,11 @@ async function step(name, fn) {
|
|
|
19276
19531
|
* @example
|
|
19277
19532
|
* const extract_data = task(async (url: string) => { ... });
|
|
19278
19533
|
* const run_external = task("f/external_script", async (x: number) => { ... });
|
|
19534
|
+
* const call_api = task(fetchOrders, { retry: { attempts: 3, delay: 30, multiplier: 2 } });
|
|
19279
19535
|
*
|
|
19280
19536
|
* Inside a `workflow()`, calling a task dispatches it as a step.
|
|
19281
|
-
* Outside a workflow, the function body executes directly
|
|
19537
|
+
* Outside a workflow, the function body executes directly and
|
|
19538
|
+
* {@link TaskOptions} — retry included — does not apply.
|
|
19282
19539
|
*
|
|
19283
19540
|
* A task runs as its own job, so its result is always encoded as JSON and
|
|
19284
19541
|
* decoded back before the caller sees it: a `Date` comes back as a string, a
|
|
@@ -19296,6 +19553,7 @@ function task(fnOrPath, maybeFnOrOptions, maybeOptions) {
|
|
|
19296
19553
|
fn = fnOrPath;
|
|
19297
19554
|
taskOptions = maybeFnOrOptions;
|
|
19298
19555
|
}
|
|
19556
|
+
assertUsableRetry(taskOptions?.retry);
|
|
19299
19557
|
const taskName = fn.name || taskPath || "";
|
|
19300
19558
|
const wrapper = function(...args) {
|
|
19301
19559
|
const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
|
|
@@ -19354,6 +19612,7 @@ function task(fnOrPath, maybeFnOrOptions, maybeOptions) {
|
|
|
19354
19612
|
* // inside workflow: await extract({ url: "https://..." })
|
|
19355
19613
|
*/
|
|
19356
19614
|
function taskScript(path, options) {
|
|
19615
|
+
assertUsableRetry(options?.retry);
|
|
19357
19616
|
const name = path.split("/").pop() || path;
|
|
19358
19617
|
const wrapper = function(...args) {
|
|
19359
19618
|
const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
|
|
@@ -19379,6 +19638,7 @@ function taskScript(path, options) {
|
|
|
19379
19638
|
* // inside workflow: await pipeline({ input: data })
|
|
19380
19639
|
*/
|
|
19381
19640
|
function taskFlow(path, options) {
|
|
19641
|
+
assertUsableRetry(options?.retry);
|
|
19382
19642
|
const name = path.split("/").pop() || path;
|
|
19383
19643
|
const wrapper = function(...args) {
|
|
19384
19644
|
const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
|