Skip to content

Commit 8db4510

Browse files
committed
CHANGELOG summarization
1 parent f0ea403 commit 8db4510

1 file changed

Lines changed: 26 additions & 81 deletions

File tree

CHANGELOG.md

Lines changed: 26 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,98 +12,46 @@ ADDED
1212
- Added a pluggable `DataConverter` (`durabletask.serialization`) accepted by
1313
`TaskHubGrpcWorker`, `TaskHubGrpcClient`, and `AsyncTaskHubGrpcClient` via a
1414
`data_converter` argument. Every payload boundary (inputs, outputs, events,
15-
custom status, entity state) routes through it. The default
15+
custom status, entity state) routes through it, so one converter controls how
16+
Python values become JSON and how they are reconstructed. The default
1617
`JsonDataConverter` preserves existing behavior, so a custom converter (for
17-
example one backed by pydantic) is opt-in. Custom objects can opt in via a
18-
`to_json()` hook and a `from_json(value)` classmethod.
19-
- `OrchestrationContext.call_activity`, `call_sub_orchestrator`, and
20-
`call_entity` accept an optional `return_type`, and `wait_for_external_event`
21-
accepts an optional `data_type`. When provided, the result/event payload is
22-
reconstructed as that type (dataclasses — including nested dataclass,
23-
`Optional`, `list`, `dict`/`Mapping`, and `tuple` fields — and
24-
`from_json()`-capable types) and the returned task is typed accordingly (e.g.
25-
`call_activity(..., return_type=Foo)` yields `CompletableTask[Foo]`). When
26-
omitted, the raw deserialized JSON is returned as before.
27-
- Inbound payloads are reconstructed from function type annotations. When an
28-
orchestrator, activity, or entity operation annotates its input parameter (or
29-
an activity its return value) with a dataclass or `from_json()`-capable type,
30-
the payload is reconstructed as that type. Builtins and unannotated/unknown
31-
types are passed through unchanged. An explicit `return_type` takes precedence
32-
over a discovered annotation.
33-
- Added typed accessors to `client.OrchestrationState`: `get_input()`,
34-
`get_output()`, and `get_custom_status()` each accept an optional
35-
`expected_type` and deserialize the corresponding payload, reconstructing
36-
dataclasses and `from_json()`-capable types. The raw `serialized_*` fields are
37-
retained.
38-
- Objects exposing a `to_json()` method are now JSON-serializable when passed as
39-
activity/orchestrator inputs or outputs.
40-
- `enum.Enum` values now serialize (to their underlying `.value`) and, when a
41-
target type is supplied, deserialize back to the enum member. This covers
42-
string-valued and other non-`int` enums as activity/orchestrator/entity inputs
43-
and outputs, including as dataclass fields and inside `list` / `dict` /
44-
`tuple` containers. (`IntEnum` / `IntFlag` already serialized as integers.)
45-
- A `from_json()` classmethod may now optionally accept the active
46-
`DataConverter` as a second parameter (`from_json(cls, value, converter)`),
47-
letting it reconstruct nested typed values via `converter.coerce(...)` /
48-
`converter.deserialize(...)`. The single-argument form remains supported.
49-
- `DataConverter` now exposes an overridable `can_reconstruct(target_type)`
50-
method that controls which annotated input/return types the SDK reconstructs
51-
on the inbound path. A custom converter can override it to recognize its own
52-
types (for example `pydantic.BaseModel` subclasses), so that orchestrator /
53-
activity / entity inputs annotated with those types are reconstructed by the
54-
converter instead of arriving as raw JSON. The default behavior is unchanged
55-
(dataclasses and `from_json()`-capable types, plus `Optional` / `list`
56-
wrappers, are reconstructable; builtins are not).
57-
- Added `EntityMetadata.get_typed_state(intended_type=...)`, which deserializes
58-
the entity's persisted state and reconstructs dataclasses and
59-
`from_json()`-capable types. The existing `get_state()` is unchanged: with no
60-
argument it returns the raw serialized JSON payload, and `get_state(some_type)`
61-
applies constructor-based coercion (`some_type(raw)`).
62-
- Entity runtime state retrieval (`EntityContext.get_state(intended_type=...)` /
63-
`DurableEntity.get_state(...)`) now also reconstructs dataclasses and
64-
`from_json()`-capable types, in addition to the existing constructor-based
65-
coercion.
18+
example one backed by pydantic) is fully opt-in.
19+
- Custom objects can participate in serialization by exposing a `to_json()`
20+
method and a `from_json(value)` classmethod. Both are honored recursively, so
21+
nested custom objects round-trip through their own hooks.
22+
- Payloads are reconstructed into a caller-supplied type — dataclasses
23+
(including nested fields), `from_json()`-capable types, and `enum.Enum`
24+
members, recursing through `list`, `dict`, `tuple`, and `Optional`/`Union`
25+
hints. The type comes from a function's annotations, from an explicit
26+
`return_type` on `call_activity` / `call_sub_orchestrator` / `call_entity`
27+
(or `data_type` on `wait_for_external_event`), or from the typed accessors
28+
`get_input()` / `get_output()` / `get_custom_status()` on
29+
`client.OrchestrationState` and `EntityMetadata.get_typed_state(...)`. It is
30+
never inferred from the payload. Which annotated types are eligible is decided
31+
by the converter via the overridable `DataConverter.can_reconstruct(...)`; a
32+
custom converter can override it to recognize its own types (for example
33+
`pydantic.BaseModel` subclasses).
6634

6735
CHANGED
6836

6937
- Custom objects (dataclasses, `SimpleNamespace`, namedtuples) are now
7038
serialized as plain JSON. Decoding such a payload *without* a type hint now
7139
yields a plain `dict` (previously a `SimpleNamespace`; a namedtuple now
72-
round-trips as a JSON array). To get the original type back, pass the new
73-
`return_type` / `data_type` arguments, annotate the consuming function's
74-
parameter or return type, or use the typed client accessors. Payloads produced
75-
by older SDK versions still deserialize — including into a `SimpleNamespace`
76-
when no type is supplied — so in-flight orchestrations continue to replay
77-
across an upgrade.
40+
round-trips as a JSON array). To get the original type back, supply a type via
41+
one of the mechanisms above. Payloads produced by older SDK versions still
42+
deserialize — including into a `SimpleNamespace` when no type is supplied — so
43+
in-flight orchestrations continue to replay across an upgrade.
7844
- JSON serialization failures now raise a `TypeError` that chains the original
7945
error (`__cause__`) and names the offending type.
8046
- `EntityContext.get_state()` / `DurableEntity.get_state()` now return a freshly
8147
reconstructed value on every call rather than a reference to a single cached
82-
object. As a result, mutating a value returned by `get_state()` in place no
83-
longer affects the persisted entity state — write the change back with
84-
`set_state()` to persist it. The entity's state is also serialized eagerly at
85-
`set_state()` time, so a value that cannot be serialized surfaces the error
86-
inside the failing operation (which rolls back) instead of after the batch has
87-
run.
48+
object, so mutating the returned value in place no longer affects persisted
49+
state — write it back with `set_state()`. State is also serialized eagerly at
50+
`set_state()` time, so a non-serializable value fails inside the operation
51+
(which rolls back) instead of after the batch has run.
8852

8953
FIXED
9054

91-
- A dataclass or `SimpleNamespace` that defines a `to_json()` hook now uses it
92-
when serialized. Previously the built-in dataclass / `SimpleNamespace`
93-
handling ran first, so the hook was ignored — and a dataclass with a field
94-
that was not JSON-serializable on its own would fail to serialize even when it
95-
provided a `to_json()` hook to handle that field. The serialize side now
96-
prefers `to_json()`, mirroring the deserialize side, which already prefers
97-
`from_json()`.
98-
- Nested `to_json()` hooks are now honored when an object is serialized inside a
99-
dataclass. Custom objects (including nested dataclasses with their own
100-
`to_json()`) are now encoded recursively instead of being flattened to their
101-
raw fields, so values that reshape themselves via `to_json()` round-trip
102-
correctly.
103-
- Type-directed deserialization now recurses into `dict`/`Mapping` values and
104-
`tuple` elements, in addition to the existing `list`, `Optional`/`Union`, and
105-
dataclass-field recursion. A `dict[str, Foo]` or `tuple[Foo, ...]` hint now
106-
reconstructs the contained `Foo` values.
10755
- Falsy entity states (`0`, `""`, `[]`, `{}`) are no longer dropped when an
10856
entity batch is persisted. Previously a falsy current state was treated as
10957
"no state" and written as `None`, effectively deleting it; only an actual
@@ -127,9 +75,6 @@ subclassing the public abstract types — may need to update their code:
12775
and `wait_for_external_event` gained new keyword-only parameters
12876
(`return_type` / `data_type`). Subclasses overriding these methods should add
12977
the parameter to match the base signature.
130-
- `client.OrchestrationState` gained a non-public `_data_converter` field
131-
(excluded from equality and `repr`). Code constructing `OrchestrationState`
132-
positionally should pass it via the new field or rely on its default.
13378

13479
## v1.6.0
13580

0 commit comments

Comments
 (0)