@@ -7,6 +7,99 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77
88## Unreleased
99
10+ ## v1.7.0
11+
12+ ADDED
13+
14+ - Added ` durabletask.scheduled ` , a recurring schedule feature built on durable
15+ entities. Use ` worker.configure_scheduled_tasks() ` to enable it on a worker,
16+ then manage schedules from the client via ` ScheduledTaskClient ` (and the
17+ per-schedule ` ScheduleClient ` ). Supports creating, describing, listing,
18+ updating, pausing, resuming, and deleting schedules with configurable
19+ ` interval ` , ` start_at ` , ` end_at ` , and ` start_immediately_if_late ` options.
20+ - Added an optional ` signal_time ` parameter to ` EntityContext.signal_entity `
21+ and ` DurableEntity.signal_entity ` , allowing an entity signal to be scheduled
22+ for future delivery.
23+ - Added an optional ` signal_time ` parameter to ` OrchestrationContext.signal_entity `
24+ and to the client ` signal_entity ` methods (sync and async), allowing entity
25+ signals to be scheduled for future delivery from orchestrations and clients.
26+ - Added a pluggable ` DataConverter ` (` durabletask.serialization ` ) accepted by
27+ ` TaskHubGrpcWorker ` , ` TaskHubGrpcClient ` , and ` AsyncTaskHubGrpcClient ` via a
28+ ` data_converter ` argument. Every payload boundary (inputs, outputs, events,
29+ custom status, entity state) routes through it, so one converter controls how
30+ Python values become JSON and how they are reconstructed. The default
31+ ` JsonDataConverter ` preserves existing behavior, so a custom converter (for
32+ example one backed by pydantic) is fully opt-in.
33+ - Custom objects can participate in serialization by exposing a ` to_json() `
34+ method and a ` from_json(value) ` classmethod. Both are honored recursively, so
35+ nested custom objects round-trip through their own hooks.
36+ - Payloads are reconstructed into a caller-supplied type — dataclasses
37+ (including nested fields), ` from_json() ` -capable types, and ` enum.Enum `
38+ members, recursing through ` list ` , ` dict ` , ` tuple ` , and ` Optional ` /` Union `
39+ hints. The type comes from a function's annotations, from an explicit
40+ ` return_type ` on ` call_activity ` / ` call_sub_orchestrator ` / ` call_entity `
41+ (or ` data_type ` on ` wait_for_external_event ` ), or from the typed accessors
42+ ` get_input() ` / ` get_output() ` / ` get_custom_status() ` on
43+ ` client.OrchestrationState ` and ` EntityMetadata.get_typed_state(...) ` . It is
44+ never inferred from the payload. Which annotated types are eligible is decided
45+ by the converter via the overridable ` DataConverter.can_reconstruct(...) ` ; a
46+ custom converter can override it to recognize its own types (for example
47+ ` pydantic.BaseModel ` subclasses).
48+
49+ CHANGED
50+
51+ - Custom objects (dataclasses, ` SimpleNamespace ` , namedtuples) are now
52+ serialized as plain JSON. Decoding such a payload * without* a type hint now
53+ yields a plain ` dict ` (previously a ` SimpleNamespace ` ; a namedtuple now
54+ round-trips as a JSON array). To get the original type back, supply a type via
55+ one of the mechanisms above. Payloads produced by older SDK versions still
56+ deserialize — including into a ` SimpleNamespace ` when no type is supplied — so
57+ in-flight orchestrations continue to replay across an upgrade.
58+ - JSON serialization failures now raise a ` TypeError ` that chains the original
59+ error (` __cause__ ` ) and names the offending type.
60+ - ` EntityContext.get_state() ` / ` DurableEntity.get_state() ` now return a freshly
61+ reconstructed value on every call rather than a reference to a single cached
62+ object. This changes v1.6.0 behavior: mutating the returned value in place no
63+ longer affects persisted state — write it back with ` set_state() ` . State is
64+ also serialized eagerly at ` set_state() ` time, so a non-serializable value
65+ fails inside the operation (which rolls back) instead of after the batch has
66+ run.
67+
68+ FIXED
69+
70+ - Falsy entity states (` 0 ` , ` "" ` , ` [] ` , ` {} ` ) are no longer dropped when an
71+ entity batch is persisted. Previously a falsy current state was treated as
72+ "no state" and written as ` None ` , effectively deleting it; only an actual
73+ ` None ` state now clears the persisted entity state.
74+
75+ DEPRECATED
76+
77+ - ` durabletask.internal.shared.to_json ` and ` durabletask.internal.shared.from_json `
78+ are deprecated and now emit a ` DeprecationWarning ` . Use a
79+ ` durabletask.serialization.DataConverter ` (for example the default
80+ ` JsonDataConverter ` ) instead. The functions continue to work for backwards
81+ compatibility.
82+
83+ BREAKING CHANGES (no runtime impact for typical users)
84+
85+ Most of these are type-level only: because the package ships ` py.typed ` ,
86+ consumers running strict type checkers (pyright/mypy) — or subclassing the
87+ public abstract types — may need to update their code. The constructor change
88+ below also affects callers who * directly* construct the named classes, which is
89+ uncommon since they are normally handed to you by the SDK.
90+
91+ - ` OrchestrationContext.call_activity ` , ` call_sub_orchestrator ` , ` call_entity ` ,
92+ and ` wait_for_external_event ` gained new keyword-only parameters
93+ (` return_type ` / ` data_type ` ). Subclasses overriding these methods should add
94+ the parameter to match the base signature.
95+ - ` EntityContext ` and ` EntityMetadata ` (and its ` from_entity_metadata ` /
96+ ` from_entity_response ` factories) now require a ` data_converter ` argument.
97+ These objects are normally constructed by the SDK — you receive an
98+ ` EntityContext ` in an entity function and an ` EntityMetadata ` from the client —
99+ so this only affects code that constructs them directly.
100+
101+ ## v1.6.0
102+
10103ADDED
11104
12105- Added overridable activity-dispatch hooks ` _on_activity_execution_started `
0 commit comments