Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
09eba16
test: add opt-in LMI cloud lifecycle regressions
Sep 22, 2026
bfb0985
test: anchor timeout probes to the real runtime deadline
Sep 22, 2026
4cd8d7d
test: use arm64 for the LMI capacity provider
Sep 22, 2026
df6228b
ci: run LMI tests on every main branch update
Sep 22, 2026
348125e
test: serialize LMI fixtures within existing capacity
Sep 22, 2026
7a37d90
test: deploy all five LMI fixtures for one cloud run
Sep 22, 2026
f3c230c
fix(test): invoke LMI functions with explicit AWS CLI arguments
Sep 22, 2026
0f27d1c
fix(test): declare all LMI fixtures and scaling in one stack
Sep 22, 2026
01789ff
test: persist and reuse the LMI test stack across runs
Sep 23, 2026
af343eb
fix(test): make LMI evidence collection deterministic
Sep 25, 2026
dc5c285
fix(test): isolate timeout evidence and cleanup
Sep 25, 2026
ef968d4
fix(test): wait for stable timeout evidence
Sep 25, 2026
9b82f7c
fix(test): complete LMI regression isolation
Sep 25, 2026
472f729
fix(test): finalize LMI suite gating and cleanup
Sep 25, 2026
ceffae2
fix(test): close remaining LMI evidence gaps
Sep 25, 2026
c672852
fix(test): require complete cleanup evidence
Sep 25, 2026
4f290cb
fix(test): validate retry cleanup and retain failures
Sep 25, 2026
2b3d23f
fix(test): pair backend calls and prove LMI recovery occupancy
zhongkechen Sep 25, 2026
b92bc6e
Update .github/workflows/lmi-e2e-tests.yml
zhongkechen Sep 29, 2026
db4d041
test: reject LMI wrapper returns without matching entries
zhongkechen Sep 29, 2026
c868553
fix: align LMI fixture parent and formatting with main
Sep 29, 2026
78f38d9
test: validate all LMI request activity and correlate cleanup evidence
zhongkechen Sep 29, 2026
b797c62
ci: validate LMI fixtures against Java 17
zhongkechen Sep 29, 2026
7693b3d
test: preserve LMI execution identity and collect silent failures
zhongkechen Sep 29, 2026
017baa2
feat: add invocation-scoped task tracking
Sep 24, 2026
a21f2bc
refactor: clarify executor task handle naming
Sep 24, 2026
f873cec
refactor: describe executor task roles
Sep 24, 2026
dbc1fa9
refactor: keep invocation lifecycle in execution manager
Sep 24, 2026
a7990b9
fix: make invocation admission safe during draining
zhongkechen Sep 25, 2026
d877354
fix: admit and drain descendants of invocation-owned tasks
zhongkechen Sep 29, 2026
3db3e73
fix: bound invocation lifecycle cleanup
Sep 24, 2026
9260736
refactor: require explicit checkpoint shutdown budget
Sep 25, 2026
fdc6f40
fix: decouple batch timer sentinel from invocation duration
Sep 25, 2026
e00c900
feat: add per-invocation executor isolation
Sep 25, 2026
3939ac9
test: serialize LMI boundaries and preserve recovery evidence
zhongkechen Sep 29, 2026
6255355
test: reconcile ambiguous LMI starts and retain only held gates
zhongkechen Sep 29, 2026
edeb507
chore: sync LMI cloud tests with main
zhongkechen Oct 16, 2026
91d94e8
fix: bind invocation task futures before dispatch
zhongkechen Oct 16, 2026
1d6cd93
chore: integrate current LMI base lifecycle
zhongkechen Oct 16, 2026
57404b0
fix: interrupt tasks before cancellation observers
zhongkechen Oct 16, 2026
b39070c
fix: integrate bounded cleanup with handler-owned lifecycle
zhongkechen Oct 16, 2026
f773944
Merge branch 'review/java-pr731-sync-20261016' into review/java-pr733…
zhongkechen Oct 16, 2026
7f8b0ad
fix: align invocation executors with lifecycle
zhongkechen Oct 16, 2026
157c99d
fix: preserve draining work after interruption
zhongkechen Oct 16, 2026
b6b164b
fix: preserve recorded cleanup control and observer gates
zhongkechen Oct 16, 2026
4e3863f
fix: retain updated lifecycle failure controls
zhongkechen Oct 16, 2026
3fd9337
fix: retain admitted results during interrupted owner drain
zhongkechen Oct 16, 2026
b5a6bf0
fix: preserve admitted work on interrupted drain
zhongkechen Oct 16, 2026
14d8fca
test: observe budgeted lifecycle waits
zhongkechen Oct 16, 2026
b55d0da
test: observe budgeted lifecycle waits
zhongkechen Oct 16, 2026
15d8eb2
fix: arbitrate task cancellation and result publication atomically
zhongkechen Oct 16, 2026
947daa1
Merge atomic task publication fix from invocation scope
zhongkechen Oct 16, 2026
f0b0173
fix: include atomic task cancellation arbitration
zhongkechen Oct 17, 2026
4f1b766
test: require settled fixed-pool placement evidence before retry
zhongkechen Oct 17, 2026
d09f1df
Merge settled fixed-pool evidence controls from LMI harness
zhongkechen Oct 17, 2026
b891a11
Merge final invocation scope and LMI harness review fixes
zhongkechen Oct 17, 2026
99a1205
test: retain observed admission contention state
zhongkechen Oct 17, 2026
b6b9767
test: include verified fixed-pool evidence handling
zhongkechen Oct 17, 2026
c2e6c5a
test: retain observed admission contention state
zhongkechen Oct 17, 2026
28d8bd6
chore: include final reviewed lifecycle base
zhongkechen Oct 17, 2026
8c05b96
test: preserve original healthy outcomes and late request failures
zhongkechen Oct 17, 2026
495f3fe
Merge complete healthy-request and transport evidence controls
zhongkechen Oct 17, 2026
8b39427
Merge final healthy-request and transport evidence controls
zhongkechen Oct 17, 2026
bd0b057
test: include final healthy-request evidence checks
zhongkechen Oct 17, 2026
160169f
test: allow bounded stubborn retry settlement after stop
zhongkechen Oct 17, 2026
5b65c52
Merge bounded stubborn-retry settlement controls
zhongkechen Oct 17, 2026
b040ae6
Merge final bounded residual-cleanup harness controls
zhongkechen Oct 17, 2026
4968c9f
test: include bounded residual-work settlement budget
zhongkechen Oct 17, 2026
8c9292d
test: validate every case request lifecycle after settlement
zhongkechen Oct 17, 2026
75ff603
Merge per-request lifecycle acceptance for all case attempts
zhongkechen Oct 17, 2026
167e49f
Merge final case-wide lifecycle acceptance controls
zhongkechen Oct 17, 2026
e193729
test: include final per-request lifecycle acceptance
zhongkechen Oct 17, 2026
37a0449
test: revalidate original request identities after collection
zhongkechen Oct 17, 2026
d9b251c
Merge final original-identity and cohort evidence controls
zhongkechen Oct 17, 2026
242b88f
Merge final original request and fixed-cohort acceptance
zhongkechen Oct 17, 2026
11b1791
test: include final immutable evidence identity checks
zhongkechen Oct 17, 2026
382c16a
test: sync LMI fixtures and revalidate final collected evidence
zhongkechen Oct 20, 2026
83ce008
Merge updated LMI harness and current main into invocation scope
zhongkechen Oct 20, 2026
3f13e52
Merge updated invocation scope and current main into deadline handling
zhongkechen Oct 20, 2026
b510ba8
Merge updated deadline lifecycle and current main into invocation exe…
zhongkechen Oct 20, 2026
2efba15
test: require complete warm wrapper snapshots before acceptance
zhongkechen Oct 20, 2026
b5b6a60
test: preserve proven warm failures alongside cleanup errors
zhongkechen Oct 20, 2026
7b13e6e
test: reject changes to the pinned warm request cohort
zhongkechen Oct 20, 2026
3faa40c
test: merge complete pinned warm snapshot checks
zhongkechen Oct 20, 2026
374e655
test: merge complete pinned warm snapshot checks
zhongkechen Oct 20, 2026
df4b1ac
test: merge complete pinned warm snapshot checks
zhongkechen Oct 20, 2026
1de7f42
fix: preserve deadline and fatal outcomes across cancellation
zhongkechen Oct 21, 2026
caf6cc3
fix(lifecycle): preserve acknowledged delivery failures during interr…
zhongkechen Oct 21, 2026
cbcd67a
Merge Java 3 main into invocation deadline lifecycle
zhongkechen Oct 21, 2026
280f723
Align cleanup boundary tests with actual owner completion
zhongkechen Oct 21, 2026
430cb20
Preserve shutdown wrappers across caller cleanup
zhongkechen Oct 21, 2026
8c74a56
test: await admitted enqueue after lifecycle deadline
zhongkechen Oct 21, 2026
7e4a266
Retain causeless failures at invocation delivery boundaries
zhongkechen Oct 21, 2026
4e4fdcf
Verify application error wrappers survive ACK delivery
zhongkechen Oct 21, 2026
7963b89
Retain checkpoint cancellation identity across JDKs
zhongkechen Oct 21, 2026
df76d92
test: admit handler scope before exercising execution cutoff
zhongkechen Oct 21, 2026
580fa84
Preserve terminal cancellation identity after lifecycle precedence
zhongkechen Oct 21, 2026
0d97689
Preserve fatal owner cleanup until lifecycle cancellation is due
zhongkechen Oct 21, 2026
2e645c1
Preserve recorded fatal priority during admission
zhongkechen Oct 21, 2026
bc33d08
test: cover input fatal and terminal End preparation cutoffs
zhongkechen Oct 21, 2026
5436186
Finalize synchronous invocation failures before automatic close
zhongkechen Oct 21, 2026
cb5d491
Preserve preparation failure priority across invocation cutoffs
zhongkechen Oct 21, 2026
5cd59d8
test: verify invocation executor routing for nested operations
zhongkechen Oct 21, 2026
ea88116
Merge Java 3 lifecycle into invocation-owned executors
zhongkechen Oct 21, 2026
9af04ef
Merge final delivery failure controls into owned executors
zhongkechen Oct 21, 2026
87ce5c8
Merge validated cancellation and scope cutoff fixes
zhongkechen Oct 21, 2026
decdc1a
test: retain first fatal through owned executor shutdown
zhongkechen Oct 21, 2026
7123865
Preserve fatal outcomes through owned executor shutdown
zhongkechen Oct 21, 2026
aa2057b
Merge preserved fatal owner cleanup semantics
zhongkechen Oct 21, 2026
aba5d09
test: preserve pre-dispatch fatal during owned close
zhongkechen Oct 21, 2026
293e34d
Distinguish explicit close failure observations during setup
zhongkechen Oct 21, 2026
3e26032
test: preserve wrapped owned shutdown fatal priority
zhongkechen Oct 21, 2026
24ded16
Recognize wrapped JVM fatals before owned cleanup classification
zhongkechen Oct 21, 2026
f9e53a4
Merge reviewed invocation admission and terminal preparation fixes
zhongkechen Oct 21, 2026
2a4d493
test: finalize owned executors after admission rejection
zhongkechen Oct 21, 2026
18def88
test: cover draining cancellation and registration races
zhongkechen Oct 21, 2026
a03274f
Fence draining admissions before and after registration
zhongkechen Oct 21, 2026
7f0f910
Keep the first lifecycle failure canonical during cleanup
zhongkechen Oct 21, 2026
fe1d663
Preserve owned shutdown failures across lease-state query errors
zhongkechen Oct 21, 2026
8bfaab6
Merge lifecycle fencing around draining registration
zhongkechen Oct 21, 2026
b6482f9
Merge canonical lifecycle failure selection during cleanup
zhongkechen Oct 21, 2026
f59de04
test: retain first lifecycle failure after owned termination timeout
zhongkechen Oct 21, 2026
f9a2b5f
Retain latched lifecycle failure through owned termination timeout
zhongkechen Oct 21, 2026
b1d0d81
test: cover cancellation while the root drains asynchronous work
zhongkechen Oct 21, 2026
f84af27
Preserve cancellation cause when the invocation owner drains work
zhongkechen Oct 21, 2026
e42bf85
Clean up newly leased executors when initialization fails
zhongkechen Oct 21, 2026
ca80a56
Merge owner-drain cancellation identity into executor initialization …
zhongkechen Oct 21, 2026
4e73334
Force owned executor cleanup when graceful shutdown throws
zhongkechen Oct 21, 2026
4e60115
test: cover post-manager setup and cleanup failure priorities
zhongkechen Oct 21, 2026
61e1971
Finalize post-manager setup failures before automatic close
zhongkechen Oct 21, 2026
d8ef9ac
Combine owned executor fallback and setup failure finalization
zhongkechen Oct 21, 2026
52a25cc
test: cover owned lease release after confirmed termination
zhongkechen Oct 21, 2026
22aa7e8
Release owned executor lease when termination is confirmed
zhongkechen Oct 21, 2026
a4a7db0
test: cover MDC restoration fatal with later owned cleanup failure
zhongkechen Oct 21, 2026
3711775
Retain root completion fatal through owned executor cleanup
zhongkechen Oct 21, 2026
1291921
test: retain adjacent MDC failure diagnostics without duplication
zhongkechen Oct 21, 2026
bccc5b0
Retain each completion-only fatal diagnostic once
zhongkechen Oct 21, 2026
dbb0521
Test completion diagnostics across ACK and caller cutoff
zhongkechen Oct 21, 2026
cd2cbd5
test: retain serializer failure under owned cleanup failures
zhongkechen Oct 21, 2026
fd12e9a
Cover repeated serializer error under caller cutoff cleanup
zhongkechen Oct 21, 2026
ee70d9f
Retain completion diagnostics on the existing cleanup failure winner
zhongkechen Oct 21, 2026
d2daa01
test: cover recorded fatal cleanup diagnostics and alias cycles
zhongkechen Oct 21, 2026
55f31ef
Keep recorded fatal cleanup diagnostics without transport alias cycles
zhongkechen Oct 21, 2026
f93515f
test: cover prior fatal and wrapped executor callback diagnostics
zhongkechen Oct 21, 2026
087d303
Preserve selected fatal and wrapper diagnostics across owned callbacks
zhongkechen Oct 21, 2026
4e4fd00
chore: merge upstream 3.0.0 release versions
zhongkechen Oct 21, 2026
1501df4
chore: merge upstream trace-header documentation
zhongkechen Oct 21, 2026
df6fcb8
chore: merge upstream 3.0.0 release versions
zhongkechen Oct 21, 2026
80ef290
chore: merge upstream trace-header documentation
zhongkechen Oct 21, 2026
9434cf5
test: cover setup wrapper diagnostics and single-pass inspection
zhongkechen Oct 21, 2026
c4ee406
fix: retain fatal setup wrapper diagnostics during finalization
zhongkechen Oct 21, 2026
7ddc417
test: retain nonfatal setup and application wrapper diagnostics
zhongkechen Oct 21, 2026
01087ee
fix: preserve diagnostics from discarded nonfatal setup wrappers
zhongkechen Oct 21, 2026
2b1ec75
test: preserve suppressed fatal diagnostics without promoting them
zhongkechen Oct 21, 2026
48c4504
fix: retain wrapper diagnostics without selecting a new failure
zhongkechen Oct 21, 2026
dc14e3a
test: await continuation observation after asserting actual exit
zhongkechen Oct 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion docs/advanced/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,22 @@ public class OrderProcessor extends DurableHandler<Order, OrderResult> {
| `withLambdaClientBuilder()` | Custom AWS Lambda client | Auto-configured Lambda client |
| `withSerDes()` | Serializer for step results | Jackson with default settings |
| `withExecutorService()` | Thread pool for user-defined operations | Cached daemon thread pool |
| `withInvocationExecutorFactory()` | Factory for isolated per-invocation user executors | Disabled |
| `withLoggerConfig()` | Logger behavior configuration | Suppress logs during replay |
| `withPollingStrategy()` | Backend polling strategy | Exponential backoff: 1s base, 2x rate, FULL jitter, 10s max |
| `withCheckpointDelay()` | How often the SDK checkpoints updates | `Duration.ofSeconds(0)` (as soon as possible) |

The `withExecutorService()` option configures the thread pool used for running user-defined operations. Internal SDK coordination (checkpoint batching, polling) runs on an SDK-managed thread pool.
The `withExecutorService()` option configures a caller-owned executor shared by every invocation that uses the configuration. The SDK never shuts it down. To isolate concurrent Lambda Managed Instances invocations, configure a factory instead:

```java
DurableConfig.builder()
.withInvocationExecutorFactory(() -> Executors.newFixedThreadPool(4))
.build();
```

The factory is called once per invocation and may be called concurrently on Lambda Managed Instances. It must return a fresh executor. The invocation caller waits for actual admitted work and End before shutting that executor down, including after cancellation. Code that ignores interruption can delay this shutdown beyond the policy budget; executor termination is then observed with any cleanup time that remains. Returning an executor already leased to an active invocation is rejected. The factory and `withExecutorService()` are mutually exclusive. Both options run all user code, including plugin-enabled root handlers, steps, and child contexts. Internal SDK coordination such as checkpoint batching and polling remains on the SDK-managed executor. `toBuilder()` and the local test runner preserve the factory, including across replay/resume.

A bounded executor supplied through `withExecutorService()` remains shared. On Lambda Managed Instances, concurrent roots can occupy all of its workers while waiting for queued steps. Use the invocation factory when capacity must be isolated between native invocations. Isolation does not define the capacity required by arbitrarily nested synchronous child contexts; size or design those separately.

### Dynamic plugin loading

Expand Down Expand Up @@ -95,3 +106,36 @@ file retention.
Custom serializers can override `serialize(value, SerDesContext)` and
`deserialize(data, typeToken, SerDesContext)` to receive stable execution/entity
identity. Existing implementations inherit defaults that call the original methods.

## Invocation deadline cleanup

The SDK captures the Lambda invocation's remaining time once and uses monotonic
cutoffs for admission and its wait policy. Deadline exhaustion selects a retryable
invocation interruption; it is not checkpointed as a business-operation failure.
Catching an admission rejection cannot turn the stopped invocation into a
successful fallback. Completed operation results and failures remain available for
replay.

Cleanup allowances determine when the SDK requests cooperative cancellation and
stops ordinary admission. They do not make cancellation equivalent to actual task
exit. Finalization still waits for admitted user work, continuations and in-flight
checkpoint/poll transport, and runs the matching invocation End on its owner.
The runtime caller waits for that owner and
End to finish, including after a deadline or interruption. End is not moved to a
completion-observer thread or deferred until after the SDK call returns.

Interruption is recorded, remaining required cleanup still runs, and the interrupt
flag is restored. A terminal execution result acknowledged by the
service remains authoritative for a handled deadline cutoff. An accepted result
does not suppress an otherwise-propagating delivery or metadata failure, and an
available JVM fatal keeps its original identity and priority.

These cutoffs do not guarantee bounded caller return or worker reclamation.
Already-running application I/O, synchronous initial-state reads, custom clients,
plugin hooks and other code that ignores interruption can keep the caller waiting
for actual cleanup beyond the policy budget. An executor that runs the root inline,
including a saturated `CallerRunsPolicy`, can also block the runtime caller before
it reaches a timeout-aware wait. Use finite downstream I/O timeouts and executor
configurations that allow progress. Cancellation cannot undo a request already
accepted by the service; interrupted side effects still require the documented
retry and idempotency strategy.
17 changes: 16 additions & 1 deletion docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,19 +145,34 @@ public class MyHandler extends DurableHandler<Input, Output> {
| `lambdaClientBuilder` | Auto-created `LambdaClient` for current region, primed for performance (see [`DurableConfig.java`](../sdk/src/main/java/software/amazon/lambda/durable/DurableConfig.java)) |
| `serDes` | `JacksonSerDes` |
| `executorService` | `Executors.newCachedThreadPool()` (for user-defined operations only) |
| `invocationExecutorFactory` | Disabled; when configured, creates an SDK-owned executor for each invocation |
| `loggerConfig` | `LoggerConfig.defaults()` (suppress replay logs) |
| `pollingStrategy` | Exponential backoff: 1s base, 2x rate, FULL jitter, 10s max |
| `checkpointDelay` | `Duration.ofSeconds(0)` (checkpoint as soon as possible) |

### Thread Pool Architecture

Each invocation tracks logical task outcomes separately from actual task exit.
Deadline and cleanup cutoffs fence admission and request cooperative cancellation,
while finalization still waits for admitted work and in-flight transport to finish.
The matching invocation End runs on its owner, and the runtime caller waits for
that owner and End before returning. Code that ignores interruption can therefore
outlast the policy budget; see [invocation deadline cleanup](advanced/configuration.md#invocation-deadline-cleanup).

The SDK uses two separate thread pools with distinct responsibilities:

**User Executor (`DurableConfig.executorService`):**
- Runs user-defined operations (the code passed to `ctx.step()` and `ctx.stepAsync()`)
- Runs the root handler, steps, child-context user code, and map/parallel coordination
- Configurable via `DurableConfig.builder().withExecutorService()`
- Caller-owned and shared across invocations; the SDK never shuts it down
- Default: cached daemon thread pool

**Invocation Executor Factory (`DurableConfig.invocationExecutorFactory`):**
- Optional alternative to the shared user executor
- Creates one executor per invocation for all root, step, child-context user code, and map/parallel coordination
- SDK-owned: the invocation caller waits for actual admitted work and End before requesting executor shutdown, including after cancellation. Non-cooperative work can delay that shutdown beyond the policy budget. Executor termination is observed with any cleanup time that remains.
- Must return a fresh executor and cannot be combined with `withExecutorService()`

**Internal Executor (`InternalExecutor.INSTANCE`):**
- Runs SDK coordination tasks: checkpoint batching, polling for wait completion
- Dedicated cached thread pool with daemon threads named `durable-sdk-internal-*`
Expand Down
44 changes: 26 additions & 18 deletions lmi-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ those original snapshots and retain the existing zero-work and +16-thread limits
Newly discovered request identities invalidate the warm cohort instead of moving
its original baseline or final measurement to another request.

The current deadline controls fence admission and request cooperative cancellation,
but the SDK still awaits actual owner cleanup, admitted transport and the matching
invocation End before returning. Non-cooperative work can therefore keep the
runtime caller blocked beyond its deadline. This remains a partial change for
[#726](https://github.com/aws/aws-durable-execution-sdk-java/issues/726), not proof
that every desired LMI lifecycle bound is satisfied. The acceptance limits below
remain unchanged; local tests do not replace a deployed cloud acceptance run, and
eventual cleanup cannot turn an earlier lifecycle violation into a pass.

## Test design

* Each fixture is a published durable function with LMI invocation concurrency
Expand All @@ -30,7 +39,7 @@ its original baseline or final measurement to another request.
SDK's minimum JDK prevents fixture-only changes from introducing newer JDK APIs
into the shared Maven reactor. On manual dispatch, a separate
serialized cloud job builds the selected commit, deploys all five
fixture functions, runs all 13 cases, then collects evidence. A persistent
fixture functions, runs all 12 gating cases, then collects evidence. A persistent
CloudFormation stack owns all five
functions and log groups. The stack, functions and bucket remain after both
successful and failed test runs; later deployments update the same resources. Each uses 2 GiB / 1 vCPU and a single
Expand Down Expand Up @@ -65,17 +74,14 @@ its original baseline or final measurement to another request.
Each real checkpoint/poll call has a request-local call ID paired with its
`finally` exit. Missing or mismatched exits prevent cleanup from reusing the
fixture, and an exit after wrapper return remains a lifecycle failure.
* A bounded same-JVM root barrier establishes the fixed-pool reproduction.
`fixed2` uses a shared two-thread pool so two roots starve their first steps.
`nested2` uses four threads and a separate cohort-scoped child barrier. Both
child handlers must enter before either schedules nested map/parallel work.
The child barrier has an independent 8-second setup budget; the nested progress
budget starts when it releases, not when the roots passed their earlier barrier.
A broken child barrier fails setup without growing the pool; an escape after
successful child admission still fails the starvation assertion.
Other cases hold steps with private S3 control objects. The driver requires
distinct request IDs active in the same JVM. Placement has its own deadline
and failure category. Environment replacement is never worker recovery.
* A bounded same-JVM root barrier verifies that `fixed2` gives each invocation
its own two-thread executor. `nested2` is retained in the persistent stack for
baseline diagnostics but does not produce a gating LMI case. It uses four
shared threads and a separate cohort-scoped child barrier before scheduling
nested map/parallel work. Other cases hold steps with private S3 control
objects. The driver requires distinct request IDs active in the same JVM.
Placement has its own deadline and failure category. Environment replacement
is never worker recovery.
* Timeout victims start before healthy peers, leaving the peers time to hold
the other runtime slots during recovery. Diagnostics capture the real context
deadline; no fake clock, context, checkpoint backend, or time-skipping runner
Expand Down Expand Up @@ -170,8 +176,9 @@ python3 lmi-tests/cloud_suite.py collect
```

The deploy command creates or updates and retains `default1`, `default2`, `default8`,
`fixed2`, and `nested2` together. The test command requires all five and runs the
full suite. CI publishes one combined artifact, named `lmi-e2e-RUN-ATTEMPT`, with
`fixed2`, and `nested2` together. The test command requires all five and runs 12
gating cases; `nested2` is retained but excluded. CI publishes one combined
artifact, named `lmi-e2e-RUN-ATTEMPT`, with
the single `template.json` and per-function configuration snapshots. The
CloudFormation execution role needs permission to manage the function scaling
configuration; the driver calls `lambda:GetFunctionScalingConfig` to verify it
Expand Down Expand Up @@ -219,7 +226,7 @@ barrier diagnostics never authorize a retry. Every attempted cohort remains in
the escape ledger, so a later successful cohort cannot hide an earlier pool escape.

`timeouts/*.json` distinguishes server timeout logs from an SDK deadline
cancellation that returns early with an invocation error. A client HTTP timeout
cancellation reported as an invocation error after owner cleanup. A client HTTP timeout
is a collection error. Deadline victims use asynchronous service invocation so a
longer durable retry does not consume the driver HTTP timeout; invocation
outcomes come from request-correlated runtime logs. Invocation request failures
Expand Down Expand Up @@ -251,9 +258,10 @@ a normally ordered retry cannot replace an admitted participant.
After stopping durable executions, cleanup allows any pre-stop stubborn retry its
configured residual hold (capped at 120 seconds), plus the existing 30-second
collection margin and 20-second quiet period. This cleanup allowance does not alter
the original invocation deadline + 5s or progress/recovery acceptance limits. No virtual-thread executor variant is deployed
until its executor contract is defined; default cached and shared fixed pools
are covered separately.
the original invocation deadline + 5s or progress/recovery acceptance limits.
No virtual-thread executor variant is deployed until its executor contract is defined.
The cloud suite gates default cached and invocation-local fixed pools; the shared
fixed nesting fixture remains available as a non-gating baseline diagnostic.

CloudFormation's native [FunctionScalingConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-lambda-function-functionscalingconfig.html)
sets the limits in the resource declaration. LMI provisioning and version behavior
Expand Down
14 changes: 7 additions & 7 deletions lmi-tests/cloud_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
OWNER = "java-sdk-lmi-e2e"
DEFAULT_STACK = "java-lmi-e2e"
FIXTURES = {"default1": (1, "default"), "default2": (2, "default"),
"default8": (8, "default"), "fixed2": (2, "fixed"), "nested2": (2, "nested")}
"default8": (8, "default"), "fixed2": (2, "invocation-fixed"), "nested2": (2, "nested")}
PEER_LOG_OBSERVATION_SECONDS = 20
PEER_PLACEMENT_SECONDS = 60

Expand Down Expand Up @@ -201,7 +201,7 @@ def deploy_fixtures(manifest, tags, seconds=1800):
wait_stack(manifest["stack"], expected, remaining_budget(deadline, seconds))
stack = existing_stack(manifest["stack"])
outputs = {output["OutputKey"]: output["OutputValue"] for output in stack["Outputs"]}
require(set(outputs) == set(FIXTURES), "The stack must expose all five LMI fixtures")
require(set(outputs) == set(FIXTURES), "The stack must expose all required LMI fixtures")
for fixture in FIXTURES:
arn = outputs[fixture]
record_fixture(manifest, fixture, arn)
Expand Down Expand Up @@ -893,10 +893,10 @@ def collect_warm_snapshots(cloud, items, seconds=30):
def cases_for_fixture(cloud, fixture):
if fixture == "default1":
return [("baseline-concurrency1", lambda: replay_case(cloud, fixture, "baseline"))]
if fixture in {"fixed2", "nested2"}:
scenario = "fixed" if fixture == "fixed2" else "nested"
return [("fixed-two-roots" if fixture == "fixed2" else "fixed-nested-map-parallel",
lambda: fixed_case(cloud, fixture, scenario))]
if fixture == "fixed2":
return [("isolated-fixed-two-roots", lambda: fixed_case(cloud, fixture, "fixed"))]
if fixture == "nested2":
return []
cases = [(fixture + "-isolation", lambda: overlap_case(cloud, fixture)),
(fixture + "-suspend-cleanup-replay", lambda: replay_case(cloud, fixture, "suspend")),
(fixture + "-timeout-recovery", lambda: timeout_case(cloud, fixture))]
Expand Down Expand Up @@ -1022,7 +1022,7 @@ def revalidate_cases(cloud, records):
def run_tests():
manifest = json.loads(MANIFEST.read_text())
if set(manifest["functions"]) != set(FIXTURES):
raise PreconditionError("All five functions must be deployed before running the cloud suite")
raise PreconditionError("All required functions must be deployed before running the cloud suite")
cloud = Cloud(manifest, ARTIFACTS)
suite = ET.Element("testsuite", name="LMI cloud lifecycle")
records = []
Expand Down
4 changes: 2 additions & 2 deletions lmi-tests/cloud_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def assert_fixed(events, markers, progress_start="BARRIER_PASSED"):
require(len({e["requestId"] for e in entered}) == len(markers), "Missing distinct runtime invocations")
require(max(e["sequence"] for e in entered) < min(e["sequence"] for e in passed),
"Root invocations did not overlap at the barrier")
require(not selected(events, "ESCAPE"), "Shared fixed executor starved its own queued work")
require(not selected(events, "ESCAPE"), "Fixed executor starved its own queued work")
# Child admission is one cohort-wide phase. A participant scheduled later must
# not get a fresh progress budget after its peer has already left the barrier.
cohort_start = min((e["nanos"] for e in selected(events, progress_start)), default=None)
Expand All @@ -222,7 +222,7 @@ def assert_fixed(events, markers, progress_start="BARRIER_PASSED"):
start = selected(events, progress_start, marker)
started = cohort_start if progress_start == "CHILD_BARRIER_PASSED" else (start[0]["nanos"] if start else None)
require(start and progress and 0 <= (progress[-1]["nanos"] - started) < 8_000_000_000,
"Shared executor did not progress within budget")
"Fixed executor did not progress within budget")


def assert_nested_reached(events, markers):
Expand Down
Loading
Loading