Skip to content

Commit efc27d6

Browse files
authored
docs(release): changelog, README, and copilot-instructions updates (#339)
1 parent fc4a7f7 commit efc27d6

2 files changed

Lines changed: 32 additions & 10 deletions

File tree

.github/copilot-instructions.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ Task<T> — Base: result, exception, isComplete, isFailed, parent r
113113
│ ├── RetryableTask — Policy-driven retries (exponential backoff)
114114
│ └── RetryHandlerTask — Custom retry handler function
115115
└── CompositeTask — Holds children with parent backlinks
116-
├── WhenAllTask — Completes when ALL children done; fails fast on first failure
116+
├── WhenAllTask — Completes when ALL children are terminal (waits for every child)
117117
└── WhenAnyTask — Completes when ANY child done
118118
```
119119

@@ -123,11 +123,15 @@ Task<T> — Base: result, exception, isComplete, isFailed, parent r
123123
**Important:** `CompositeTask` checks already-complete children in its constructor.
124124
A composite task can be **immediately complete upon construction** — callers must handle this.
125125

126-
### WhenAll Fail-Fast Behavior
126+
### WhenAll Wait-All Behavior
127127

128-
`WhenAllTask` marks itself complete on the **first** failed child. Other children may still
129-
be in flight. The `isComplete` guard prevents double-completion, but the mental model is:
130-
one failure = whole task fails immediately, remaining results ignored.
128+
`WhenAllTask` completes only when **every** child is terminal (`_completedTasks == _tasks.length`) —
129+
a failing child does **not** complete it early. This prevents a later failing sibling's `TaskFailed`
130+
from being dropped against an already-terminal instance (issue #301). `_exception` is set only at
131+
completion, so `isFailed` and `isComplete` flip together — otherwise `resume()` (which checks
132+
`isFailed` before `isComplete`) would throw into the generator before the other siblings finish,
133+
re-introducing fail-fast. On failure, all child exceptions are aggregated into an `AggregateError`
134+
whose message inlines each child message.
131135

132136
---
133137

packages/azure-functions-durable/README.md

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,13 @@ changed:
4040
**`client.startNew()` supports the `version` option.**
4141
- **Entity locking / critical sections moved to the core context.** v3's `context.df.lock(...)` /
4242
`context.df.isLocked()` and the `DurableLock` / `LockState` / `LockingRulesViolationError` exports
43-
are removed. Acquire locks with the core `context.entities.lockEntities(...entityIds)` (returns a
44-
`LockHandle` — call `release()`, ideally in a `finally`) and query with
45-
`context.entities.isInCriticalSection()`. Restoring the v3 `df.lock` / `isLocked` surface is tracked
46-
in [#317](https://github.com/microsoft/durabletask-js/issues/317).
43+
are removed. Locks live on the core-native `context.entities` surface, which the classic
44+
`{ df, log }` context does **not** expose — an orchestrator that needs locks must first migrate to
45+
the core-native orchestrator/context shape, then acquire locks with
46+
`context.entities.lockEntities(...entityIds)` (returns a `LockHandle` — call `release()`, ideally
47+
in a `finally`) and query with `context.entities.isInCriticalSection()`. Reintroducing the v3
48+
`df.lock` / `isLocked` surface is **not supported and not planned**
49+
([#317](https://github.com/microsoft/durabletask-js/issues/317), closed as not planned).
4750
- **`context.df.callHttp(...)` is restored** as a worker-side durable HTTP call
4851
([#318](https://github.com/microsoft/durabletask-js/issues/318)) — though **not** as a drop-in, fully
4952
v3-equivalent replacement: the known incompatibilities and behavior differences listed below are
@@ -106,6 +109,19 @@ changed:
106109
sync **generators** (`function*`) using `context.df.*` — are unaffected; convert any non-generator
107110
classic orchestrator to generator form, or to the core-native `ctx.*` API.
108111

112+
## Requirements
113+
114+
This provider reaches the Durable Task backend over the Functions host's **gRPC** channel, which
115+
exists only in newer durable-extension builds. Your app's `host.json` must reference one of:
116+
117+
- GA bundle — `Microsoft.Azure.Functions.ExtensionBundle` at **`[4.36.0, 5.0.0)`**, or
118+
- Preview bundle — `Microsoft.Azure.Functions.ExtensionBundle.Preview` at **`[4.29.0, 5.0.0)`**.
119+
120+
Earlier GA v4 bundles (**<= 4.32.0**) predate that gRPC endpoint, so orchestration starters **hang
121+
for ~60 seconds and time out with no error**. A fresh app on the default GA range (`[4.*, 5.0.0)`)
122+
resolves to the latest GA (>= 4.36.0) and works — the trap is an **explicit** pin at or below
123+
4.32.0.
124+
109125
## Getting started
110126

111127
```typescript
@@ -170,4 +186,6 @@ are `@deprecated`):
170186

171187
## Status
172188

173-
This package is an early preview (`4.0.0`); APIs may change before the stable release.
189+
This rewritten `durable-functions` v4 provider is in **preview**, published under the `preview` npm
190+
dist-tag — install it with `npm install durable-functions@preview`. APIs may change before the
191+
GA `4.0.0` release.

0 commit comments

Comments
 (0)