Skip to content

Commit fcb6e0a

Browse files
committed
Merge branch 'main' into filinto/asyncio
2 parents 4441156 + 3854b18 commit fcb6e0a

25 files changed

+1216
-770
lines changed

.github/workflows/pr-validation.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
strategy:
1818
fail-fast: false
1919
matrix:
20-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
20+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
2121

2222
steps:
2323
- uses: actions/checkout@v4
@@ -28,13 +28,13 @@ jobs:
2828
- name: Install dependencies
2929
run: |
3030
python -m pip install --upgrade pip
31-
pip install '.[dev]'
32-
- name: Lint with flake8
31+
pip install .[dev]
32+
- name: Lint with ruff
3333
run: |
34-
flake8 . --count --show-source --statistics --exit-zero
34+
ruff check
3535
- name: Pytest unit tests
3636
run: |
37-
pytest -m "not e2e" --verbose
37+
tox -e py${{ matrix.python-version }}
3838
# Sidecar for running e2e tests requires Go SDK
3939
- name: Install Go SDK
4040
uses: actions/setup-go@v5
@@ -45,7 +45,7 @@ jobs:
4545
run: |
4646
go install github.com/dapr/durabletask-go@main
4747
durabletask-go --port 4001 &
48-
pytest -m "e2e" --verbose
48+
tox -e py${{ matrix.python-version }}-e2e
4949
publish:
5050
needs: build
5151
if: startswith(github.ref, 'refs/tags/v')

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ install:
1313
gen-proto:
1414
curl -o durabletask/internal/orchestrator_service.proto https://raw.githubusercontent.com/dapr/durabletask-protobuf/refs/heads/main/protos/orchestrator_service.proto
1515
curl -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/dapr/durabletask-protobuf/commits?path=protos/orchestrator_service.proto&sha=main&per_page=1" | jq -r '.[0].sha' > durabletask/internal/PROTO_SOURCE_COMMIT_HASH
16-
pip install grpcio-tools==1.74.0
16+
# NOTE: remember to check/update pyproject.toml protobuf version to follow https://github.com/grpc/grpc/blob/v{{VERSION GRPC IO TOOL BELLOW}}/tools/distrib/python/grpcio_tools/setup.py
17+
pip install .[dev]
1718
python3 -m grpc_tools.protoc --proto_path=. --python_out=. --pyi_out=. --grpc_python_out=. ./durabletask/internal/orchestrator_service.proto
1819
rm durabletask/internal/*.proto
1920

README.md

Lines changed: 6 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,6 @@
66

77
This repo contains a Python client SDK for use with the [Durable Task Framework for Go](https://github.com/microsoft/durabletask-go) and [Dapr Workflow](https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-overview/). With this SDK, you can define, schedule, and manage durable orchestrations using ordinary Python code.
88

9-
> **🚀 Enhanced Async Features**: This fork includes comprehensive async workflow enhancements with advanced error handling, non-determinism detection, timeout support, and debugging tools. See [ASYNC_ENHANCEMENTS.md](./ASYNC_ENHANCEMENTS.md) for details.
10-
11-
## Quick Start - Async Workflows
12-
13-
For async workflow development, use the new `durabletask.aio` package:
14-
15-
```python
16-
from durabletask.aio import AsyncWorkflowContext
17-
from durabletask.worker import TaskHubGrpcWorker
18-
19-
async def my_workflow(ctx: AsyncWorkflowContext, name: str) -> str:
20-
result = await ctx.call_activity(say_hello, input=name)
21-
await ctx.sleep(1.0)
22-
return f"Workflow completed: {result}"
23-
24-
def say_hello(ctx, name: str) -> str:
25-
return f"Hello, {name}!"
26-
27-
# Register and run
28-
with TaskHubGrpcWorker() as worker:
29-
worker.add_activity(say_hello)
30-
worker.add_orchestrator(my_workflow)
31-
worker.start()
32-
# ... schedule workflows with client
33-
```
34-
359
⚠️ **This SDK is currently under active development and is not yet ready for production use.** ⚠️
3610

3711
> Note that this project is **not** currently affiliated with the [Durable Functions](https://docs.microsoft.com/azure/azure-functions/durable/durable-functions-overview) project for Azure Functions. If you are looking for a Python SDK for Durable Functions, please see [this repo](https://github.com/Azure/azure-functions-durable-python).
@@ -181,13 +155,6 @@ python3 -m pip install .
181155

182156
See the [examples](./examples) directory for a list of sample orchestrations and instructions on how to run them.
183157

184-
**Enhanced Async Examples:**
185-
- `async_activity_sequence.py` - Updated to use new `durabletask.aio` package
186-
- `async_fanout_fanin.py` - Updated to use new `durabletask.aio` package
187-
- `async_enhanced_features.py` - Comprehensive demo of all enhanced features
188-
- `async_non_determinism_demo.py` - Non-determinism detection demonstration
189-
- See [ASYNC_ENHANCEMENTS.md](./durabletask/aio/ASYNCIO_ENHANCEMENTS.md) for detailed examples and usage patterns
190-
191158
## Development
192159

193160
The following is more information about how to develop this project. Note that development commands require that `make` is installed on your local machine. If you're using Windows, you can install `make` using [Chocolatey](https://chocolatey.org/) or use WSL.
@@ -205,7 +172,7 @@ This will download the `orchestrator_service.proto` from the `microsoft/durablet
205172

206173
### Running unit tests
207174

208-
Unit tests can be run using the following command from the project root.
175+
Unit tests can be run using the following command from the project root.
209176
Unit tests _don't_ require a sidecar process to be running.
210177

211178
To run on a specific python version (eg: 3.11), run the following command from the project root:
@@ -216,7 +183,7 @@ tox -e py311
216183

217184
### Running E2E tests
218185

219-
The E2E (end-to-end) tests require a sidecar process to be running.
186+
The E2E (end-to-end) tests require a sidecar process to be running.
220187

221188
For non-multi app activities test you can use the Durable Task test sidecar using the following command:
222189

@@ -257,53 +224,16 @@ export DAPR_GRPC_HOST=localhost
257224
export DAPR_GRPC_PORT=50001
258225
```
259226

260-
#### GRPC Keepalive Configuration
261-
262-
Configure GRPC keepalive settings to maintain long-lived connections:
263-
264-
- `DAPR_GRPC_KEEPALIVE_ENABLED` - Enable keepalive (default: `false`)
265-
- `DAPR_GRPC_KEEPALIVE_TIME_MS` - Keepalive time in milliseconds (default: `120000`)
266-
- `DAPR_GRPC_KEEPALIVE_TIMEOUT_MS` - Keepalive timeout in milliseconds (default: `20000`)
267-
- `DAPR_GRPC_KEEPALIVE_PERMIT_WITHOUT_CALLS` - Permit keepalive without active calls (default: `false`)
268-
269-
Example:
270-
271-
```sh
272-
export DAPR_GRPC_KEEPALIVE_ENABLED=true
273-
export DAPR_GRPC_KEEPALIVE_TIME_MS=60000
274-
export DAPR_GRPC_KEEPALIVE_TIMEOUT_MS=10000
275-
```
276-
277-
#### GRPC Retry Configuration
278-
279-
Configure automatic retry behavior for transient failures:
280-
281-
- `DAPR_GRPC_RETRY_ENABLED` - Enable automatic retries (default: `false`)
282-
- `DAPR_GRPC_RETRY_MAX_ATTEMPTS` - Maximum retry attempts (default: `4`)
283-
- `DAPR_GRPC_RETRY_INITIAL_BACKOFF_MS` - Initial backoff in milliseconds (default: `100`)
284-
- `DAPR_GRPC_RETRY_MAX_BACKOFF_MS` - Maximum backoff in milliseconds (default: `1000`)
285-
- `DAPR_GRPC_RETRY_BACKOFF_MULTIPLIER` - Backoff multiplier (default: `2.0`)
286-
- `DAPR_GRPC_RETRY_CODES` - Comma-separated status codes to retry (default: `UNAVAILABLE,DEADLINE_EXCEEDED`)
287-
288-
Example:
289-
290-
```sh
291-
export DAPR_GRPC_RETRY_ENABLED=true
292-
export DAPR_GRPC_RETRY_MAX_ATTEMPTS=5
293-
export DAPR_GRPC_RETRY_INITIAL_BACKOFF_MS=200
294-
```
295227

296228
#### Async Workflow Configuration
297229

298230
Configure async workflow behavior and debugging:
299231

300-
- `DAPR_WF_DEBUG` or `DT_DEBUG` - Enable debug mode for workflows (set to `true`)
301232
- `DAPR_WF_DISABLE_DETECTION` - Disable non-determinism detection (set to `true`)
302233

303234
Example:
304235

305236
```sh
306-
export DAPR_WF_DEBUG=true
307237
export DAPR_WF_DISABLE_DETECTION=false
308238
```
309239

@@ -406,7 +336,7 @@ try:
406336
except Exception as e:
407337
# handle failure branch
408338
...
409-
```
339+
```
410340

411341
Or capture with gather:
412342

@@ -416,6 +346,7 @@ if isinstance(res[0], Exception):
416346
...
417347
```
418348

349+
419350
- Sub-orchestrations (function reference or registered name):
420351
```python
421352
out = await ctx.call_sub_orchestrator(child_fn, input=payload)
@@ -427,27 +358,6 @@ out = await ctx.call_sub_orchestrator(child_fn, input=payload)
427358
now = ctx.now(); rid = ctx.random().random(); uid = ctx.uuid4()
428359
```
429360

430-
- Workflow metadata and info:
431-
```python
432-
# Read-only info snapshot (Temporal-style convenience)
433-
info = ctx.info
434-
print(f"Workflow: {info.workflow_name}, Instance: {info.instance_id}")
435-
print(f"Replaying: {info.is_replaying}, Suspended: {info.is_suspended}")
436-
437-
# Or access properties directly
438-
instance_id = ctx.instance_id
439-
is_replaying = ctx.is_replaying
440-
is_suspended = ctx.is_suspended
441-
workflow_name = ctx.workflow_name
442-
parent_instance_id = ctx.parent_instance_id # for sub-orchestrators
443-
444-
# Execution info (internal metadata if provided by sidecar)
445-
exec_info = ctx.execution_info
446-
447-
# Tracing span IDs
448-
span_id = ctx.orchestration_span_id # or ctx.workflow_span_id (alias)
449-
```
450-
451361
- Workflow metadata/headers (async only for now):
452362
```python
453363
# Attach contextual metadata (e.g., tracing, tenant, app info)
@@ -532,8 +442,8 @@ contact [[email protected]](mailto:[email protected]) with any additio
532442

533443
## Trademarks
534444

535-
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
536-
trademarks or logos is subject to and must follow
445+
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
446+
trademarks or logos is subject to and must follow
537447
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
538448
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
539449
Any use of third-party trademarks or logos are subject to those third-party's policies.

dev-requirements.txt

Whitespace-only changes.

durabletask/aio/__init__.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
"""Async workflow primitives (aio namespace).
2-
3-
This package contains the async implementation previously under
4-
`durabletask.asyncio`, now moved to `durabletask.aio` for naming
5-
consistency.
6-
"""
7-
81
# Deterministic utilities
92
from durabletask.deterministic import (
103
DeterminismSeed,
@@ -53,7 +46,10 @@
5346
sandbox_strict,
5447
)
5548

49+
from .client import AsyncTaskHubGrpcClient
50+
5651
__all__ = [
52+
"AsyncTaskHubGrpcClient",
5753
# Core classes
5854
"AsyncWorkflowContext",
5955
"WorkflowInfo",

0 commit comments

Comments
 (0)