@gencow/core 0.1.29 → 0.1.30
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/workflow-json.d.ts +2 -0
- package/dist/workflow-json.js +5 -0
- package/dist/workflow.js +51 -53
- package/dist/workflows-api.js +3 -2
- package/package.json +1 -1
- package/src/workflow-json.ts +6 -0
- package/src/workflow.ts +51 -55
- package/src/workflows-api.ts +3 -2
package/dist/workflow.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sql } from "drizzle-orm";
|
|
2
2
|
import { mutation } from "./reactive-mutation.js";
|
|
3
|
+
import { workflowJsonb } from "./workflow-json.js";
|
|
3
4
|
import { registerWorkflowsApi } from "./workflows-api.js";
|
|
4
5
|
const workflowRegistry = (globalThis.__gencow_workflowRegistry ??= new Map());
|
|
5
6
|
export const DEFAULT_WORKFLOW_MAX_DURATION_MS = 30 * 60 * 1000;
|
|
@@ -90,63 +91,60 @@ function isMissingWorkflowV2SchemaError(error) {
|
|
|
90
91
|
message.includes('column "retry_count"') ||
|
|
91
92
|
message.includes('column "user_id"'));
|
|
92
93
|
}
|
|
93
|
-
async function tryInsertWorkflowV2WakeOutbox(db, workflowId) {
|
|
94
|
-
try {
|
|
95
|
-
await db.execute(sql `
|
|
96
|
-
INSERT INTO _gencow_workflow_outbox_v2 (
|
|
97
|
-
id,
|
|
98
|
-
run_id,
|
|
99
|
-
kind,
|
|
100
|
-
available_at,
|
|
101
|
-
status
|
|
102
|
-
)
|
|
103
|
-
VALUES (
|
|
104
|
-
${`start:${workflowId}`},
|
|
105
|
-
${workflowId},
|
|
106
|
-
'wake_run',
|
|
107
|
-
NOW(),
|
|
108
|
-
'pending'
|
|
109
|
-
)
|
|
110
|
-
ON CONFLICT (id) DO NOTHING
|
|
111
|
-
`);
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
if (!isMissingWorkflowV2SchemaError(error))
|
|
115
|
-
throw error;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
94
|
async function tryInsertWorkflowV2Run(options) {
|
|
119
95
|
try {
|
|
120
96
|
await options.db.execute(sql `
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
97
|
+
WITH inserted_run AS (
|
|
98
|
+
INSERT INTO _gencow_workflow_runs_v2 (
|
|
99
|
+
id,
|
|
100
|
+
workflow_name,
|
|
101
|
+
workflow_version,
|
|
102
|
+
args_json,
|
|
103
|
+
user_id,
|
|
104
|
+
max_active_duration_ms,
|
|
105
|
+
lifecycle_deadline_at,
|
|
106
|
+
retry_count,
|
|
107
|
+
max_retries,
|
|
108
|
+
max_attempts
|
|
109
|
+
)
|
|
110
|
+
VALUES (
|
|
111
|
+
${options.workflowId},
|
|
112
|
+
${options.workflowName},
|
|
113
|
+
${options.workflowVersion ?? null},
|
|
114
|
+
${workflowJsonb(options.args)},
|
|
115
|
+
${options.userId},
|
|
116
|
+
${options.maxActiveDurationMs},
|
|
117
|
+
CASE
|
|
118
|
+
WHEN ${options.lifecycleTimeoutMs}::bigint IS NULL THEN NULL
|
|
119
|
+
ELSE NOW() + (${options.lifecycleTimeoutMs}::bigint * INTERVAL '1 millisecond')
|
|
120
|
+
END,
|
|
121
|
+
0,
|
|
122
|
+
${options.maxRetries},
|
|
123
|
+
${options.maxRetries + 1}
|
|
124
|
+
)
|
|
125
|
+
RETURNING id
|
|
126
|
+
),
|
|
127
|
+
inserted_outbox AS (
|
|
128
|
+
INSERT INTO _gencow_workflow_outbox_v2 (
|
|
129
|
+
id,
|
|
130
|
+
run_id,
|
|
131
|
+
kind,
|
|
132
|
+
available_at,
|
|
133
|
+
status
|
|
134
|
+
)
|
|
135
|
+
SELECT
|
|
136
|
+
'start:' || inserted_run.id,
|
|
137
|
+
inserted_run.id,
|
|
138
|
+
'wake_run',
|
|
139
|
+
NOW(),
|
|
140
|
+
'pending'
|
|
141
|
+
FROM inserted_run
|
|
142
|
+
ON CONFLICT (id) DO NOTHING
|
|
143
|
+
RETURNING id
|
|
147
144
|
)
|
|
145
|
+
SELECT id
|
|
146
|
+
FROM inserted_run
|
|
148
147
|
`);
|
|
149
|
-
await tryInsertWorkflowV2WakeOutbox(options.db, options.workflowId);
|
|
150
148
|
return true;
|
|
151
149
|
}
|
|
152
150
|
catch (error) {
|
|
@@ -230,7 +228,7 @@ export function workflow(name, options) {
|
|
|
230
228
|
VALUES (
|
|
231
229
|
${workflowId},
|
|
232
230
|
${name},
|
|
233
|
-
${
|
|
231
|
+
${workflowJsonb(persistedArgs)},
|
|
234
232
|
${realtimeToken},
|
|
235
233
|
'pending',
|
|
236
234
|
0,
|
package/dist/workflows-api.js
CHANGED
|
@@ -2,6 +2,7 @@ import { sql } from "drizzle-orm";
|
|
|
2
2
|
import { query } from "./reactive-query.js";
|
|
3
3
|
import { mutation } from "./reactive-mutation.js";
|
|
4
4
|
import { createWorkflowRealtimeToken, deserializeWorkflowValue, getWorkflowResumeActionName, getWorkflowRealtimeKey, serializeWorkflowValue, } from "./workflow.js";
|
|
5
|
+
import { workflowJsonb } from "./workflow-json.js";
|
|
5
6
|
import { GencowValidationError, v } from "./v.js";
|
|
6
7
|
import { deriveWorkflowStatus } from "./workflow-types.js";
|
|
7
8
|
const WORKFLOW_STATUSES = new Set(["pending", "running", "completed", "failed"]);
|
|
@@ -160,7 +161,7 @@ async function tryRecordWorkflowV2Signal(options) {
|
|
|
160
161
|
${crypto.randomUUID()},
|
|
161
162
|
${options.workflowId},
|
|
162
163
|
${options.event},
|
|
163
|
-
${
|
|
164
|
+
${workflowJsonb(options.payload)},
|
|
164
165
|
${crypto.randomUUID()}
|
|
165
166
|
)
|
|
166
167
|
RETURNING run_id
|
|
@@ -297,7 +298,7 @@ export function registerWorkflowsApi() {
|
|
|
297
298
|
${crypto.randomUUID()},
|
|
298
299
|
${workflow.id},
|
|
299
300
|
${normalizedEvent},
|
|
300
|
-
${
|
|
301
|
+
${workflowJsonb(persistedPayload)}
|
|
301
302
|
)
|
|
302
303
|
`);
|
|
303
304
|
await tryRecordWorkflowV2Signal({
|
package/package.json
CHANGED
package/src/workflow.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
WorkflowOptions,
|
|
8
8
|
WorkflowStartResult,
|
|
9
9
|
} from "./workflow-types.js";
|
|
10
|
+
import { workflowJsonb } from "./workflow-json.js";
|
|
10
11
|
import { registerWorkflowsApi } from "./workflows-api.js";
|
|
11
12
|
|
|
12
13
|
declare global {
|
|
@@ -125,33 +126,6 @@ function isMissingWorkflowV2SchemaError(error: unknown): boolean {
|
|
|
125
126
|
);
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
async function tryInsertWorkflowV2WakeOutbox(
|
|
129
|
-
db: { execute: (query: ReturnType<typeof sql>) => Promise<unknown> },
|
|
130
|
-
workflowId: string,
|
|
131
|
-
): Promise<void> {
|
|
132
|
-
try {
|
|
133
|
-
await db.execute(sql`
|
|
134
|
-
INSERT INTO _gencow_workflow_outbox_v2 (
|
|
135
|
-
id,
|
|
136
|
-
run_id,
|
|
137
|
-
kind,
|
|
138
|
-
available_at,
|
|
139
|
-
status
|
|
140
|
-
)
|
|
141
|
-
VALUES (
|
|
142
|
-
${`start:${workflowId}`},
|
|
143
|
-
${workflowId},
|
|
144
|
-
'wake_run',
|
|
145
|
-
NOW(),
|
|
146
|
-
'pending'
|
|
147
|
-
)
|
|
148
|
-
ON CONFLICT (id) DO NOTHING
|
|
149
|
-
`);
|
|
150
|
-
} catch (error) {
|
|
151
|
-
if (!isMissingWorkflowV2SchemaError(error)) throw error;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
129
|
async function tryInsertWorkflowV2Run(options: {
|
|
156
130
|
db: { execute: (query: ReturnType<typeof sql>) => Promise<unknown> };
|
|
157
131
|
workflowId: string;
|
|
@@ -165,35 +139,57 @@ async function tryInsertWorkflowV2Run(options: {
|
|
|
165
139
|
}): Promise<boolean> {
|
|
166
140
|
try {
|
|
167
141
|
await options.db.execute(sql`
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
142
|
+
WITH inserted_run AS (
|
|
143
|
+
INSERT INTO _gencow_workflow_runs_v2 (
|
|
144
|
+
id,
|
|
145
|
+
workflow_name,
|
|
146
|
+
workflow_version,
|
|
147
|
+
args_json,
|
|
148
|
+
user_id,
|
|
149
|
+
max_active_duration_ms,
|
|
150
|
+
lifecycle_deadline_at,
|
|
151
|
+
retry_count,
|
|
152
|
+
max_retries,
|
|
153
|
+
max_attempts
|
|
154
|
+
)
|
|
155
|
+
VALUES (
|
|
156
|
+
${options.workflowId},
|
|
157
|
+
${options.workflowName},
|
|
158
|
+
${options.workflowVersion ?? null},
|
|
159
|
+
${workflowJsonb(options.args)},
|
|
160
|
+
${options.userId},
|
|
161
|
+
${options.maxActiveDurationMs},
|
|
162
|
+
CASE
|
|
163
|
+
WHEN ${options.lifecycleTimeoutMs}::bigint IS NULL THEN NULL
|
|
164
|
+
ELSE NOW() + (${options.lifecycleTimeoutMs}::bigint * INTERVAL '1 millisecond')
|
|
165
|
+
END,
|
|
166
|
+
0,
|
|
167
|
+
${options.maxRetries},
|
|
168
|
+
${options.maxRetries + 1}
|
|
169
|
+
)
|
|
170
|
+
RETURNING id
|
|
171
|
+
),
|
|
172
|
+
inserted_outbox AS (
|
|
173
|
+
INSERT INTO _gencow_workflow_outbox_v2 (
|
|
174
|
+
id,
|
|
175
|
+
run_id,
|
|
176
|
+
kind,
|
|
177
|
+
available_at,
|
|
178
|
+
status
|
|
179
|
+
)
|
|
180
|
+
SELECT
|
|
181
|
+
'start:' || inserted_run.id,
|
|
182
|
+
inserted_run.id,
|
|
183
|
+
'wake_run',
|
|
184
|
+
NOW(),
|
|
185
|
+
'pending'
|
|
186
|
+
FROM inserted_run
|
|
187
|
+
ON CONFLICT (id) DO NOTHING
|
|
188
|
+
RETURNING id
|
|
194
189
|
)
|
|
190
|
+
SELECT id
|
|
191
|
+
FROM inserted_run
|
|
195
192
|
`);
|
|
196
|
-
await tryInsertWorkflowV2WakeOutbox(options.db, options.workflowId);
|
|
197
193
|
return true;
|
|
198
194
|
} catch (error) {
|
|
199
195
|
if (isMissingWorkflowV2SchemaError(error)) return false;
|
|
@@ -297,7 +293,7 @@ export function workflow<TSchema = any, TReturn = any>(
|
|
|
297
293
|
VALUES (
|
|
298
294
|
${workflowId},
|
|
299
295
|
${name},
|
|
300
|
-
${
|
|
296
|
+
${workflowJsonb(persistedArgs)},
|
|
301
297
|
${realtimeToken},
|
|
302
298
|
'pending',
|
|
303
299
|
0,
|
package/src/workflows-api.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
getWorkflowRealtimeKey,
|
|
9
9
|
serializeWorkflowValue,
|
|
10
10
|
} from "./workflow.js";
|
|
11
|
+
import { workflowJsonb } from "./workflow-json.js";
|
|
11
12
|
import { GencowValidationError, v } from "./v.js";
|
|
12
13
|
import type {
|
|
13
14
|
WorkflowDerivedStatus,
|
|
@@ -246,7 +247,7 @@ async function tryRecordWorkflowV2Signal(options: {
|
|
|
246
247
|
${crypto.randomUUID()},
|
|
247
248
|
${options.workflowId},
|
|
248
249
|
${options.event},
|
|
249
|
-
${
|
|
250
|
+
${workflowJsonb(options.payload)},
|
|
250
251
|
${crypto.randomUUID()}
|
|
251
252
|
)
|
|
252
253
|
RETURNING run_id
|
|
@@ -397,7 +398,7 @@ export function registerWorkflowsApi(): void {
|
|
|
397
398
|
${crypto.randomUUID()},
|
|
398
399
|
${workflow.id},
|
|
399
400
|
${normalizedEvent},
|
|
400
|
-
${
|
|
401
|
+
${workflowJsonb(persistedPayload)}
|
|
401
402
|
)
|
|
402
403
|
`);
|
|
403
404
|
await tryRecordWorkflowV2Signal({
|