Conversation
…dates (aws#360) Bumps the actions-deps group with 4 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/setup-python](https://github.com/actions/setup-python), [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) and [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action). Updates `actions/checkout` from 4 to 6 - [Release notes](https://github.com/actions/checkout/releases) - [Commits](actions/checkout@v4...v6) Updates `actions/setup-python` from 4 to 6 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](actions/setup-python@v4...v6) Updates `aws-actions/configure-aws-credentials` from 4 to 6 - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Commits](aws-actions/configure-aws-credentials@v4...v6) Updates `slackapi/slack-github-action` from 3.0.1 to 3.0.2 - [Release notes](https://github.com/slackapi/slack-github-action/releases) - [Changelog](https://github.com/slackapi/slack-github-action/blob/main/CHANGELOG.md) - [Commits](slackapi/slack-github-action@af78098...03ea543) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Virtual child contexts (FLAT-mode map/parallel branches) no longer write FAIL checkpoints when the user function raises. The branch is a logical scope only; it does not appear in the execution history regardless of outcome, aligning with the JS reference SDK. Also fixes an incoherent state when a user set ChildConfig.is_virtual=True via run_in_child_context: lifecycle checkpoints were suppressed, but the child context's _parent_id was the child's own operation id (never announced in the checkpoint stream), so inner operations stamped a parent_id pointing to a dangling reference. Nesting produced a chain of such references. The two decisions (lifecycle suppression, parent-id propagation) are now coupled through ChildConfig.is_virtual. Refactor of the supporting mechanism: - Single source of truth for the virtual-vs-real decision. create_child_context computes two fields (_parent_id, _step_id_prefix) at construction; no per-operation-method knowledge is required. New operations just read self._parent_id and work correctly under both modes. - Field names match their roles. _parent_id is "the id my inner operations stamp as their parent"; _step_id_prefix is "how I prefix step ids". Each field has one job. - is_virtual is encapsulated in the context as a cached property. Callers opt in with create_child_context(..., is_virtual=True); the property makes the state inspectable. - Nested virtual-in-virtual matches the JS reference. A virtual child of a virtual parent inherits its parent's reporting ancestor, so chained FLAT layers collapse to the outermost non-virtual context without dangling parent-id references. - ChildConfig.is_virtual drives lifecycle-checkpoint suppression in ChildOperationExecutor (START, SUCCEED, FAIL) and, via run_in_child_context, the child context's own virtual-ness. The field remains public, matching the JS SDK's ChildConfig.virtualContext. - Fewer parameters threaded through. operation_identifier is gone from ConcurrentExecutor, MapExecutor, and ParallelExecutor constructors and from_items/from_callables; the concurrency layer no longer needs an OperationIdentifier to figure out the reporting parent. - Tests exercise the invariants directly with a real DurableContext and assert wire-format decisions, including nested-virtual-in- virtual coverage. Improves observability (no phantom FAILED CONTEXT entries for virtual branches), cost (no billable operation per failed virtual branch), and cross-SDK wire parity. fixes aws#362, fixes aws#363
Kiro and VS Code mangle the hatch interpreter path when it contains spaces, breaking "Select Interpreter". Document the `.venv` symlink workaround and split the existing VS Code section into Interpreter and Linting subsections.
…ws#358) Non-retryable customer errors from Lambda (e.g., KMSAccessDeniedException, KMSDisabledException) arrive as HTTP 502 during CheckpointDurableExecution and GetDurableExecutionState API calls. Without this change, these 502s are classified as retryable invocation errors, causing the SDK to retry invocations that will never self-resolve. Extract shared classification logic into BotoClientError with a _NON_RETRYABLE_CUSTOMER_ERROR_CODES set and _classify_error_category method. Both CheckpointError and GetExecutionStateError now inherit from_exception() with unified classification so that non-retryable errors (KMS 502s, 4xx client errors) return Status: FAILED immediately, while retryable errors (5xx, 429, network errors) continue to raise for Lambda retry. Add is_retryable() to InvocationError hierarchy so execution.py handlers use a single interface instead of isinstance checks. Add backward-compatible aliases for CheckpointErrorCategory and is_retriable(). Log Durable API errors during state fetch, and save partially fetched state. Testing — parameterized classification tests across both error types for all four KMS codes, 4xx, 429, 5xx, and 502 scenarios. Integration tests for non-retryable/retryable errors across all three execution.py code paths: initial pagination, background thread, and user thread. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
- Update the UserAgent string format to be consistent with the format used in other language SDKs.
Bumps the actions-deps group with 2 updates: [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action) and [github/codeql-action](https://github.com/github/codeql-action).
* fix: replay status after paginated state * fix: move replay status check into state --------- Co-authored-by: Frank Chen <65260095+zhongkechen@users.noreply.github.com>
* feat: add lambda bundled runtime useragent header - Detect whether the SDK is installed under the Lambda runtime path. If so, update the UserAgent header string. --------- Co-authored-by: yaythomas <tgaigher@amazon.com>
The /docs folder is fully superseded by the AWS documentation site at https://docs.aws.amazon.com/durable-execution/. Remove it and point README.md and AGENTS.md at the AWS docs instead. - Delete docs/ and all subpages (index, getting-started, core/*, advanced/*, testing-patterns/*, architecture). - README.md: replace the Documentation section with links to the AWS docs site and the Lambda Durable Functions Guide. - AGENTS.md: in the "Python SDK:" link list, replace per-page docs/ links with a single link to the AWS docs site.
- notify-issues.yml: issue notifications - notify-pr.yml: pull request notifications - notify-release.yml: callable workflow for release notifications - pypi-publish.yml: call notify-release after successful publish
- notify-issues.yml: issue notifications - notify-pr.yml: pull request notifications - notify-release.yml: callable workflow for release notifications - pypi-publish.yml: call notify-release after successful publish
Bumps the actions-deps group with 1 update in the / directory: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.35.3 to 4.35.5 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@e46ed2c...9e0d7b8)
After PR aws#216, durable-execution ARNs minted by Execution.new() contain a literal '/' of the form "<uuid>/<invocation-id>". boto's rest-json serializer percent-encodes '/' as %2F in the non-greedy {DurableExecutionArn} URI label, so paths arriving at the local WebServer look like: /2025-12-01/durable-executions/<uuid>%2F<invocation-id> The same shape applies to ListDurableExecutionsByFunction with function names like "MyFunction:$LATEST" (':' -> %3A, '$' -> %24). Without decoding, store lookups never match the key and every Get/State/History/Checkpoint/Stop returns 404. List queries silently return an empty result set. - Decode each segment once in Route.from_string. raw_path is kept as the original wire string for logging. Splitting on '/' happens before decoding so a captured value containing %2F stays inside its segment instead of acting as a path separator. - Remove the now-redundant per-route unquote() calls from the three callback routes (added in aws#117 for the same bug shape). - Add a real-boto regression test under tests/web/e2e/ that drives a live WebServer for every affected operation with values containing the characters boto percent-encodes. Closes the test-coverage gap that let the bug ship. - Strengthen test_route_with_special_characters to assert both segments[N] and the named field are decoded while raw_path keeps the wire form. Affects users running WebRunner / dex-local-runner against their durable function in RIE; pre-fix, the function 404s on its first checkpoint after upgrading to 1.2.0. Closes aws#222
…#398) Bumps the actions-deps group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.35.5 to 4.36.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@9e0d7b8...7211b7c) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.36.0 dependency-type: direct:production update-type: version-update:semver-minor 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: Ayushi Ahjolia <aahjolia@amazon.com>
Co-authored-by: Frank Chen <frankchn@dev-dsk-frankchn-2a-ff9871a5.us-west-2.amazon.com>
Co-authored-by: Frank Chen <frankchn@dev-dsk-frankchn-2a-ff9871a5.us-west-2.amazon.com>
Co-authored-by: Frank Chen <frankchn@dev-dsk-frankchn-2a-ff9871a5.us-west-2.amazon.com>
After collecting a synchronous checkpoint, the collector waited up to 100 ms on an empty queue. The caller waits until the batch persists, so it cannot add work. The wait only delayed it. Sequential steps paid it once per step. Once a batch holds a synchronous checkpoint, wait 1 ms on an empty queue instead. A batch with no blocked caller keeps the full window, so a step's asynchronous START still shares a request with its SUCCEED. With a 1 ms window, refreshes from independent coordinators can split into separate requests when they arrive more than 1 ms apart. A refresh is the empty checkpoint a coordinator sends to see that a wait has ended. The coordinator knows the end time when the branch suspends, so it now requests the refresh then, with that time attached, through ExecutionState.schedule_refresh. The collector holds refreshes until their time and sends all refreshes due at one time in one request. A refresh scheduled before a batch is sealed joins it. Failure, completion and shutdown settle every pending refresh. On Lambda at 1024 MB, 1000 sequential steps went from 142 ms to 41 ms per step. Ten nested coordinators resumed a wave 89 to 104 ms after its end time instead of 288 to 303 ms. Fixes aws#710
- DynamoDBExporter: PutItem, pk=executionArn, optional sk=emittedAt - AuroraExporter: RDS Data API upsert, postgresql or mysql dialect - CloudWatchLogsExporter: PutLogEvents into a per-day stream of any log group - OTelExporter: OTLP/HTTP log record, http/json only - FirehoseExporter: PutRecord, one JSON line per record - EventBridgeExporter: PutEvents, DetailType = record status - RedshiftExporter: Redshift Data API MERGE by execution_arn - OpenSearchExporter: Index API PUT, SigV4 or basic auth - SQSExporter: SendMessage, FIFO group and dedup ids - HttpExporter: POST or PUT JSON with a timeout - FileExporter: ndjson append or one json file per execution - OperationsFormat / apply_operations_format shared by the flexible exporters - README: exporter table and one setup block per exporter
* fix: match invalid checkpoint token casing Service emits "Invalid checkpoint token" (lowercase). The SDK compared with a Title Case prefix, so stale tokens were treated as non-retryable execution failures. Compare case-insensitively and cover both casings in unit tests. Fixes aws#721 * fix: use exact Invalid checkpoint token match Match the backend error prefix case-sensitively and restore the single-unit test description preferred in review.
|
|
||
| # Operation-level terminal failure | ||
| if ( | ||
| checkpointed_result.is_failed() |
There was a problem hiding this comment.
The run status now lives on the operation. So a FAILED, STOPPED, or TIMED_OUT run arrives here with a details block. This branch raises before reading that block. So every non-SUCCEEDED run throws. _distributed_map_status_from_operation already maps these statuses, but this branch makes it unreachable. Pls resolve whenever details are present, and raise only when a terminal operation has none. The existing test only covers the no-details case.
| "Check your resource configurations to confirm the durability is set." | ||
| ) | ||
| raise ExecutionError(msg) from e | ||
| return DurableExecutionInvocationOutput( |
There was a problem hiding this comment.
This changes what every durable handler returns on a malformed or non-durable invoke. It returns a FAILED envelope where it used to raise. That is unrelated to distributed map and is not in the description. Pls split it into its own PR.
| self.operation_identifier = operation_identifier | ||
| self.config = config | ||
|
|
||
| def _resolve_summary( |
There was a problem hiding this comment.
ruff format --check fails here and in tests/dmap_test.py. hatch fmt will fix it.
structure and contractAlthough the functionality is mostly there, the structure doesn't integrate with the codebase's existing layering, so before a line-by-line review let's think through the broader organizational structure or shape of the code. Why restructureThe codebase has two layers and one bridge between them:
The PR adds a third layer between the two:
I sketch out an alternative layout below that removes the extra third layer. Each type gets one home and one job. Translation happens in exactly one place. The serialization layer mirrors the API model one to one, so a model change is a one-file edit. The customer types carry no serialization knowledge, so they validate and unit-test standalone. Envelope dataclasses replace the hand-built dicts in the handler wrappers, so the processor and reader protocols are typed and testable. Proposed structureTwo names exist in both the customer surface and the API model: How the types flow: The translation the executor owns:
Return type. Handler wrappers as decoratorsMake the wrappers decorators, named the way this repo names its decorators (
@durable_distributed_map_item_handler
def handler(ctx: DurableContext, order: dict) -> dict: ...
@distributed_map_item_handler(report="failures", concurrency=8)
def handler(order: dict) -> None: ...
handler = distributed_map_reader(read_page, state_serdes=my_serdes)The decorated name becomes the Lambda handler and takes Other issues with PR currentlyContract:
Style (CONTRIBUTING.md):
|
hatchling 1.32.1 (PyPI, 2026-09-16 16:52 UTC) adds `from hatch.plugin.manager import PluginManager` to hatchling/builders/binary.py, but hatchling does not depend on hatch. Every isolated build env that resolves the unpinned `hatchling` requirement now fails at import time with `ModuleNotFoundError: No module named 'hatch'`, so the `build` CI matrix is red on every PR opened since that release (main was green at 22:40 UTC the day before). Pin `build-system.requires` in all seven packages to `hatchling!=1.32.1,<1.33`: exclude the known-broken release, let the upstream patch release through, and keep the next minor from landing untested. Verified locally: `hatch build` in the insight and conformance-tests-otel packages fails before this change and succeeds after it, resolving hatchling 1.32.0.
The HttpExporter docstring said timeout_ms "bounds the whole request". It does not: http_send passes it to urllib, which applies it to each blocking socket operation. An endpoint that stops reading or goes silent fails at timeout_ms, but one that keeps consuming or sending bytes slowly can hold the request open for longer (measured in review of aws#720: 37 s with timeout_ms=2000 against a 1 byte/s server). - HttpExporter docstring: name the phases the timeout applies to (the connect, each write of the request, each read of the status line, headers, and a non-2xx error body; a 2xx body is never read), note that a future release may enforce timeout_ms as a whole-request deadline, and tell callers to size the function timeout with this in mind - http_send docstring: same per-operation description - README HttpExporter section: same caveat and reservation - rename test_timeout_is_enforced to test_timeout_applies_to_a_silent_peer, which is the case it exercises; no assertion changed No behaviour change.
The local runner rejected CHAINED_INVOKE checkpoints, so a durable
function that calls context.invoke could not be tested locally.
- A START checkpoint validates the options as the service does (Lambda
function name grammar, same account and region, TenantId constraint,
input at most 1 MiB) and resolves the target before anything runs: a
target the runner cannot resolve comes back FAILED in the checkpoint
response, so the handler raises without suspending, as at the
service; otherwise the operation is recorded STARTED and dispatched.
The child's terminal transition completes the parent's operation
and re-invokes the parent; no thread waits on a child.
- A qualified target (child:prod) is invoked as written; its
registration or configuration is the one under that key, else under
the bare name. A PENDING response is valid when an operation
completed after the invocation's input was built.
- Outcomes follow the service: SUCCEEDED, FAILED with the child's error,
STOPPED with the stop error, or TIMED_OUT with ChainedInvoke.Timeout
and "CHAINED_INVOKE timed out after N seconds". A plain target is
bounded by the invocation timeout; a child result over 1 MiB fails.
A target that cannot be invoked fails with the Lambda API error code.
- In-process runner: targets are registered with
register_durable_function or register_function.
- Web runner: --function-configs gives the functions a durable
function may invoke, as a JSON object mapping each name to its
configuration in the shape of the Lambda function configuration
({"ProcessPayment": {"DurableConfig": {...}}, "LookupPrice": {}}), or
file://<path>. A durable target runs as a child execution the runner
drives; a plain target is one synchronous Invoke. Without the option
every chained invoke fails with a message naming it.
- Every handler invocation carries the header X-Dex-Handler-Invoke:
true, so a Lambda-compatible endpoint runs the handler once instead
of starting an execution as it does for a caller's Invoke of a
durable function, and the execution's TenantId, so handlers see
their tenant.
- Client read timeouts follow --invocation-timeout plus 60 s.
- Both runners emulate one region (default us-west-2), fixed at
startup: executions record it, targets in another region are
rejected, and PUT /lambda-endpoint moves the endpoint only. Lambda
contexts report the run's account and tenant, and the target's
function name, version and ARN as Lambda fills them; run() takes
tenant_id.
- GetDurableExecution and the list report the function ARN qualified
with the executed version, and Version, from the execution's own
region and account. A numeric qualifier and $LATEST.PUBLISHED are
reported as given; anything else runs $LATEST, as the runner keeps
no versions or aliases.
- History records ChainedInvokeStarted, Succeeded, Failed, TimedOut,
and Stopped, redacted unless IncludeExecutionData is set. The started
event omits TenantId, as the service's history does. A target the
runner could not resolve is recorded without its input, as at the
service.
- UpdatedOperationIds lists the operations changed since the state the
handler last observed, so a target that completes during an
invocation is reported on the next one.
- The child-to-parent link is rebuilt from the stored parent ARN and
child map when the in-memory link is gone, so a child that completes
after a runner restart still completes its parent's operation.
- Handler invocations and dispatch run on bounded pools of daemon
threads. Python cannot interrupt a blocked Invoke, so closing the
runner leaves it to its read timeout without holding the process;
a result that lands after shutdown is dropped.
Verified with the unit and e2e suites at 95% coverage and the JS
examples conformance suite through the web runner.
Closes aws#436
Closes aws#735
The conformance-tests and conformance-tests-otel packages pin aws-durable-execution-sdk-python==2.0.0 exactly. Bump both to ==2.0.1 to match the release bump; otherwise the shared CI install cannot resolve 2.0.1 against the 2.0.0 pin (ResolutionImpossible).
…dates (aws#739) Bumps the actions-deps group with 7 updates in the / directory: | Package | From | To | | --- | --- | --- | | [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) | `6.2.4` | `6.3.0` | | [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `4.3.0` | `4.4.0` | | [aws/aws-durable-execution-ci/.github/workflows/issue-triage.yml](https://github.com/aws/aws-durable-execution-ci) | `0.3.0` | `0.3.1` | | [aws/aws-durable-execution-ci/.github/workflows/notify.yml](https://github.com/aws/aws-durable-execution-ci) | `0.3.0` | `0.3.1` | | [aws/aws-durable-execution-conformance-tests/.github/workflows/opentelemetry-orchestrator.yml](https://github.com/aws/aws-durable-execution-conformance-tests) | `c31f95f448a4fe8ffb93203c7920a48e87362801` | `a628f5589bbf067a441696c792ab3023c0d0899b` | | [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.37.9` | `4.38.1` | | [aws/aws-durable-execution-ci/.github/workflows/stale-issue-closer.yml](https://github.com/aws/aws-durable-execution-ci) | `1ce65d9d6bf531169718a5e967e15d72fc958265` | `48b3b4349f7d00a6212b9d959427bd7df81ea99d` | Updates `aws-actions/configure-aws-credentials` from 6.2.4 to 6.3.0 - [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@cbe3b39...e125382) Updates `docker/setup-qemu-action` from 4.3.0 to 4.4.0 - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@1f40c72...9901266) Updates `aws/aws-durable-execution-ci/.github/workflows/issue-triage.yml` from 0.3.0 to 0.3.1 - [Release notes](https://github.com/aws/aws-durable-execution-ci/releases) - [Commits](aws/aws-durable-execution-ci@8de63fa...d6b017d) Updates `aws/aws-durable-execution-ci/.github/workflows/notify.yml` from 0.3.0 to 0.3.1 - [Release notes](https://github.com/aws/aws-durable-execution-ci/releases) - [Commits](aws/aws-durable-execution-ci@8de63fa...d6b017d) Updates `aws/aws-durable-execution-conformance-tests/.github/workflows/opentelemetry-orchestrator.yml` from c31f95f448a4fe8ffb93203c7920a48e87362801 to a628f5589bbf067a441696c792ab3023c0d0899b - [Release notes](https://github.com/aws/aws-durable-execution-conformance-tests/releases) - [Commits](aws/aws-durable-execution-conformance-tests@c31f95f...a628f55) Updates `github/codeql-action/upload-sarif` from 4.37.9 to 4.38.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@cdf488f...1c5b675) Updates `aws/aws-durable-execution-ci/.github/workflows/stale-issue-closer.yml` from 1ce65d9d6bf531169718a5e967e15d72fc958265 to 48b3b4349f7d00a6212b9d959427bd7df81ea99d - [Release notes](https://github.com/aws/aws-durable-execution-ci/releases) - [Commits](aws/aws-durable-execution-ci@1ce65d9...48b3b43) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-deps - dependency-name: docker/setup-qemu-action dependency-version: 4.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-deps - dependency-name: aws/aws-durable-execution-ci/.github/workflows/issue-triage.yml dependency-version: 0.3.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-deps - dependency-name: aws/aws-durable-execution-ci/.github/workflows/notify.yml dependency-version: 0.3.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-deps - dependency-name: aws/aws-durable-execution-conformance-tests/.github/workflows/opentelemetry-orchestrator.yml dependency-version: a628f5589bbf067a441696c792ab3023c0d0899b dependency-type: direct:production dependency-group: actions-deps - dependency-name: github/codeql-action/upload-sarif dependency-version: 4.38.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-deps - dependency-name: aws/aws-durable-execution-ci/.github/workflows/stale-issue-closer.yml dependency-version: 48b3b4349f7d00a6212b9d959427bd7df81ea99d 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>
- 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
Move the distributed map code into a dmap package and name the serialization dataclasses after their API shapes. Translation now happens only in the executor, so config.py no longer imports from lambda_service at runtime. Split the tests by layer. Terminal failures raised instead of resolving. Every terminal state now resolves with the summary, and throw_if_error() opts into raising. Missing details or a missing completion reason raise ExecutionError. Items, Output, and the record body were converted to and from JSON around the serdes. Pass the serdes output through unchanged instead. Removed the Status field from DistributedMapDetails. distributed_map_id split the ARN on its last colon and returned a path fragment. Derive it from the /distributed-map-run/ segment. Enforce the documented max_concurrency ceiling of 10000. Flatten the API surface and align with repo conventions: rename the processor factories to batch, item_failures, and item_results. Promote the source and destination factories to InlineSource, S3Source, ReaderSource, and S3Destination. Fold ProcessorRetryConfig into max_retry_attempts and max_retry_duration on the processor. Select the return type statically with DistributedMapResultConfig instead of returning a union. Export only the result types and their enums from the package root. Reverts the unrelated malformed-invoke change to execution.py.
c435308 to
ab38b73
Compare
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.pyDistributedMapSummary: whatctx.distributed_mapreturns, describes run's overall outcome.DistributedMapResult: returned fromctx.distributed_mapwhen inline result collection is enabled. Contains individual map run item outcomes.DistributedMapResultItemandDistributedMapItemError: represent a single item's result / errorconfig.pyDistributedMapConfig: optional settings for distributed mapDistributedMapSource: 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 backProcessorRetryConfig: configures how failing items are retriedDistributedMapCompletionConfig: defines item failure thresholds for marking the overall map run failedSuccessDestination,FailureDestination,DistributedMapDestinationConfig,DistributedMapDestination: for routing successful and failed item records to S3context.pyctx.distributed_map: the entry point a customer calls to run a distributed mapdistributed_map_helpers.pyoperation/distributed_map.pylambda_service.pystate.pyexceptions.pyDistributedMapError: the error a customer catches when a run or an item fails__init__.pyTests
tests/operation/distributed_map_test.pytests/context_test.pytests/e2e/distributed_map_int_test.pyctx.distributed_maptests, mocking backend responses: suspend / resume, collect results, throw on failuretests/distributed_map_helpers_test.pytests/e2e/distributed_map_helpers_int_test.pyTODO
Future Tasks
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.