Skip to content

Add azure-functions-durable v2: a durabletask-based rewrite of Durable Functions for Python - #155

Merged
berndverst merged 89 commits into
microsoft:mainfrom
andystaples:andystaples/add-functions-support
Jul 27, 2026
Merged

Add azure-functions-durable v2: a durabletask-based rewrite of Durable Functions for Python#155
berndverst merged 89 commits into
microsoft:mainfrom
andystaples:andystaples/add-functions-support

Conversation

@andystaples

@andystaples andystaples commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduces azure-functions-durable 2.x as a new sub-package in this repository — a ground-up rewrite of the Azure Durable Functions Python SDK, built on top of the durabletask SDK. 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 durabletask runtime — the same gRPC-based core that powers the Durable Task Scheduler (DTS) and the modern Durable Functions host. That means:

  • one shared orchestration/entity execution core, serialization pipeline, and retry/versioning implementation instead of a Functions-specific reimplementation;
  • Functions users can adopt durabletask-native APIs and patterns directly; and
  • less protocol drift between the Python worker and the durable backend.

What's included

  • Decorator programming model via DFApp / Blueprint (the Python v2 model).
  • durabletask-native authoring: two-argument orchestrators and entities (def orchestrator(ctx, input)) and class-based entities (DurableEntity), alongside supported v1-style single-argument functions.
  • v1 compatibility layer: DurableOrchestrationContext / DurableEntityContext, deprecated DurableOrchestrationClient method aliases (emitting DeprecationWarning), return-type wrappers (DurableOrchestrationStatus, PurgeHistoryResult, EntityStateResponse), HttpManagementPayload, EntityId, RetryOptions, and the call_http durable HTTP API.
  • New capabilities inherited from durabletask: rewind_orchestration, plus opt-in DFApp.configure_scheduled_tasks() and DFApp.configure_history_export().
  • Packaging & CI: the azure-functions-durable package, unit and end-to-end test suites, and strict pyright type-checking for the new package.

Programming models supported

Style Orchestrator Entity
durabletask-native def o(ctx, input) def e(ctx, input) / DurableEntity class
v1-compatible def o(context) def e(context)

Breaking changes vs. azure-functions-durable 1.x

  • Python 3.13+ is required (1.x supported 3.10+).
  • Decorator-only: the classic function.json programming model is not supported.
  • The OpenAI Agents integration has been removed.
  • Primary client and context APIs use durabletask names (e.g. schedule_new_orchestration, get_orchestration_state, wait_for_orchestration_completion); the v1 names remain as deprecated aliases.
  • Runtime target is the durabletask gRPC protocol (DTS / modern Durable Functions host) rather than the classic extension protocol.

Status

Preview (2.0.0b1). APIs may change before the stable 2.0.0. See the package CHANGELOG for the full set of additions, compatibility notes, and known limitations.

andystaples and others added 28 commits November 6, 2025 10:01
- 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
@andystaples
andystaples marked this pull request as ready for review June 25, 2026 16:30
Copilot AI review requested due to automatic review settings June 25, 2026 16:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_context is assigned in handle() 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.
Copilot AI review requested due to automatic review settings July 24, 2026 22:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() assigns self.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. Initialize durable_context in __init__ (e.g. to None) with an explicit type.
    azure-functions-durable/azure/durable_functions/internal/converters.py:85
  • Same as above: this issubclass(...) call will raise TypeError for non-class annotations (e.g. Optional[...]), which can break function indexing. Wrap it in a try/except TypeError and return False when 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 ## Unreleased heading (see root CHANGELOG.md). Even for a new package, having ## Unreleased at 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.
Copilot AI review requested due to automatic review settings July 24, 2026 22:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ## Unreleased section. 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 of ScheduleConfiguration (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 core CHANGELOG.md under ## Unreleased.

Comment thread eng/templates/build.yml
Copilot AI review requested due to automatic review settings July 27, 2026 05:44
berndverst
berndverst previously approved these changes Jul 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 103 out of 106 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 27, 2026 14:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 103 out of 106 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 27, 2026 14:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() assigns self.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.

@berndverst
berndverst merged commit c8522ec into microsoft:main Jul 27, 2026
23 checks passed
@andystaples
andystaples deleted the andystaples/add-functions-support branch July 27, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants