Skip to content

Bound shutdown waits and retain Node cleanup - #23

Open
ChrisKrawczyk wants to merge 9 commits into
mainfrom
feature/rust-dotnet-lifecycle
Open

ChrisKrawczyk wants to merge 9 commits into
mainfrom
feature/rust-dotnet-lifecycle

Conversation

@ChrisKrawczyk

@ChrisKrawczyk ChrisKrawczyk commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Limit Node shutdown waits without discarding native cleanup.
Successful shutdown still returns Promise<void> and resolves to undefined.

  • Use fallible core startup and retain partial-startup ownership.
  • Validate durations before accepting stop. Repeated calls retain the first deadlines and observe the original operation.
  • Keep registry and preparation failures as sanitized startup errors without changing registration policy.
  • Release obsolete callback and core holders on the JavaScript thread only after proven cleanup. Keep terminal results and deadlines separately.
  • Add isolated lifecycle tests, repeated race cases, callback-collection controls, native-provenance checks, and an instrumented CI job.
flowchart TD
    Stop["First valid stop"] --> Cleanup["Keep native cleanup owned"]
    Stop --> Wait["Wait within grace plus 5000 ms"]
    Cleanup -->|Cleanup proven| Release["Release callback and core holders on the JavaScript thread"]
    Cleanup -->|Cleanup unproven| Retain["Retain ownership"]
    Release -->|Release fails| Retain
    Wait -->|Total expires first| Timeout["Reject timeout; keep cleanup owned"]
    Timeout --> Terminate["Application or supervisor must terminate the process"]
Loading

Behavior and review focus

Omitted grace is 1000 ms. Zero requests force, not instant cleanup.
Pre-start shutdown is terminal.
Serialize lifecycle and registration calls on each Runtime.
Metrics remain unavailable after stop or accepted startup failure.

Timeout requires application- or supervisor-owned process termination, even after later cleanup.
The SDK never exits the process itself.
lifecycle_shutdown_failed alone does not prove cleanup.
It can also mean that the shutdown owner was lost or callback-reference release failed.

This adapter covers core-owned execution, not arbitrary detached JavaScript continuations.
Independent providers and Clients keep their lifetimes.
The global orchestration-handler map remains unchanged.
Returned lifecycle errors exclude panic payloads; the process-wide Rust panic hook is not replaced.

The lifecycle guide
explains duration limits, callback ownership, and supervisor budget sizing.
The documentation follow-up adds simpler explanations and Mermaid diagrams without changing executable code or examples.

Evidence and remaining gates

Current upstream 0.2.2 changes are merged. The earlier conflict list is resolved.
Fresh Windows development-graph evidence after reconciliation:

Check Result
Hook-free lifecycle 26 passed; 11 expected hook-only skips
Instrumented lifecycle 37 passed; no skips, failures, or aborts
PostgreSQL-backed E2E 42 passed, including the SQLite control
Instrumented all-target Clippy Passed

Both ordered races retain 100 iterations.
The local graph uses the modified core source declaring 0.1.32 and registry provider 0.1.37.
These native builds use the dev profile. "Hook-free" does not mean optimized release qualification.
The temporary PostgreSQL container and credentials were removed after validation.

Depends on microsoft/duroxide#64.
Hosted CI is blocked because published core 0.1.32 lacks the required lifecycle APIs.
This PR is ready for review, but final registry minima and dependency validation still require maintainer-authorized core publication.
Final hosted, release-profile, supported-platform, and installed-package checks remain required.
This does not claim that unrelated pre-existing issues or the full regression matrix are resolved.
Development overrides, ignored Cargo locks, binaries, and workflow artifacts are excluded.
No release or package publication is requested.

Generated with PAW.

chkraw and others added 2 commits October 6, 2026 14:33
Preserve the prepared core and startup failures across repeated lifecycle
calls, validate shutdown deadlines before mutation, and unref callbacks
only after proven core quiescence without changing Promise<void> results.
Add supervised lifecycle regressions, test-hook wiring, and migration docs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
Preserve upstream replay isolation, failed-race semantics, lock options, release metadata, and the Rust toolchain pin. Integrate options into protected startup preparation and add raw/typed lifecycle race regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
@ChrisKrawczyk

Copy link
Copy Markdown
Contributor Author

Conflict reconciliation is pushed in ff5f40e (a normal merge of main; no history rewrite). GitHub now reports this draft conflict-free. Upstream replay/race fixes, lock options, release metadata and the toolchain pin are retained, with option preparation still inside the protected lifecycle startup path.

The requested independent Claude Opus 5 integration review covered all four lifecycle PRs and returned PASS, with no blocking findings. The reviewed tree is exactly the committed tree; microsoft/duroxide#64 is unchanged. Non-blocking follow-ups include choosing a new sibling package version before release and the existing signed-to-unsigned negative-option validation gap. This supersedes the original conflict note only: the published core/provider graph, final registry pins, PostgreSQL, non-Windows/five-RID, broader regressions and hosted CI remain unwaived gates. The PR stays draft; nothing was merged, released or published.

Keep one native cleanup operation independent of bounded Promise observers
and preserve the first SDK budget, callback roots and error categories.
Retain upstream release and replay fixes; distinguish cancellable provider
futures from non-yielding native frames in lifecycle coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
@ChrisKrawczyk

Copy link
Copy Markdown
Contributor Author

Upstream-first reconciliation is pushed in 61e59d3 (normal merge of main; no history rewrite). GitHub reports this draft conflict-free. The adapter retains one native cleanup operation and observes it through the first SDK budget, preserving Promise, terminal-state/error behavior and JS-thread callback unref only after proven retirement. Upstream 0.2.1 release metadata and replay/KV fixes are retained. Tests distinguish cancellable fetch futures from non-yielding native frames; no guarantee for unregistered JavaScript continuations was added.

The independent scoped four-repository review is PASS, including the corrected inherited .NET concurrency-test defect. Node's instrumented lifecycle suite passed 20 cases, including 100 repetitions per force ordering and isolated timeout/late-retirement probes. Production lifecycle/lock/replay/typed selections passed 26 with nine expected hook/POSIX skips. Production assets are restored; the reviewed source tree exactly matches the commit.

Core microsoft/duroxide#64 now uses upstream task tracking and is about 32% smaller by feature changed-line count. The local core 0.1.32/provider 0.1.36 graph is development-only: published core lacks additive APIs. Registry delivery, PostgreSQL, non-Windows/five-RID, broader regression and hosted CI remain OPEN. The PR stays draft; nothing was merged, released or published.

chkraw and others added 3 commits October 21, 2026 13:57
Release obsolete native callback holders only after proven cleanup. Add isolated recurring lifecycle instrumentation, installed-addon provenance and stronger timing, registration and ownership regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
Preserve unreleased lifecycle notes while integrating main package metadata and duroxide-pg 0.1.37. Rebuild both native modes against the retained local-core graph and preserve the separate compatible-core publication gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
@ChrisKrawczyk ChrisKrawczyk changed the title [Sibling Runtime Lifecycle] Add retained bounded shutdown for Node Bound shutdown waits and retain Node cleanup Oct 21, 2026
@ChrisKrawczyk
ChrisKrawczyk marked this pull request as ready for review October 22, 2026 04:55
chkraw and others added 3 commits October 22, 2026 13:36
Preserve unreleased lifecycle notes and upstream 0.2.3 metadata. Run instrumented lifecycle CI on Node 24.22.1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
Expose retained stop/fault state through independently owned observers with isolated AbortSignal waits and terminal local close. Keep observation metadata separate from worker ownership and event-loop keepalive. Cover real faults, source retirement, collection and notification races, and document the contracts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
Retain lifecycle and observation changes alongside the upstream package metadata, PostgreSQL provider 0.1.38 requirement, migration guidance, and both changelog histories.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 73748d4f-2eb6-47d2-9dbc-af8681e80e83
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.

2 participants