Skip to content

feat: add distributed map operation - #1

Draft
nvasiu wants to merge 37 commits into
mainfrom
feat/map-run
Draft

nvasiu wants to merge 37 commits into
mainfrom
feat/map-run

Conversation

@nvasiu

@nvasiu nvasiu commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the distributed map operation (ctx.distributed_map) to the Python SDK:
A map run processes a bounded dataset in parallel. A customer starts a map run from a durable function, naming a source to read items from, a processor function to invoke per batch, and concurrency, retry, and failure settings. The service reads items from the source, groups them into batches, invokes the processor for each batch, retries failures, tracks progress, routes successful results and failed items to destinations, and reports completion.

Changes

concurrency/models.py

  • DistributedMapSummary: what ctx.distributed_map returns, describes run's overall outcome.
  • DistributedMapResult: returned from ctx.distributed_map when inline result collection is enabled. Contains individual map run item outcomes.
  • DistributedMapResultItem and DistributedMapItemError: represent a single item's result / error

config.py

  • DistributedMapConfig: optional settings for distributed map
  • DistributedMapSource: describes where map run items come from (inline list, S3, or a custom reader)
  • DistributedMapProcessor: describes the Lambda that processes items and how outcomes are reported back
  • ProcessorRetryConfig: configures how failing items are retried
  • DistributedMapCompletionConfig: defines item failure thresholds for marking the overall map run failed
  • SuccessDestination, FailureDestination, DistributedMapDestinationConfig, DistributedMapDestination: for routing successful and failed item records to S3

context.py

  • ctx.distributed_map: the entry point a customer calls to run a distributed map

distributed_map_helpers.py

  • Authoring wrappers: let a customer write a plain function and have it work as a processor Lambda without hand-writing the item or batch protocol, including durable-execution variants and a reader
  • Currently placed in a separate top level file, can be moved elsewhere.

operation/distributed_map.py

  • The executor: drives the operation so the caller's function suspends while the run executes and resumes with the finished outcome, and surfaces a clear error if the operation itself fails

lambda_service.py

  • Carries the operation and its results to and from the backend service

state.py

  • Stores the run's outcome in the durable execution state so it persists across suspend and resume

exceptions.py

  • DistributedMapError: the error a customer catches when a run or an item fails

__init__.py

  • Makes the distributed-map types importable by customers as public API

Tests

tests/operation/distributed_map_test.py
tests/context_test.py

  • Core operation unit tests: executor, config/argument validation, wire round trips, result types

tests/e2e/distributed_map_int_test.py

  • End to end ctx.distributed_map tests, mocking backend responses: suspend / resume, collect results, throw on failure

tests/distributed_map_helpers_test.py

  • Authoring wrapper tests: checking that they process items, report failures, reject bad inputs

tests/e2e/distributed_map_helpers_int_test.py

  • End to end authoring wrapper tests.

TODO

  • When the model changes and distributed map implementation are complete in the durable service backend, these SDK changes need to be verified against them.

Future Tasks

  • Add distributed map to the local emulator (in the testing package).
    • When this is done, we can add full end to end tests using the emulator.
  • Add distributed map examples to the examples package.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@nvasiu
nvasiu deployed to ai-pr-review August 20, 2026 21:10 — with GitHub Actions Active
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 20, 2026 21:10 — with GitHub Actions Failure
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 20, 2026 21:10 — with GitHub Actions Failure
@nvasiu
nvasiu deployed to ai-pr-review August 20, 2026 21:27 — with GitHub Actions Active
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 20, 2026 21:27 — with GitHub Actions Failure
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 20, 2026 21:27 — with GitHub Actions Failure
* feat(plugin): report incomplete user function outcomes


---------

Co-authored-by: Alex Wang <wangyb@amazon.com>

@yaythomas yaythomas left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this won't work against installed botocore yet. the checkpoint goes through the boto3 lambda client, which rejects unknown structure members at param-validation time, so every ctx.distributed_map call fails client-side with ParamValidationError until a botocore release ships the distributed-map model.

bump the boto3 minimum pin once this available. so the failure mode becomes an install-time constraint instead of a runtime one.

WAIT = "WAIT"
CALLBACK = "CALLBACK"
CHAINED_INVOKE = "CHAINED_INVOKE"
DISTRIBUTED_MAP = "DISTRIBUTED_MAP"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

any other changes necessary here to wire the events in for plugin? are there specific events?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Looks like no operation type specific hooks anywhere, DISTRIBUTED_MAP will call the same hooks as invoke/step.

But there are experimental result/error fields on OperationInfo that won't get populated for dmaps. Do we want to do that as part of this PR?

zhongkechen and others added 4 commits August 21, 2026 10:07
* ci: schedule long-running OTel conformance tests

* ci: bump OTel orchestrator pin to latest conformance commit

---------

Co-authored-by: Ayushi Ahjolia <aahjolia@amazon.com>
@nvasiu
nvasiu deployed to ai-pr-review August 22, 2026 00:10 — with GitHub Actions Active
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 22, 2026 00:10 — with GitHub Actions Failure
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 22, 2026 00:10 — with GitHub Actions Failure
@nvasiu
nvasiu deployed to ai-pr-review August 26, 2026 17:01 — with GitHub Actions Active
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 26, 2026 17:01 — with GitHub Actions Failure
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 26, 2026 17:01 — with GitHub Actions Failure
@nvasiu
nvasiu deployed to ai-pr-review August 26, 2026 19:04 — with GitHub Actions Active
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 26, 2026 19:04 — with GitHub Actions Failure
@nvasiu
nvasiu had a problem deploying to ai-pr-review-runtime August 26, 2026 19:04 — with GitHub Actions Failure
Alex Wang and others added 2 commits August 27, 2026 12:53
Preserve failed invocation results when Lambda returns FAILED without an
error payload. The local test runner now reports a failed execution
instead of treating the result as successful.

Expose terminal execution status on durable function test results and
align cloud runner polling with the STOPPED terminal status.
Alex Wang and others added 20 commits September 1, 2026 22:06
Port of the JS SDK's workflowInsight() plugin as a new package,
aws-durable-execution-sdk-python-insight: listens to the SDK's
instrumentation hooks and emits one curated WorkflowInsight record
(schemaVersion 1.0, JS-identical camelCase wire format) per execution
through configurable exporters (LambdaLogExporter default with the
operationsByName summary; S3Exporter with the per-occurrence operations
array). Mirrors the JS emit model: on-complete/on-failure/on-change
scheduling with coalescing, ARN-hash sampling, content configuration
(input/output omission and transforms, include_errors, per-operation
result opt-in), two-phase truncation, top-level vs full-tree operation
detail, and unnamed-operation dropping. Uses the invocation-hook
execution_input/execution_result fields introduced in aws#616.
Convert the single exporters.py module into an exporters/ package with one
module per destination (lambda_log_exporter, s3_exporter) plus a private
_common helper, mirroring the JS package's src/exporters/ layout so the set
can grow to full parity (DynamoDB, Firehose, CloudWatch Logs, ...) without a
single file accreting every backend's imports. Public import paths are
unchanged: 'from ...insight import S3Exporter' and
'from ...insight.exporters import S3Exporter' both still resolve. Adds
test_exporters.py covering both exporters (previously untested).
- Seed operation map from InvocationStart/End/OperationChange snapshots
  instead of reconstructing via per-operation hooks (cold-resume correctness)
- on-change mode emits an updated RUNNING record on each change
- Drop on_operation_end/_current_execution_arn heuristic; key strictly by
  execution_arn to prevent cross-execution contamination
- Clear per-execution state after every invocation end (bounded, no leak on
  suspend/retry/sampled-out)
- Default to LambdaLogExporter when exporters omitted or empty
- Always adopt authoritative execution_start_time on resume
- Correct hook enum imports (InvocationStatus/OperationType from plugin)
- Register insight tests in root testpaths and mypy type-checks
- 1: wire aws-durable-execution-sdk-python-insight into both the build and
  publish matrices of pypi-publish.yml; the generic legal-file verifier runs
  through the build matrix unchanged (LICENSE+NOTICE confirmed in whl+sdist).
- 3: in on-change mode, a PENDING/RETRY invocation end maps to RUNNING and now
  omits endTime/durationMs; only terminal SUCCEEDED/FAILED records carry an end
  time (plus output/error).
- 4: fix the README usage example to import WorkflowInsightConfig and call
  workflow_insight(WorkflowInsightConfig(exporters=[...])); add a smoke test for
  the documented call shape.
- 5: back EmitMode/OperationDetail with StrEnum (JS-style values); config fields
  use Literal input typing and __post_init__ normalizes accepted strings to enum
  members (invalid dynamic strings raise ValueError); export the enums.
- 6: add a checked-in tests/e2e local-runner integration test that drives the
  real durable_execution/PluginExecutor lifecycle through a suspend/resume wait
  and asserts the terminal record includes the prior step and completed wait.

Comment 2 (asynchronous export scheduling) is intentionally deferred; no async
queue/worker/coalescing/drain was added.
Address the S3 partition-validation review comment on PR aws#632. Add a
public S3Partitioning(StrEnum) (DATE=date, FUNCTION_NAME=function-name,
NONE=none) in the s3_exporter module. The constructor is typed as an
S3Partitioning | Literal[...] union (never bare str) and normalizes input
with S3Partitioning(partitioning), so an invalid dynamic value (e.g.
function_name) raises ValueError at construction instead of silently
falling through to no partitioning. Key building now compares enum members.
Re-export S3Partitioning from the exporters package and top-level package
alongside S3Exporter. Existing API-compatible string inputs are preserved.

Scheduler/flush/queueing/draining behavior is intentionally unchanged.
NaN compares False to everything, so a NaN sampling_rate flowed

through _should_sample and sampled OUT every execution, silently

disabling all instrumentation. _resolve_sampling_rate now fails

open to 1.0 (full sampling), matching the JS plugin. Adds focused

tests and a README note that on-change exporter calls run

synchronously on the checkpoint path (async work tracked in aws#687).
* fix(core): validate replay operation identity

* fix(core): preserve nondeterminism across nested replay

* fix(core): preserve late replay failures

* fix(core): close replay identity gaps

* fix(core): allocate replay IDs atomically

* fix(core): reject failed nested replay

* fix(core): validate replay edge cases

* fix(core): detect flat started history

* fix(core): remove ambiguous nesting scan

---------

Co-authored-by: Frank Chen <frankchn@dev-dsk-frankchn-2a-ff9871a5.us-west-2.amazon.com>
- Rename to migration-1.x-to-2.0.md; name the release 2.0, not 2.x
- Add a Why upgrade to 2.0 section listing only 2.0 additions
- Rewrite in active voice; remove filler and passive constructions
- Rename batching heading to Removed 1.x-only names
- Add max_concurrency in-flight semantics section
- Add replay operation identity validation (aws#698)
- Add wait_for_condition unreadable-polling-state failure
- Scope RetryableSerDesError guidance to invocation replay and
  step semantics; scope exhaustion to create_wait_strategy
- Correct callbacks note: create_callback().result() still exists
- Move the experimental plugin note to its own linked section
- Mark the grep checklist as non-exhaustive
Address review feedback from ParidelPooya and Codex:

- all_completed(): 1.x already failed fast by default and 1.x
  all_completed() hit the same fail-fast path, so the factory change
  is the breaking change, not the default. Advise 1.x all_completed()
  users to switch to all_successful() or a bare CompletionConfig()
  to keep fail-fast behavior.
- Drop the default-completion claim from the intro and porting
  summary; promote replay identity validation to the headline.
- SerDesError: the raise site changed (1.x wrapped serdes failures
  in ExecutionError), not the class hierarchy.
- should_complete runs on every branch state change, including
  completion and failure, not only scheduling and suspension.
- Identity validation cannot catch swaps of operations with
  identical identities; prohibit reordering under in-flight
  executions regardless.
- Scope RetryableSerDesError body-replay to pre-SUCCEED first-run
  failures; checkpoint-read retries never re-run the step body.
- Point the plugin note at the plugins page, not the logging page.
- Fix two SDK docstrings the guide contradicted: MapConfig's
  completion_config default is fail-fast, and __cause__ holds a
  reconstructed stand-in on both first run and replay.
Bump the SDK version for the 2.0.0 major release and align every
reference to the never-published 1.8.0:

- conformance test packages: exact pins to ==2.0.0
- otel and insight packages: SDK floor to >=2.0.0 (both build
  against the 2.0 plugin interface)
- test-pypi-otel hatch env: SDK floor to >=2.0.0
- lambda-layer-publish.toml: sdk-version pin to 2.0.0 for the
  next otel layer release

SDK-only release: otel and testing package versions are unchanged.
* fix(otel): end recording spans on non-terminal invocations

* fix(otel): support vendor parent span processors

* fix(otel): address PR 696 review findings

* fix(otel): handle virtual context replay spans

* fix(otel): implement current span interface

* fix(otel): reuse reentered context spans

* fix(otel): align virtual context links

* fix(otel): mark only incomplete attempts truncated

---------

Co-authored-by: Frank Chen <frankchn@dev-dsk-frankchn-2a-ff9871a5.us-west-2.amazon.com>
Bumps the actions-deps group with 3 updates: [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials), [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) and [aws/aws-durable-execution-conformance-tests/.github/workflows/opentelemetry-orchestrator.yml](https://github.com/aws/aws-durable-execution-conformance-tests).


Updates `aws-actions/configure-aws-credentials` from 6.2.3 to 6.2.4
- [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases)
- [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md)
- [Commits](aws-actions/configure-aws-credentials@e6de054...cbe3b39)

Updates `docker/setup-qemu-action` from 4.2.0 to 4.3.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](docker/setup-qemu-action@96fe6ef...1f40c72)

Updates `aws/aws-durable-execution-conformance-tests/.github/workflows/opentelemetry-orchestrator.yml` from b8ca81f11aa28e7f7b77ad96a6d323ce10b5f21f to c31f95f448a4fe8ffb93203c7920a48e87362801
- [Release notes](https://github.com/aws/aws-durable-execution-conformance-tests/releases)
- [Commits](aws/aws-durable-execution-conformance-tests@b8ca81f...c31f95f)

---
updated-dependencies:
- dependency-name: aws-actions/configure-aws-credentials
  dependency-version: 6.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-deps
- dependency-name: docker/setup-qemu-action
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-deps
- dependency-name: aws/aws-durable-execution-conformance-tests/.github/workflows/opentelemetry-orchestrator.yml
  dependency-version: c31f95f448a4fe8ffb93203c7920a48e87362801
  dependency-type: direct:production
  dependency-group: actions-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Frank Chen <frankchn@dev-dsk-frankchn-2a-ff9871a5.us-west-2.amazon.com>
- Add ctx.distributed_map with inline, S3, and reader sources
- Add DistributedMapConfig, processor, completion, and destination
  config types
- Add DistributedMapResult/Summary result types and DistributedMapError
- Add function-authoring helpers for item and batch handlers
- Serialize the DISTRIBUTED_MAP operation and add its executor
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.

6 participants