Sparkdo.Console
0.0.1-preview.3
dotnet add package Sparkdo.Console --version 0.0.1-preview.3
NuGet\Install-Package Sparkdo.Console -Version 0.0.1-preview.3
<PackageReference Include="Sparkdo.Console" Version="0.0.1-preview.3" />
<PackageVersion Include="Sparkdo.Console" Version="0.0.1-preview.3" />
<PackageReference Include="Sparkdo.Console" />
paket add Sparkdo.Console --version 0.0.1-preview.3
#r "nuget: Sparkdo.Console, 0.0.1-preview.3"
#:package Sparkdo.Console@0.0.1-preview.3
#addin nuget:?package=Sparkdo.Console&version=0.0.1-preview.3&prerelease
#tool nuget:?package=Sparkdo.Console&version=0.0.1-preview.3&prerelease
Sparkdo.Runtime.Console
Sparkdo.Runtime.Console 为独立控制台进程提供 RuntimeHost 生命周期适配。它将进程级关闭事件收敛为一次有界的停止事务,并返回可供进程入口使用的结构化终止结果。
该包适合直接运行的命令行程序、守护进程和容器入口。它不依赖 Microsoft.Extensions.Hosting;应用已经采用 Generic Host 时,应使用 Sparkdo.Runtime.Hosting.MicrosoftExtensions,避免两个宿主同时管理同一个 Runtime 的启动和关闭。
何时选用
在以下场景选用本包:
- 进程入口需要处理 Ctrl+C、
SIGINT、SIGTERM、调用方取消或ProcessExit。 - 希望把启动、停止、重启请求和失败原因统一为
ConsoleRuntimeRunResult。 - 需要根据稳定的
SuggestedExitCode设置进程退出码。 - 应用直接持有
IRuntimeRegistrationTable或RuntimeHost,而不是由 Generic Host 托管。
在以下场景不要选用本包:
- ASP.NET Core、Worker Service 或其他 Generic Host 应用已经由
IHost管理生命周期。 - 运行时位于另一个进程,或外部编排器才是唯一生命周期所有者。
- 同一个
RuntimeHost已由另一个ConsoleRuntimeHost或应用级宿主管理。
引用
面向 NuGet 的应用引用正式发布包,并将同一运行时集合的包保持在相同版本:
<ItemGroup>
<PackageReference Include="Sparkdo.Runtime.Console" Version="x.y.z" />
</ItemGroup>
同仓开发可直接引用项目:
<ItemGroup>
<ProjectReference Include="path/to/Sparkdo.Runtime.Console/Sparkdo.Runtime.Console.csproj" />
</ItemGroup>
本项目目标框架为 net10.0,并直接依赖 Sparkdo.Runtime.Contracts 与 Sparkdo.Runtime.Hosting。ConsoleRuntimeHost 的构造函数接受现成的 RuntimeHost,也可接受 IRuntimeRegistrationTable 由其创建宿主。
最小可运行示例
下例使用 Sparkdo.Runtime.Testing 的 StaticRuntimeRegistrationTable 构造一个会在一秒后正常停止的最小进程。它用于验证控制台接线;生产应用必须替换为自己的完整注册表或生成的 RuntimeCompositionTable.Instance。
<ItemGroup>
<PackageReference Include="Sparkdo.Runtime.Console" Version="x.y.z" />
<PackageReference Include="Sparkdo.Runtime.Testing" Version="x.y.z" />
</ItemGroup>
using Sparkdo.Runtime.Console;
using Sparkdo.Runtime.Testing;
using var shutdown = new CancellationTokenSource(TimeSpan.FromSeconds(1));
await using var host = new ConsoleRuntimeHost(StaticRuntimeRegistrationTable.Create());
var result = await host.RunWithResultAsync(shutdown.Token);
Console.WriteLine($"终止原因:{result.TerminationReason}");
Console.WriteLine($"建议退出码:{result.SuggestedExitCode}");
return result.SuggestedExitCode;
生产入口通常从应用的运行时组合产物取得注册表:
using Sparkdo.Runtime;
using Sparkdo.Runtime.Console;
IRuntimeRegistrationTable registrations = RuntimeCompositionTable.Instance;
await using var host = new ConsoleRuntimeHost(
registrations,
new RuntimeStopOptions(DrainTimeout: TimeSpan.FromSeconds(20)),
shutdownTimeout: TimeSpan.FromSeconds(30));
var result = await host.RunWithResultAsync();
Environment.ExitCode = result.SuggestedExitCode;
RuntimeCompositionTable 由应用的运行时组合生成流程提供。使用该方式时,应用项目还需要接入 Sparkdo.Runtime.Generators,并完整声明其运行时工件、RuntimeSourceId、RuntimeSourceVersion 与 RuntimeContractVersion。
生命周期与终止结果
每个 ConsoleRuntimeHost 实例只能启动一次运行生命周期。RunWithResultAsync 先调用 RuntimeHost.StartAsync,仅在启动成功且初始协调结果为 Published 时,StartResult.Succeeded 才为 true;随后等待关闭信号或底层 RuntimeHost 到达终态。
运行期间会处理以下关闭来源:
- 调用方传入的
CancellationToken。 - 控制台 Ctrl+C。
- Linux、macOS 和 FreeBSD 上的
SIGINT与SIGTERM。 AppDomain.CurrentDomain.ProcessExit。- Runtime 发出的重启请求。
DisposeAsync。
多个关闭来源并发到达时,首个终止原因生效。ProcessExit 只能发起最后一次不可等待的关闭请求,不能保证排空完成;在容器或服务管理器中应依赖 SIGTERM 并给进程保留足够的优雅关闭时间。
RunWithResultAsync 返回 ConsoleRuntimeRunResult:
| 成员 | 含义 |
|---|---|
StartResult |
启动与初始协调的结构化结果。 |
StopResult |
停止事务结果;未执行停止事务时可以为 null。 |
TerminationReason |
终止来源,例如 ConsoleInterrupt、TerminationSignal、RestartRequested 或 HostFailed。 |
Reason 与 Observation |
运行时提供的稳定原因标识与关联 Observation。 |
SuggestedExitCode |
建议写入进程退出码的整数。 |
IsSuccessfulExit |
当且仅当建议退出码为 0 时为 true。 |
退出码映射固定如下:Ctrl+C 为 130,SIGTERM 为 143,重启请求为 75;启动失败或取消、底层宿主失败、停止超时或失败,以及 DrainTimedOut 或 Quarantined 停止结果均为 1。其他成功完成的关闭路径为 0。
RunAsync 仅把完整运行结果投影为 RuntimeHostStartResult,不会提供终止原因、停止结果或退出码。进程入口需要决定退出码时,应始终使用 RunWithResultAsync。
失败与资源管理
启动或停止过程中发生的运行时失败会尽可能转换为结构化结果,而不是由进程信号线程抛出异常。以下编程错误仍会直接抛出:
- 构造函数传入
null的RuntimeHost或不合法的超时。 - 在同一实例上再次运行。
- 在已开始
DisposeAsync后尝试运行。 - 无法为缺少重启处理器的终态
RuntimeHost接入控制台重启处理器。
始终使用 await using 或在进程收尾处等待 DisposeAsync。Dispose 会请求关闭,并在配置的总关闭时限内等待运行、停止和底层宿主释放;超时后底层宿主保持失败关闭,迟到任务只用于完成资源收尾,不会把状态恢复为成功。
RuntimeStopOptions.DrainTimeout 和 shutdownTimeout 都必须为正值。未显式提供 shutdownTimeout 时,控制台宿主使用 30 秒总关闭时限。该时限应与容器、服务管理器和负载均衡器的终止宽限期协调设置。
生产注意事项
- 不要把
StaticRuntimeRegistrationTable用作业务运行时注册表;它仅适合演示、测试和消费者冒烟验证。 - 将
SuggestedExitCode返回给进程宿主或写入Environment.ExitCode,不要以异常替代正常的重启、信号和停止路径。 - 记录
TerminationReason、Reason?.Code、StopResult?.Status与Observation,以便关联运行时诊断。 - 将 Runtime 的停止排空预算、Console 总关闭时限和外部终止宽限期作为同一个容量与可靠性约束配置。
- 对 Native AOT 或 trim 发布目标执行真实
publish和运行验证;不要只依赖编译器分析结果。
验证
验证仓库中的控制台生命周期规格:
dotnet test ./src/runtime/test/Sparkdo.Runtime.Specification.Tests/Sparkdo.Runtime.Specification.Tests.csproj `
--configuration Release `
--filter "FullyQualifiedName~RuntimeConsoleAdapterTests"
验证应用自身:
dotnet build --configuration Release
dotnet run --configuration Release
dotnet publish --configuration Release --runtime linux-x64 --self-contained true -p:PublishAot=true
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Sparkdo.Hosting (>= 0.0.1-preview.3)
- Sparkdo.Runtime.Contracts (>= 0.0.1-preview.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Sparkdo.Console:
| Package | Downloads |
|---|---|
|
Sparkdo.Hosting.MicrosoftExtensions
Sparkdo 统一运行时的 Generic Host 与 Microsoft DI 适配。 |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1-preview.3 | 51 | 8/26/2026 |
| 0.0.1-preview.2 | 61 | 8/25/2026 |
| 0.0.1-preview.1 | 56 | 8/25/2026 |