Greetings. I have come across a weird case using a cancellation-scope in the Java SDK. I was hoping someone could comment? Imagine a workflow which:
- In a cancellation-scope, launch an async child workflow (and keep the promise). Child-workflow is a long-running operation.
- Run the cancellation-scope.
- Wait N seconds.
- Cancel the cancellation-scope.
- Join to the child workflow’s promise.
My expectation is that (a) the child workflow would receive a CanceledFailure
exception, which (b) according to the documentation it should re-throw when it exits, and then (c) would be thrown out of the join.
But, that’s not what happens. When you look at the workflow history: the parent workflow records the cancellation sent to the child, but, the child-workflow doesn’t start until a later event, and therefore, doesn’t get the CanceledFailure
exception.
I think this is a bug, but my understanding might be incorrect.
public static class MigrateCancellationWorkflowTest implements MigrateCancellationWorkflow {
@Override
public void migrate(final DatabaseMapping databaseMapping) {
final AtomicReference<Promise<Void>> reference = new AtomicReference<>();
final CancellationScope scope =
Workflow.newCancellationScope(() -> reference.set(
Async.procedure(
Workflow.newChildWorkflowStub(
MigrateBackupFilesWorkflow.class,
ChildWorkflowOptions.newBuilder()
.setCancellationType(WAIT_CANCELLATION_COMPLETED)
.setNamespace(DCP_NAMESPACE)
.setTaskQueue(DCP_PRIMITIVES_TASK_QUEUE)
.setWorkflowExecutionTimeout(Duration.ofHours(12))
.build())::migrateBackupFiles,
databaseMapping, "s3://bucket/key", true)));
scope.run();
Workflow.sleep(Duration.ofSeconds(10));
scope.cancel();
// Expect the following to throw `CanceledFailure`.
reference.get().get();
}
}
Regards,
Sean