@kubun/plugin-workflow 0.17.1 → 0.18.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/lib/engine.js CHANGED
@@ -186,9 +186,12 @@ export function createWorkflowEngine(deps) {
186
186
  handlers: def.handlers,
187
187
  stateValidator: def.stateValidator
188
188
  });
189
+ const initialAction = row.next_action ?? def.initialAction;
190
+ let currentAction = initialAction;
191
+ let stepInputState = row.state;
189
192
  const flow = generate({
190
- state: row.state,
191
- action: row.next_action ?? def.initialAction,
193
+ state: stepInputState,
194
+ action: initialAction,
192
195
  signal: controller.signal
193
196
  });
194
197
  events.fire('started', {
@@ -210,11 +213,14 @@ export function createWorkflowEngine(deps) {
210
213
  const held = await s.renew(instanceID, bootID, LEASE_MS, now());
211
214
  if (!held) return;
212
215
  const nextAction = value.status === 'action' ? value.action : null;
216
+ const checkpointState = flow.getState();
213
217
  await s.checkpoint(instanceID, {
214
- state: flow.getState(),
218
+ state: checkpointState,
215
219
  nextAction,
216
220
  status: 'running'
217
221
  }, now());
222
+ stepInputState = checkpointState;
223
+ currentAction = nextAction;
218
224
  events.fire('checkpoint', {
219
225
  instanceID,
220
226
  name: def.name
@@ -244,7 +250,7 @@ export function createWorkflowEngine(deps) {
244
250
  fireTerminal(def, instanceID, 'cancelled');
245
251
  return;
246
252
  }
247
- // status === 'error'. `getState()` here is the PRE-handler input state.
253
+ // status === 'error'. Persist the failing step with the state it received.
248
254
  const error = String(value.error);
249
255
  const attempts = row.attempts + 1;
250
256
  const maxAttempts = def.retry?.maxAttempts ?? 1;
@@ -252,8 +258,8 @@ export function createWorkflowEngine(deps) {
252
258
  // Retry rides the queue: re-queue `pending` with a future run gate; the
253
259
  // scheduler re-claims it when due. Not terminal, so no terminal event.
254
260
  await s.fail(instanceID, {
255
- state: flow.getState(),
256
- nextAction: row.next_action,
261
+ state: stepInputState,
262
+ nextAction: currentAction,
257
263
  error,
258
264
  attempts,
259
265
  runAfter: now() + backoff(attempts, def.retry),
@@ -262,8 +268,8 @@ export function createWorkflowEngine(deps) {
262
268
  return;
263
269
  }
264
270
  const wrote = await s.fail(instanceID, {
265
- state: flow.getState(),
266
- nextAction: row.next_action,
271
+ state: stepInputState,
272
+ nextAction: currentAction,
267
273
  error,
268
274
  attempts,
269
275
  runAfter: now(),
package/lib/schema.js CHANGED
@@ -143,6 +143,9 @@ export function createWorkflowContextFactory(api) {
143
143
  // connector exposes numeric time (`ConnectorSyncEvent.duration`). `Int` would
144
144
  // overflow GraphQL's 32-bit range for a millisecond epoch. `state`/`next_action`
145
145
  // have no field here — the projection cannot leak them.
146
+ // Retry rejects missing, active, or non-resumable instances and instances whose
147
+ // singleton key is already held. Cancellation only requests a transition, so
148
+ // the returned status may still be non-terminal.
146
149
  const SDL = `
147
150
  type WorkflowInstanceStatus {
148
151
  instanceID: ID!
@@ -183,12 +186,7 @@ extend type Query {
183
186
  extend type Mutation {
184
187
  setPeriodicSyncEnabled(id: ID!, enabled: Boolean!): PeriodicSync!
185
188
  setPeriodicSyncPolicy(id: ID!, policy: JSON!): PeriodicSync!
186
- # Operator re-arm of a failed instance. Errors (not a null result) when the
187
- # instance is missing, not failed, has no resumable action, or a live
188
- # singleton already holds its key.
189
189
  retryWorkflow(instanceID: ID!): WorkflowInstanceStatus!
190
- # Operator-initiated cancel. Async: cancel() only requests cancellation, so the
191
- # returned status is a re-fetch right after and may not yet be terminal.
192
190
  cancelWorkflow(instanceID: ID!): WorkflowInstanceStatus!
193
191
  }
194
192
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/plugin-workflow",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "keywords": [],
5
5
  "license": "see LICENSE.md",
6
6
  "sideEffects": false,
@@ -15,23 +15,23 @@
15
15
  "LICENSE.md"
16
16
  ],
17
17
  "dependencies": {
18
- "@kubun/db": "^0.17.0",
19
- "@kubun/engine": "^0.17.2",
20
- "@kubun/graphql": "^0.17.2",
21
- "@kubun/id": "^0.17.0",
22
- "@kubun/logger": "^0.17.0",
23
- "@kubun/plugin-p2p-api": "^0.17.0",
24
- "@kubun/plugin-workflow-api": "^0.17.1",
25
- "@kubun/store-workflow": "^0.17.1",
26
- "@sozai/event": "^0.1.3",
18
+ "@kubun/db": "^0.18.0",
19
+ "@kubun/engine": "^0.18.0",
20
+ "@kubun/graphql": "^0.18.0",
21
+ "@kubun/id": "^0.18.0",
22
+ "@kubun/logger": "^0.18.0",
23
+ "@kubun/plugin-p2p-api": "^0.18.0",
24
+ "@kubun/plugin-workflow-api": "^0.18.0",
25
+ "@kubun/store-workflow": "^0.18.0",
26
+ "@sozai/event": "^0.1.6",
27
27
  "@sozai/flow": "^0.3.1",
28
28
  "@sozai/runtime": "^0.1.0",
29
- "@sozai/schema": "^0.1.2"
29
+ "@sozai/schema": "^0.1.4"
30
30
  },
31
31
  "devDependencies": {
32
- "@kubun/db-better-sqlite": "^0.17.0",
33
- "@kubun/db-postgres": "^0.17.1",
34
- "@testcontainers/postgresql": "^12.1.0"
32
+ "@kubun/db-better-sqlite": "^0.18.0",
33
+ "@kubun/db-postgres": "^0.18.0",
34
+ "@testcontainers/postgresql": "^12.2.1"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public"