Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6738d41

Browse files
committed
Implement signals
1 parent faf6d2a commit 6738d41

File tree

4 files changed

+70
-18
lines changed

4 files changed

+70
-18
lines changed

packages/test-workflows/src/signals.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@ const signals = {
1515
};
1616

1717
async function main(): Promise<void> {
18-
await Promise.race([
19-
new Promise((_resolve, reject) => {
20-
interrupt = reject;
21-
}),
22-
sleep(100000),
23-
]);
18+
try {
19+
await Promise.race([
20+
new Promise<never>((_resolve, reject) => {
21+
interrupt = reject;
22+
}),
23+
(async (): Promise<never> => {
24+
await sleep(100000);
25+
throw new Error('Sleep completed unexpectedly');
26+
})(),
27+
]);
28+
} catch (err) {
29+
if (err.message !== 'just because') {
30+
throw new Error('Unexpected error');
31+
}
32+
}
33+
// Don't complete to allow Workflow to be interrupted by fail() signal
34+
await sleep(100000);
2435
}
2536

2637
export const workflow: Interruptable = { main, signals };

packages/test/src/test-integration.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,14 @@ if (RUN_INTEGRATION_TESTS) {
108108
t.is(res, undefined);
109109
});
110110

111-
// Queries not yet properly implemented
112-
test.skip('signals', async (t) => {
111+
test('signals', async (t) => {
113112
const client = new Connection();
114113
const workflow = client.workflow<Interruptable>('signals', { taskQueue: 'test' });
115114
const promise = workflow.start();
116115
await workflow.started;
117116
await workflow.signal.interrupt('just because');
118-
t.throwsAsync(promise, { message: /just because/, instanceOf: WorkflowExecutionFailedError });
117+
await workflow.signal.fail();
118+
await t.throwsAsync(promise, { message: /Signal failed/, instanceOf: WorkflowExecutionFailedError });
119119
});
120120

121121
test('http', async (t) => {

packages/test/src/test-workflows.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ function makeSignalWorkflow(
133133
args: any[],
134134
timestamp: number = Date.now()
135135
): coresdk.workflow_activation.IWFActivation {
136-
return makeActivation(timestamp, { signalWorkflow: { signalName, input: args } });
136+
return makeActivation(timestamp, { signalWorkflow: { signalName, input: defaultDataConverter.toPayloads(...args) } });
137137
}
138138

139139
function makeCompleteWorkflowExecution(result?: coresdk.common.IPayload): coresdk.workflow_commands.IWorkflowCommand {
@@ -528,8 +528,7 @@ test('simple-query', async (t) => {
528528
}
529529
});
530530

531-
// Signals have not yet been implemented
532-
test.skip('signals', async (t) => {
531+
test('signals', async (t) => {
533532
const { script } = t.context;
534533
{
535534
const req = await activate(t, makeStartWorkflow(script));
@@ -540,12 +539,30 @@ test.skip('signals', async (t) => {
540539
);
541540
}
542541
{
543-
const req = await activate(t, makeSignalWorkflow('fail', []));
544-
compareCompletion(t, req, makeSuccess([])); // TODO
542+
const req = await activate(t, makeSignalWorkflow('interrupt', ['just because']));
543+
compareCompletion(
544+
t,
545+
req,
546+
makeSuccess([makeStartTimerCommand({ timerId: '1', startToFireTimeout: msToTs(100000) })])
547+
);
545548
}
546549
{
547-
const req = await activate(t, makeSignalWorkflow('interrupt', ['just because']));
548-
compareCompletion(t, req, makeSuccess([])); // TODO
550+
const req = cleanWorkflowFailureStackTrace(await activate(t, makeSignalWorkflow('fail', [])));
551+
compareCompletion(
552+
t,
553+
req,
554+
makeSuccess([
555+
makeFailWorkflowExecution(
556+
'Signal failed',
557+
dedent`
558+
Error: Signal failed
559+
at fail
560+
at Activator.signalWorkflow
561+
at activate`,
562+
'Error'
563+
),
564+
])
565+
);
549566
}
550567
});
551568

packages/workflow/src/internals.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,32 @@ export class Activator implements WorkflowTaskHandler {
213213
}
214214
}
215215

216-
public signalWorkflow(_activation: iface.coresdk.workflow_activation.ISignalWorkflow): void {
217-
throw new Error('Not implemented');
216+
public signalWorkflow(activation: iface.coresdk.workflow_activation.ISignalWorkflow): void {
217+
if (state.workflow === undefined) {
218+
throw new Error('state.workflow is not defined');
219+
}
220+
const { signals } = state.workflow;
221+
if (signals === undefined) {
222+
throw new Error('Workflow did not define any signals');
223+
}
224+
225+
if (!activation.signalName) {
226+
throw new Error('Missing activation signalName');
227+
}
228+
229+
const fn = signals[activation.signalName];
230+
if (fn === undefined) {
231+
throw new Error(`Workflow did not register a signal named ${activation.signalName}`);
232+
}
233+
try {
234+
// TODO: support custom converter
235+
const retOrPromise = fn(...arrayFromPayloads(defaultDataConverter, activation.input));
236+
if (retOrPromise instanceof Promise) {
237+
retOrPromise.catch(failWorkflow);
238+
}
239+
} catch (err) {
240+
failWorkflow(err);
241+
}
218242
}
219243

220244
public updateRandomSeed(activation: iface.coresdk.workflow_activation.IUpdateRandomSeed): void {

0 commit comments

Comments
 (0)