|
44 | 44 | from temporalio.api.failure.v1 import Failure
|
45 | 45 | from temporalio.api.sdk.v1 import EnhancedStackTrace
|
46 | 46 | from temporalio.api.workflowservice.v1 import (
|
47 |
| - DescribeWorkflowExecutionRequest, |
48 | 47 | GetWorkflowExecutionHistoryRequest,
|
49 | 48 | ResetStickyTaskQueueRequest,
|
50 | 49 | )
|
@@ -6306,3 +6305,64 @@ async def test_workflow_sleep(client: Client):
|
6306 | 6305 | task_queue=worker.task_queue,
|
6307 | 6306 | )
|
6308 | 6307 | assert (datetime.now() - start_time) >= timedelta(seconds=1)
|
| 6308 | + |
| 6309 | + |
| 6310 | +@workflow.defn |
| 6311 | +class ConcurrentSleepsWorkflow: |
| 6312 | + @workflow.run |
| 6313 | + async def run(self) -> None: |
| 6314 | + sleeps_a = [workflow.sleep(0.1, summary=f"t{i}") for i in range(5)] |
| 6315 | + zero_a = workflow.sleep(0, summary="zero_timer") |
| 6316 | + zero_b = workflow.wait_condition( |
| 6317 | + lambda: False, timeout=0, timeout_summary="zero_wait" |
| 6318 | + ) |
| 6319 | + no_summ = workflow.sleep(0.1) |
| 6320 | + sleeps_b = [workflow.sleep(0.1, summary=f"t{i}") for i in range(5, 10)] |
| 6321 | + try: |
| 6322 | + await asyncio.gather( |
| 6323 | + *sleeps_a, zero_a, zero_b, no_summ, *sleeps_b, return_exceptions=True |
| 6324 | + ) |
| 6325 | + except asyncio.TimeoutError: |
| 6326 | + pass |
| 6327 | + |
| 6328 | + task_1 = asyncio.create_task(self.make_timers(100, 105)) |
| 6329 | + task_2 = asyncio.create_task(self.make_timers(105, 110)) |
| 6330 | + await asyncio.gather(task_1, task_2) |
| 6331 | + |
| 6332 | + async def make_timers(self, start: int, end: int): |
| 6333 | + await asyncio.gather( |
| 6334 | + *[workflow.sleep(0.1, summary=f"m_t{i}") for i in range(start, end)] |
| 6335 | + ) |
| 6336 | + |
| 6337 | + |
| 6338 | +async def test_concurrent_sleeps_use_proper_options(client: Client): |
| 6339 | + async with new_worker(client, ConcurrentSleepsWorkflow) as worker: |
| 6340 | + handle = await client.start_workflow( |
| 6341 | + ConcurrentSleepsWorkflow.run, |
| 6342 | + id=f"workflow-{uuid.uuid4()}", |
| 6343 | + task_queue=worker.task_queue, |
| 6344 | + ) |
| 6345 | + await handle.result() |
| 6346 | + resp = await client.workflow_service.get_workflow_execution_history( |
| 6347 | + GetWorkflowExecutionHistoryRequest( |
| 6348 | + namespace=client.namespace, |
| 6349 | + execution=WorkflowExecution(workflow_id=handle.id), |
| 6350 | + ) |
| 6351 | + ) |
| 6352 | + timer_summaries = [ |
| 6353 | + PayloadConverter.default.from_payload(e.user_metadata.summary) |
| 6354 | + if e.user_metadata.HasField("summary") |
| 6355 | + else "<no summ>" |
| 6356 | + for e in resp.history.events |
| 6357 | + if e.event_type == EventType.EVENT_TYPE_TIMER_STARTED |
| 6358 | + ] |
| 6359 | + assert timer_summaries == [ |
| 6360 | + *[f"t{i}" for i in range(5)], |
| 6361 | + "zero_timer", |
| 6362 | + "<no summ>", |
| 6363 | + *[f"t{i}" for i in range(5, 10)], |
| 6364 | + *[f"m_t{i}" for i in range(100, 110)], |
| 6365 | + ] |
| 6366 | + |
| 6367 | + # Force replay with a query to ensure determinism |
| 6368 | + await handle.query("__temporal_workflow_metadata") |
0 commit comments