1
+ """
2
+ See sibling file test_workflow_caller_cancellation_types.py for explanatory comments.
3
+ """
4
+
1
5
import asyncio
2
6
import uuid
3
7
from dataclasses import dataclass , field
@@ -46,20 +50,29 @@ class TestContext:
46
50
class HandlerWorkflow :
47
51
def __init__ (self ):
48
52
self .cancel_handler_released = asyncio .Event ()
53
+ self .caller_op_future_resolved = asyncio .Event ()
49
54
50
55
@workflow .run
51
56
async def run (self ) -> None :
52
57
# We want the cancel handler to be invoked, so this workflow must not close before
53
58
# then.
54
59
await self .cancel_handler_released .wait ()
55
- # TODO: there is technically a race now between (1) caller server writing
56
- # NEXUS_OPERATION_CANCEL_REQUEST_FAILED in reponse to failed cancel handler in nexus task
57
- # and (2) NEXUS_OPERATION_COMPLETED due to this workflow completing.
60
+ if (
61
+ test_context .cancellation_type
62
+ == workflow .NexusOperationCancellationType .WAIT_REQUESTED
63
+ ):
64
+ # For WAIT_REQUESTED, we want to prove that the future can be unblocked before the
65
+ # handler workflow completes.
66
+ await self .caller_op_future_resolved .wait ()
58
67
59
68
@workflow .signal
60
69
def set_cancel_handler_released (self ) -> None :
61
70
self .cancel_handler_released .set ()
62
71
72
+ @workflow .signal
73
+ def set_caller_op_future_resolved (self ) -> None :
74
+ self .caller_op_future_resolved .set ()
75
+
63
76
64
77
@nexusrpc .service
65
78
class Service :
@@ -159,6 +172,10 @@ async def run(self, input: Input) -> CancellationResult:
159
172
test_context .cancellation_type
160
173
== workflow .NexusOperationCancellationType .WAIT_REQUESTED
161
174
):
175
+ # For WAIT_REQUESTED, we need core to receive the NexusOperationCancelRequestCompleted
176
+ # event. That event should trigger a workflow task, but does not currently due to
177
+ # https://github.com/temporalio/temporal/issues/8175. Force a new WFT, allowing time for
178
+ # the event hopefully to arrive.
162
179
await workflow .sleep (0.1 , summary = "Force new WFT" )
163
180
error_type , error_cause_type = None , None
164
181
try :
@@ -310,11 +327,12 @@ async def check_behavior_for_wait_cancellation_requested(
310
327
caller_wf : WorkflowHandle [Any , CancellationResult ],
311
328
handler_wf : WorkflowHandle ,
312
329
) -> None :
313
- await handler_wf .result ()
314
330
await caller_wf .signal (CallerWorkflow .release )
315
331
result = await caller_wf .result ()
316
332
assert result .error_type == "NexusOperationError"
317
333
assert result .error_cause_type == "HandlerError"
334
+ await handler_wf .signal (HandlerWorkflow .set_caller_op_future_resolved )
335
+ await handler_wf .result ()
318
336
await assert_event_subsequence (
319
337
[
320
338
(caller_wf , EventType .EVENT_TYPE_WORKFLOW_EXECUTION_STARTED ),
@@ -328,7 +346,11 @@ async def check_behavior_for_wait_cancellation_requested(
328
346
caller_wf ,
329
347
EventType .EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED ,
330
348
)
331
- assert op_cancel_request_failed < caller_op_future_resolved
349
+ handler_wf_completed = await get_event_time (
350
+ handler_wf ,
351
+ EventType .EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED ,
352
+ )
353
+ assert op_cancel_request_failed < caller_op_future_resolved < handler_wf_completed
332
354
333
355
334
356
async def check_behavior_for_wait_cancellation_completed (
@@ -339,10 +361,14 @@ async def check_behavior_for_wait_cancellation_completed(
339
361
await caller_wf .signal (CallerWorkflow .release )
340
362
result = await caller_wf .result ()
341
363
assert not result .error_type
364
+ # Note that the relative order of these two events is non-deterministic, since one is the result
365
+ # of the cancel handler response being processed and the other is the result of the handler
366
+ # workflow exiting.
367
+ # (caller_wf, EventType.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED)
368
+ # (handler_wf, EventType.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED)
342
369
await assert_event_subsequence (
343
370
[
344
371
(caller_wf , EventType .EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED ),
345
- (caller_wf , EventType .EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED ),
346
372
(handler_wf , EventType .EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED ),
347
373
(caller_wf , EventType .EVENT_TYPE_NEXUS_OPERATION_COMPLETED ),
348
374
]
0 commit comments