Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/cloudflare/internal/test/workflows/workflows-api-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,21 @@ export const tests = {
assert.deepStrictEqual(instances[1].id, 'bar');
}
},

async testRestartNoOptions(_, env) {
const instance = await env.workflow.get('restart-basic');
await instance.restart();
},

async testRestartFromStepNameOnly(_, env) {
const instance = await env.workflow.get('restart-step');
await instance.restart({ from: { name: 'fetch data' } });
},

async testRestartFromStepAllOptions(_, env) {
const instance = await env.workflow.get('restart-full');
await instance.restart({
from: { name: 'process item', count: 3, type: 'do' },
});
},
};
4 changes: 4 additions & 0 deletions src/cloudflare/internal/test/workflows/workflows-mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export default {
);
}

if (reqUrl.pathname === '/restart' && request.method === 'POST') {
return Response.json({}, { status: 200 });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mock returns 200 unconditionally without inspecting the request body. This means the testRestartFromStepNameOnly and testRestartFromStepAllOptions tests only verify the call doesn't throw -- they don't assert that from is actually included in the request payload. A regression that silently drops the from field would pass all tests.

Consider validating the body and returning the from data so the tests can assert on it. For example:

Suggested change
return Response.json({}, { status: 200 });
if (reqUrl.pathname === '/restart' && request.method === 'POST') {
return Response.json({ result: { from: data.from } }, { status: 200 });
}

Then in the test assertions, verify the response carries the expected from value back (or at minimum, assert data.from is defined when it should be).

}

if (reqUrl.pathname === '/createBatch' && request.method === 'POST') {
return Response.json(
{
Expand Down
3 changes: 2 additions & 1 deletion src/cloudflare/internal/workflows-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ class InstanceImpl implements WorkflowInstance {
});
}

async restart(): Promise<void> {
async restart(options?: WorkflowInstanceRestartOptions): Promise<void> {
await callFetcher(this.fetcher, '/restart', {
id: this.id,
from: options?.from,
});
}

Expand Down
21 changes: 19 additions & 2 deletions src/cloudflare/internal/workflows.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ interface WorkflowError {
message: string;
}

interface WorkflowInstanceRestartOptions {
/**
* Restart from a specific step. If omitted, the instance restarts from the beginning.
* The step must exist in the instance's execution history.
*/
from?: {
/** The step name as defined in your workflow code. */
name: string;
/** 1-indexed occurrence of this step name. Defaults to 1. Use when the same step name appears multiple times (e.g. in a loop). */
count?: number;
/** Step type filter. Use when different step types share the same name. */
type?: 'do' | 'sleep' | 'waitForEvent';
};
}

declare abstract class WorkflowInstance {
id: string;

Expand All @@ -127,9 +142,11 @@ declare abstract class WorkflowInstance {
terminate(): Promise<void>;

/**
* Restart the instance.
* Restart the instance. Optionally restart from a specific step, preserving
* cached results for all steps before it.
* @param options Options for the restart, including an optional step to restart from.
*/
restart(): Promise<void>;
restart(options?: WorkflowInstanceRestartOptions): Promise<void>;

/**
* Returns the current status of the instance.
Expand Down
21 changes: 19 additions & 2 deletions types/defines/workflows.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ interface WorkflowError {
message: string;
}

interface WorkflowInstanceRestartOptions {
/**
* Restart from a specific step. If omitted, the instance restarts from the beginning.
* The step must exist in the instance's execution history.
*/
from?: {
/** The step name as defined in your workflow code. */
name: string;
/** 1-indexed occurrence of this step name. Defaults to 1. Use when the same step name appears multiple times (e.g. in a loop). */
count?: number;
/** Step type filter. Use when different step types share the same name. */
type?: 'do' | 'sleep' | 'waitForEvent';
};
}

declare abstract class WorkflowInstance {
public id: string;

Expand All @@ -112,9 +127,11 @@ declare abstract class WorkflowInstance {
public terminate(): Promise<void>;

/**
* Restart the instance.
* Restart the instance. Optionally restart from a specific step, preserving
* cached results for all steps before it.
* @param options Options for the restart, including an optional step to restart from.
*/
public restart(): Promise<void>;
public restart(options?: WorkflowInstanceRestartOptions): Promise<void>;

/**
* Returns the current status of the instance.
Expand Down
Loading