Coverage for async_durable_execution/_operation/step.py: 100%
12 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-30 23:43 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-30 23:43 +0000
1"""User-facing durable step operation."""
3from __future__ import annotations
5import asyncio
6from collections.abc import Awaitable, Callable
7from typing import TypeVar
9from .._core import Duration, OperationSubType, SerDes
10from .._primitive.step import (
11 StepContext,
12 StepInterruptedError,
13 StepSemantics,
14 get_step_context,
15)
16from ..extension import get_extension_context
18T = TypeVar("T")
21def step(
22 func: Callable[[], Awaitable[T]],
23 *,
24 name: str | None = None,
25 retry_strategy: Callable[[Exception, int], Duration | None] | None = None,
26 step_semantics: StepSemantics = StepSemantics.AT_LEAST_ONCE_PER_RETRY,
27 serdes: SerDes | None = None,
28) -> asyncio.Task[T]:
29 """Run user code as a checkpointed durable step.
31 Durable steps are the main way to isolate non-deterministic work such as API
32 calls, clock reads, UUID generation, and database access from replayed code.
33 """
34 step_name = name if name is not None else getattr(func, "__name__", None)
35 return (
36 get_extension_context()
37 ._reserve_sdk_operation( # noqa: SLF001
38 step_name,
39 )
40 ._run_step( # noqa: SLF001
41 func,
42 sub_type=OperationSubType.STEP,
43 retry_strategy=retry_strategy,
44 step_semantics=step_semantics,
45 serdes=serdes,
46 )
47 )
50__all__ = [
51 "StepContext",
52 "StepInterruptedError",
53 "StepSemantics",
54 "get_step_context",
55 "step",
56]