Skip to content

Commit

Permalink
Test Server: Fix Nexus operation cancel before start (temporalio#2223)
Browse files Browse the repository at this point in the history
* Test Server: Fix Nexus operation cancel before start

* test
  • Loading branch information
pdoerner authored Sep 17, 2024
1 parent 6f0cf07 commit 7525c65
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -608,13 +608,12 @@ public static StateMachine<NexusOperationData> newNexusOperation(Endpoint endpoi
.add(NONE, INITIATE, INITIATED, StateMachines::scheduleNexusOperation)
.add(INITIATED, START, STARTED, StateMachines::startNexusOperation)
.add(INITIATED, TIME_OUT, TIMED_OUT, StateMachines::timeoutNexusOperation)
// Transitions directly to CANCELED if operation has not been started
// TODO: properly support cancel before start
.add(
INITIATED,
REQUEST_CANCELLATION,
CANCELED,
StateMachines::reportNexusOperationCancellation)
// .add(
// INITIATED,
// REQUEST_CANCELLATION,
// INITIATED,
// StateMachines::requestCancelNexusOperation)
.add(INITIATED, CANCEL, CANCELED, StateMachines::reportNexusOperationCancellation)
// Transitions directly from INITIATED to COMPLETE for sync completions
.add(INITIATED, COMPLETE, COMPLETED, StateMachines::completeNexusOperation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import io.temporal.api.enums.v1.*;
import io.temporal.api.errordetails.v1.QueryFailedFailure;
import io.temporal.api.failure.v1.ApplicationFailureInfo;
import io.temporal.api.failure.v1.CanceledFailureInfo;
import io.temporal.api.failure.v1.Failure;
import io.temporal.api.history.v1.*;
import io.temporal.api.nexus.v1.Endpoint;
Expand Down Expand Up @@ -753,14 +754,26 @@ private void processRequestCancelNexusOperation(
.asRuntimeException();
}

operation.action(Action.REQUEST_CANCELLATION, ctx, null, workflowTaskCompletedId);
if (isTerminalState(operation.getState())) {
// Operation canceled before started, so immediately remove operation since no new
// cancellation task will be generated.
if (operation.getState() == State.INITIATED) {
// TODO: properly support cancel before start once server does
ctx.addEvent(
HistoryEvent.newBuilder()
.setEventType(EventType.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED)
.setNexusOperationCancelRequestedEventAttributes(
NexusOperationCancelRequestedEventAttributes.newBuilder()
.setScheduledEventId(attr.getScheduledEventId())
.setWorkflowTaskCompletedEventId(workflowTaskCompletedId))
.build());
Failure canceled =
Failure.newBuilder()
.setMessage("operation canceled before it was started")
.setCanceledFailureInfo(CanceledFailureInfo.getDefaultInstance())
.build();
operation.action(Action.CANCEL, ctx, canceled, workflowTaskCompletedId);
nexusOperations.remove(scheduleEventId);
ctx.setNeedWorkflowTask(true);
} else {
operation.action(Action.REQUEST_CANCELLATION, ctx, null, workflowTaskCompletedId);
ctx.addTimer(
ProtobufTimeUtils.toJavaDuration(operation.getData().requestTimeout),
() ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,9 @@ public void testNexusOperationCancelBeforeStart() {
events.get(0).getNexusOperationCanceledEventAttributes().getFailure();
assertOperationFailureInfo(failure.getNexusOperationExecutionFailureInfo());
Assert.assertEquals("nexus operation completed unsuccessfully", failure.getMessage());
Assert.assertFalse(failure.hasCause());
io.temporal.api.failure.v1.Failure cause = failure.getCause();
Assert.assertEquals("operation canceled before it was started", cause.getMessage());
Assert.assertNotNull(cause.getCanceledFailureInfo());
}

@Test(timeout = 15000)
Expand Down

0 comments on commit 7525c65

Please sign in to comment.