Align durable Parallel/Map failure semantics with the JS SDK#2465
Merged
Conversation
Full JS-SDK parity for ParallelAsync/MapAsync (preview 0.x, breaking): - No auto-throw: both operations always return IBatchResult; failure surfaces via CompletionReason/HasFailure/ThrowIfError(), matching JS/Python/Java. - Removed ParallelException and MapException. - Empty CompletionConfig() is now fail-fast (any failure resolves FailureToleranceExceeded), matching JS/Python getCompletionReason. AllCompleted() redefined to ToleratedFailureCount = int.MaxValue so it stays lenient. Map default flipped from AllCompleted() to AllSuccessful(). - MapConfig is now generic (MapConfig<TItem>) so ItemNamer is typed Func<TItem, int, string> instead of Func<object, int, string>. Updates all consumers (context, config, ops, docs, analyzer stubs, shared workflows/scenarios, unit + integration tests). Also corrects a stale docs claim that NestingType.Flat throws NotSupportedException. 405 unit tests and 153 testing-shared tests pass.
philasmar
approved these changes
Jul 8, 2026
normj
approved these changes
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings
ParallelAsync/MapAsyncinAmazon.Lambda.DurableExecutionto full parity with the JS reference SDK's concurrent-operation failure semantics. Verified against all four SDK clones (JS/Python/Java) and the canonicalaws-durable-execution-docsspec.Preview (0.x) — intentionally backward-incompatible.
Changes
ParallelAsync/MapAsyncnow always returnIBatchResult. Failure surfaces viaCompletionReason/HasFailure/ThrowIfError()— matching JS, Python, and Java. Previously the failure-tolerance path threw.ParallelExceptionandMapException. No SDK has a batch-level exception;ThrowIfError()throws the individual child error.CompletionConfig()is now fail-fast (any failure →FailureToleranceExceeded), matching JS/PythongetCompletionReason.AllCompleted()is redefined toToleratedFailureCount = int.MaxValueso it stays lenient after the flip. Map's default completion flipped fromAllCompleted()toAllSuccessful(), matching Parallel and JS/Python.MapConfigis now generic (MapConfig<TItem>) soItemNameris typedFunc<TItem, int, string>instead ofFunc<object, int, string>.Also corrects a stale doc statement that
NestingType.FlatthrowsNotSupportedException(Flat is implemented).New user experience (before → after)
Handling failures — no more
try/catchon the batch operationBefore, a failure that exceeded the tolerance threw a batch-level exception, so you had two different error channels to reason about (the thrown
ParallelException/MapExceptionand the per-itemFailedlist). Now the operation never throws — you always get anIBatchResultback and inspect it.MapAsyncnow defaults to fail-fast (likeParallelAsyncand JS/Python)Previously
MapAsyncran every item regardless of failures by default. Now any item failure resolves the map withFailureToleranceExceeded. To keep the old run-everything behavior, opt in withAllCompleted().MapConfigis now generic —ItemNameris strongly typedAn empty/default
CompletionConfig()is now fail-fastMigration checklist
catch (ParallelException)/catch (MapException)— replace withif (batch.HasFailure)orbatch.ThrowIfError().new MapConfig { ... }→new MapConfig<TItem> { ... }; drop the cast inItemNamer.MapAsyncrunning every item, setCompletionConfig = CompletionConfig.AllCompleted().new CompletionConfig()— it is now fail-fast, not lenient.Cross-SDK context
The table lists each SDK's default in that SDK's own vocabulary, with the resulting behavior in parentheses:
all_successful(fail-fast)CompletionConfig(fail-fast)allCompleted()(lenient)allCompleted()(lenient).get()summary API)AllSuccessful()(fail-fast)AllSuccessful()(fail-fast).NET's fail-fast default matches JS on both operations and matches Python on Map (Python's Parallel default,
all_successful, is also fail-fast, so the behavior lines up there too — only the spelling differs). Java remains an outlier by its own design: both its defaults are lenient (allCompleted()), and it has noItemNamer.Testing
TreatWarningsAsErrorson, 0 warnings).Change file
.autover/changes/durable-concurrent-js-parity.json(Minor, preview).