Add azure-functions-durable v2: a durabletask-based rewrite of Durable Functions for Python - #155
Conversation
- Still needs eventSent and eventRecieved implementations
- Add new_uuid method to OrchestrationContext for deterministic replay-safe UUIDs - Fix entity locking behavior for Functions - Align _RuntimeOrchestrationContext param names with OrchestrationContext - Remap __init__.py files for new module - Update version to 0.0.1dev0 - Add docstrings to missing methods - Move code for executing orchestrators/entities to DurableFunctionsWorker - Add function metadata to triggers for detection by extension
…ions-support # Conflicts: # durabletask/client.py # durabletask/internal/shared.py # durabletask/worker.py # pyproject.toml
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 103 out of 106 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
azure-functions-durable/azure/durable_functions/orchestrator.py:33
self.durable_contextis assigned inhandle()without being declared/initialized in__init__. This creates a dynamic attribute that’s easy to miss for readers and type checkers (and can trip strict analysis). Initialize it in__init__with an explicit type so the instance surface is clear and stable.
The e2e harness writes each sample app's 'func start' output to <app>/_func_host.log, but only folds it into an exception on startup failures -- runtime 500s (e.g. durable operations failing after the host is up) leave the real host/worker error invisible in the CI log. Upload the host logs on failure so the durable-extension/worker error is retrievable for diagnosis.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 103 out of 106 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (3)
azure-functions-durable/azure/durable_functions/orchestrator.py:33
Orchestrator.handle()assignsself.durable_context, but the attribute is never declared in__init__. With the repo’s strict pyright config for this package, this will be flagged as an unknown attribute and also makes the instance shape unclear to readers. Initializedurable_contextin__init__(e.g. toNone) with an explicit type.
azure-functions-durable/azure/durable_functions/internal/converters.py:85- Same as above: this
issubclass(...)call will raiseTypeErrorfor non-class annotations (e.g.Optional[...]), which can break function indexing. Wrap it in atry/except TypeErrorand returnFalsewhen the annotation isn’t a class.
azure-functions-durable/CHANGELOG.md:13 - This changelog doesn’t follow the repo’s established convention of recording user-facing changes under a
## Unreleasedheading (see rootCHANGELOG.md). Even for a new package, having## Unreleasedat the top keeps the release process consistent and prevents future entries from being added directly under a released version section.
## 2.0.0b1
First preview (beta) release of `azure-functions-durable` 2.x — a ground-up
rewrite of the Azure Durable Functions Python SDK built on top of the
[`durabletask`](https://pypi.org/project/durabletask/) SDK. This is a preview
release; APIs may change before the stable 2.0.0.
The Durable Functions host client-config JSON can send fields explicitly as null (observed with maxGrpcMessageSizeInBytes on newer extension bundles) rather than omitting them. dict.get(key, default) only substitutes the default for absent keys, so a present-but-null value returned None -- crashing the 'maxGrpcMessageSizeInBytes > 0' guard in __init__ (TypeError: '>' not supported between NoneType and int) and failing every durable-client binding decode with a 500. Parse every field with 'client.get(key) or default' so an explicit null (like a missing key) collapses to its falsy default. Diagnosed from the e2e func host log; add regression tests for a single null field and for all fields sent as null.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 103 out of 106 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
azure-functions-durable/CHANGELOG.md:8
- This changelog is missing an
## Unreleasedsection. Repo policy expects user-facing changes to be documented under## Unreleased, and having the section present (even if empty initially) prevents future changes from being added directly to a released version heading.
## 2.0.0b1
durabletask/scheduled/models.py:418
ScheduleState.to_json()changes the persisted wire shape ofScheduleConfiguration(now always a plain mapping instead of a nested object/envelope). This is user-visible for anyone persisting schedule entity state or depending on the serialized JSON shape, so it should be called out in the coreCHANGELOG.mdunder## Unreleased.
…m/andystaples/durabletask-python into andystaples/add-functions-support
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 103 out of 106 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
azure-functions-durable/azure/durable_functions/orchestrator.py:33
Orchestrator.handle()assignsself.durable_context, but the instance variable is never declared/initialized. With the package's strict pyright settings, this is likely to be reported as an uninitialized/unknown instance member, and it also makes the attribute shape harder to reason about for consumers/tests.
Summary
Introduces
azure-functions-durable2.x as a new sub-package in this repository — a ground-up rewrite of the Azure Durable Functions Python SDK, built on top of thedurabletaskSDK. Existing v1 apps keep working through a compatibility layer, while new apps can adopt durabletask-native APIs directly.Why build on durabletask
The 1.x SDK implemented the Durable Functions out-of-process model directly, with its own orchestration action/state model and a JSON protocol tailored to the classic Durable Functions host extension. 2.x instead builds on the
durabletaskruntime — the same gRPC-based core that powers the Durable Task Scheduler (DTS) and the modern Durable Functions host. That means:What's included
DFApp/Blueprint(the Python v2 model).def orchestrator(ctx, input)) and class-based entities (DurableEntity), alongside supported v1-style single-argument functions.DurableOrchestrationContext/DurableEntityContext, deprecatedDurableOrchestrationClientmethod aliases (emittingDeprecationWarning), return-type wrappers (DurableOrchestrationStatus,PurgeHistoryResult,EntityStateResponse),HttpManagementPayload,EntityId,RetryOptions, and thecall_httpdurable HTTP API.rewind_orchestration, plus opt-inDFApp.configure_scheduled_tasks()andDFApp.configure_history_export().azure-functions-durablepackage, unit and end-to-end test suites, and strict pyright type-checking for the new package.Programming models supported
def o(ctx, input)def e(ctx, input)/DurableEntityclassdef o(context)def e(context)Breaking changes vs.
azure-functions-durable1.xfunction.jsonprogramming model is not supported.schedule_new_orchestration,get_orchestration_state,wait_for_orchestration_completion); the v1 names remain as deprecated aliases.Status
Preview (
2.0.0b1). APIs may change before the stable2.0.0. See the package CHANGELOG for the full set of additions, compatibility notes, and known limitations.