Skip to content

feat(server): split start wait stop lifecycle - #659

Merged
SunSi12138 merged 1 commit into
devfrom
feat/646-server-lifecycle-dev
Sep 11, 2026
Merged

feat(server): split start wait stop lifecycle#659
SunSi12138 merged 1 commit into
devfrom
feat/646-server-lifecycle-dev

Conversation

@SunSi12138

@SunSi12138 SunSi12138 commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Closes #646

Summary

  • Replace public Server RunAsync with StartAsync, WaitForShutdownAsync, and StopAsync as the single canonical lifecycle model.
  • Expose SharpLinkServerLifecycleState independently from local HealthStatus.
  • Make SharpLinkServer own and observe its accept loop and fatal runtime tasks after startup.
  • Preserve connection/session cleanup as a local failure domain instead of faulting the whole Server.
  • Simplify Generic Host integration to direct Server Start/Stop bridging; remove the hosted _runTask, _runCts, and ObserveRunTaskAsync lifetime model.
  • Migrate demos, samples, test harnesses, benchmarks, smoke tests, and documentation away from Server RunAsync.
  • Keep development versions unchanged: no package/project/assembly/file/diagnostics schema version bump.

Lifecycle semantics

  • StartAsync returns only after the Server-owned accept infrastructure is established and lifecycle is published as Running; an immediate accept/startup failure is propagated to the startup caller.
  • A startup caller token stops owning anything after startup succeeds. A concurrent Start waiter can cancel only its own wait.
  • WaitForShutdownAsync is a pure terminal observer. Its token cancels only that caller's wait and never initiates shutdown.
  • StopAsync creates or joins one shared Server-owned drain/cleanup operation. Caller cancellation cancels only the caller's wait, not the shared shutdown.
  • StopAsync from Created reaches a real terminal Stopped state.
  • Unrecoverable accept/heartbeat-supervisor/decode-executor termination converges on the shared terminal cleanup path and Faulted; Stop/Wait expose the same terminal failure.

Failure domains

  • Accept loop / heartbeat supervisor / persistent decode executor unexpected termination: Server-terminal.
  • Accepted connection lifecycle and heartbeat-timeout connection cleanup failures: observed/logged locally; the Server remains running.
  • Fatal-runtime owners explicitly observe the shared terminal cleanup task. The shared _stopTask remains faulted/joinable so later StopAsync callers still receive the same terminal failure, while WaitForShutdownAsync remains an independent terminal observer.

Generic Host

  • IHostedService.StartAsync awaits server.StartAsync and publishes readiness only after startup succeeds.
  • IHostedService.StopAsync joins server.StopAsync without passing the Host caller token into the Server-owned stop operation.
  • The Host keeps only an observer for unexpected terminal Server failure so the application lifetime can stop; it does not coordinate a second Server runtime.

Validation

Development validation was run from exact dev base 2f16532e4c18acff922d208eb262aec4999b33ac:

  • exact-base / patch / public API / version+schema guards: passed
  • dotnet format whitespace + git diff --check: passed
  • maintainability tests and debt gate: passed
  • Debug build: passed
  • Release build: passed
  • generated-assembly dependency verification: passed
  • Unit tests: passed
  • Generator tests: passed
  • LoadTest tests: passed
  • serialized Integration tests: passed (451/451)

Dev validation run: 34543816894.

Review follow-up validation:

  • added FatalRuntimeFailureWaitOnlyShouldObserveOwnedTerminalCleanupTask, covering StartAsync -> WaitForShutdownAsync without a follow-up StopAsync and asserting the Server-owned terminal cleanup observer completes successfully;
  • review-fix UnitTests, scope guard, git diff --check, and version/schema guard: passed;
  • review thread resolved after the exact-head checks completed.

Final exact-head PR CI on a7f685052a8c18b01b7fc8d9d3e89f2f40280ca5 is green:

  • PR Quick: passed (including Debug/Release build, Unit, Generator, LoadTest, Integration, NativeAOT, package, demo/load/chaos smoke)
  • PR Fast: passed
  • Extension fault containment: passed
  • Pending and codec validation: passed
  • Codec Padding Security Evidence: passed
  • CodeQL: passed

Final branch is one commit ahead of exact dev base and contains no temporary review workflow files. No version/schema bump was introduced.

@SunSi12138
SunSi12138 marked this pull request as ready for review September 11, 2026 01:54

@SunSi12138 SunSi12138 left a comment

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.

整体方向与 #646 一致,#648 两轮 failure-domain 修复也保留住了;exact-head CI 和 base ancestry 当前都没有问题。这里还有一个 Server-owned terminal cleanup task 的 observation 缺口需要先收口。

Comment thread src/SharpLink.Server/ServerLifecycleCoordinator.cs
Make StartAsync/WaitForShutdownAsync/StopAsync the canonical Server lifecycle, preserve runtime-vs-connection failure domains, and explicitly observe the shared terminal cleanup task for fatal runtime paths.
@SunSi12138
SunSi12138 force-pushed the feat/646-server-lifecycle-dev branch from 9429d3c to a7f6850 Compare September 11, 2026 10:09
@SunSi12138
SunSi12138 merged commit d5a74be into dev Sep 11, 2026
15 checks passed
@SunSi12138
SunSi12138 deleted the feat/646-server-lifecycle-dev branch September 11, 2026 11:17
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.

1 participant