Sparkdo.Hosting
0.0.1-preview.3
See the version list below for details.
dotnet add package Sparkdo.Hosting --version 0.0.1-preview.3
NuGet\Install-Package Sparkdo.Hosting -Version 0.0.1-preview.3
<PackageReference Include="Sparkdo.Hosting" Version="0.0.1-preview.3" />
<PackageVersion Include="Sparkdo.Hosting" Version="0.0.1-preview.3" />
<PackageReference Include="Sparkdo.Hosting" />
paket add Sparkdo.Hosting --version 0.0.1-preview.3
#r "nuget: Sparkdo.Hosting, 0.0.1-preview.3"
#:package Sparkdo.Hosting@0.0.1-preview.3
#addin nuget:?package=Sparkdo.Hosting&version=0.0.1-preview.3&prerelease
#tool nuget:?package=Sparkdo.Hosting&version=0.0.1-preview.3&prerelease
Sparkdo.Runtime.Hosting
Sparkdo.Runtime.Hosting 为 Sparkdo Runtime 提供框架无关的宿主生命周期。它负责把已经准备好的 IRuntimeRegistrationTable、CatalogInputs 与可选的 HostBindingSnapshot 组织成一次可观察、可停止、可重协调的运行时会话;它不引用 Microsoft.Extensions.Hosting、依赖注入容器、配置系统、控制台或 Web 框架。
这个包适合需要自行掌控进程模型、生命周期信号、重启协调和关闭时限的应用、嵌入式宿主与平台适配层。使用 .NET Generic Host、Microsoft DI 或 IConfiguration 时,应改用 Sparkdo.Runtime.Hosting.MicrosoftExtensions,由该适配包完成接线。
包定位
| 需求 | 应选择的包 |
|---|---|
| 自行创建和停止运行时,不依赖任何宿主框架 | Sparkdo.Runtime.Hosting |
使用 IHostApplicationBuilder、IServiceCollection、IConfiguration、健康检查或 OpenTelemetry |
Sparkdo.Runtime.Hosting.MicrosoftExtensions |
| 需要控制台信号、退出码与进程重启语义 | Sparkdo.Runtime.Console,或直接使用 Sparkdo.Runtime.Hosting.MicrosoftExtensions 提供的 RuntimeConsoleConfigurationHost |
基础包依赖 Sparkdo.Runtime.Contracts 与 Sparkdo.Runtime。因此它只处理运行时协议和生命周期,不会替应用装配注册表、读取配置或替进程执行重启。
安装
在应用项目中安装与其余 Sparkdo Runtime 包相同版本的包:
dotnet add package Sparkdo.Runtime.Hosting
源代码方式引用时:
<ProjectReference Include="../Sparkdo.Runtime.Hosting/Sparkdo.Runtime.Hosting.csproj" />
应用还必须提供一个有效的 IRuntimeRegistrationTable。该表通常由应用的组合根或 Sparkdo 生成器产物提供;RuntimeHost 不会扫描程序集、也不会从容器中猜测注册项。
核心模型
RuntimeHost 是一个 IAsyncDisposable,其公开状态由 RuntimeHostStatus 表示:
| 状态 | 含义 |
|---|---|
Created |
已构造,尚未开始首次发布。 |
Starting |
正在创建 Runtime、创建 Catalog 或提交首次重协调。 |
Started |
首次 Catalog 已成功发布,Runtime 与 CurrentRevision 可用。 |
Stopping |
正在执行停止和排空。 |
Stopped |
已正常停止。 |
Failed |
已发生启动、重协调、停止或失败关闭问题;不能把它当作可用状态。 |
以下成员构成基础调用面:
| 成员 | 用途 |
|---|---|
StartAsync(...) |
创建 Runtime、创建首次 Catalog 并提交首次发布。 |
UpdateCatalogAsync(...) |
使用新 CatalogInputs 提交一次重协调。 |
UpdateCatalogIfCurrentAsync(...) |
以 CatalogRevision 做乐观并发保护的更新。 |
StopAsync(...) |
关闭接纳、排空并停止 Runtime。 |
Runtime |
当前公开可用的 IRuntime;未启动、已停止或失败关闭时为 null。 |
CurrentRevision |
最近一次已发布的 Catalog 修订;首次发布前、停止后或失败关闭后为 null。 |
Status |
当前宿主状态。 |
最小可用接线
组合根需要传入真实的注册表和首次输入。下面的辅助方法不假定注册表的生成方式,因而可直接放入应用的宿主层:
using Sparkdo.Runtime;
using Sparkdo.Runtime.Hosting;
static async ValueTask<RuntimeHostStartResult> RunRuntimeAsync(
IRuntimeRegistrationTable registrations,
CatalogInputs initialInputs,
CancellationToken cancellationToken)
{
await using var host = new RuntimeHost(
registrations,
options: new RuntimeOptions(),
initialInputs: initialInputs);
var started = await host.StartAsync(cancellationToken);
if (!started.Succeeded)
{
return started;
}
// 在此期间通过 host.Runtime 使用已发布的运行时。
var stopped = await host.StopAsync(
new RuntimeStopOptions(DrainTimeout: TimeSpan.FromSeconds(30)),
CancellationToken.None);
if (stopped.Status != RuntimeStopStatus.Stopped)
{
throw new InvalidOperationException(
$"运行时未完成停止。原因代码:{stopped.Reason?.Code}");
}
return started;
}
await using 仍然必要:它会在调用路径出现异常时执行最终收尾。正常路径中显式调用 StopAsync 可以让应用检查 RuntimeStopResult,而随后的 DisposeAsync 是幂等的收尾调用。
若首次输入只应在实际启动时计算,可以使用同步工厂:
var host = RuntimeHost.CreateWithInitialInputsFactory(
registrations,
initialInputsFactory: BuildInitialInputs,
options: new RuntimeOptions());
BuildInitialInputs 的返回类型必须是 CatalogInputs。需要可取消的异步配置或机密引用解析时,请使用 Microsoft 适配包的配置入口,而不是在此处阻塞异步操作。
启动与失败语义
StartAsync 返回 RuntimeHostStartResult,不要仅用异常判断首次发布是否成功:
Succeeded仅在Status == RuntimeHostStatus.Started且Reconciliation.Outcome == ReconciliationOutcome.Published时为true。Creation保留 Runtime 创建结果;Catalog保留 Catalog 创建和验证结果;Reconciliation保留首次发布的结构化结果和原因代码。- 注册表创建 Runtime、创建 Catalog 或提交首次重协调失败时,宿主返回失败的结构化结果,并清理可安全清理的 Runtime。
- 调用方传入的取消令牌在启动过程中被取消时,
StartAsync抛出OperationCanceledException,宿主转为Failed。 - 成功的首次启动结果会被缓存;重复调用
StartAsync会得到同一成功结果。处于Starting或Stopping时,调用会返回当前状态的未完成结果,不能据此取得 Runtime。
启动成功后,Runtime 才可使用。不要在 Created、Starting、Stopping 或 Failed 状态调用其成员,也不要把 Runtime is null 当作重试已经完成的信号。
Catalog 更新与并发控制
运行中的配置变化必须转换为新的 CatalogInputs 后提交,而不是修改旧 Catalog:
static async ValueTask ApplyInputsAsync(
RuntimeHost host,
CatalogInputs nextInputs,
CancellationToken cancellationToken)
{
if (host.CurrentRevision is not { } currentRevision)
{
throw new InvalidOperationException("运行时尚未完成首次发布,不能提交更新。");
}
var update = await host.UpdateCatalogIfCurrentAsync(
nextInputs,
currentRevision,
cancellationToken);
if (!update.Catalog.Succeeded)
{
// Catalog 验证失败时,已发布 Runtime 保持原状;处理验证报告后再提交新候选。
return;
}
switch (update.Reconciliation?.Outcome)
{
case ReconciliationOutcome.Published:
// host.CurrentRevision 已更新。
break;
case ReconciliationOutcome.Superseded:
// 有更晚的更新已获胜,重新读取 CurrentRevision 后决定是否重试。
break;
case ReconciliationOutcome.RestartRequested:
case ReconciliationOutcome.Quarantined:
case ReconciliationOutcome.Rejected:
default:
// 记录 Reconciliation?.Reason 与宿主状态,交由应用的失败/重启策略处理。
break;
}
}
使用 UpdateCatalogIfCurrentAsync 可防止较旧的异步读取结果覆盖较新的已发布版本。其 expectedCurrentRevision 不匹配时,调用方应把 Superseded 视为正常并发结果,而不是当作已发布成功。
UpdateCatalogAsync 的两个重载适合不需要版本比较的串行更新。两个更新入口都允许随候选传入 HostBindingSnapshot;首次启动和后续更新会保留最近一次已接受的 Host 绑定快照,供 Runtime 在重协调时使用。
重启请求
当重协调结果为 RestartRequested 或 Quarantined,RuntimeHost 需要通过 IRuntimeHostRestartHandler 将原因交给最外层宿主:
public interface IRuntimeHostRestartHandler
{
ValueTask RequestRestartAsync(
RuntimeReason reason,
CancellationToken cancellationToken = default);
}
在构造函数或 CreateWithInitialInputsFactory 中传入该处理器。处理器应请求外部编排器停止或替换进程,并记录 RuntimeReason.Code;它不应仅返回成功而不执行任何处置。未提供处理器,或处理器抛出异常、被取消时,重启转发会变成 Rejected,宿主进入失败关闭路径。
本包没有单独的 RestartAsync。受控重启流程应先让 StopAsync 返回 RuntimeStopStatus.Stopped,再对同一实例调用 StartAsync。停止未完成、隔离或失败关闭后,应把该实例视为不可重新投入使用,并创建新的进程或新的宿主实例。
停止、排空与处置
StopAsync 接受 RuntimeStopOptions,其中 DrainTimeout 用于限定 Runtime 的排空时间:
var result = await host.StopAsync(
new RuntimeStopOptions(DrainTimeout: TimeSpan.FromSeconds(20)),
CancellationToken.None);
RuntimeStopStatus.Stopped表示 Runtime 已停止;若 Runtime 实现IAsyncDisposable,宿主随后处置它,状态转为Stopped。- 非
Stopped的停止结果,例如排空超时或隔离,不能被报告为成功停止。宿主转为失败关闭,并保留内部所有权以便迟到收尾;公开的Runtime会变为null。 - 停止过程抛出异常,或调用方的取消令牌在进入生命周期闸门前取消时,宿主同样失败关闭。不要在这种情况下继续接纳请求或再次把实例作为可用 Runtime 暴露。
DisposeAsync可并发、重复调用。它会尝试在无取消令牌下完成停止,且不会把内部收尾异常重新抛给释放方;业务代码仍应在正常关闭路径先检查StopAsync的结果。
生产组合根应把停止超时视为进程级故障:停止接纳新流量、保留原因与观测信息、由上层监督器替换实例,而不是对仍有未确认资源的宿主做就地重启。
健康检查与遥测
基础包不注册健康检查、日志提供程序、Activity、Meter 或 OpenTelemetry 管道,以保持其框架无关边界。需要这些能力时使用 Sparkdo.Runtime.Hosting.MicrosoftExtensions;该包会基于同一个 RuntimeHost 添加健康检查和生命周期遥测。
依赖边界
Sparkdo.Runtime.Hosting 只依赖 Sparkdo Runtime 的契约和实现层。它不会:
- 从
IConfiguration读取输入; - 注册
IHostedService或调用IHostApplicationLifetime; - 使用
IServiceProvider构造 Runtime; - 处理控制台信号、设置退出码或启动新进程;
- 自动把
HostRestart解释为系统级重启。
这些职责应保留在应用组合根或对应的外层适配包中,避免 Runtime Core 与具体宿主框架耦合。
验证
在仓库根目录执行:
dotnet build src/runtime/src/Sparkdo.Runtime.Hosting/Sparkdo.Runtime.Hosting.csproj --configuration Release
dotnet test src/runtime/test/Sparkdo.Runtime.Specification.Tests/Sparkdo.Runtime.Specification.Tests.csproj --configuration Release --filter "FullyQualifiedName~RuntimeHostLifecycleTests"
第二条命令覆盖宿主启动、Catalog 失败、重启转发、停止排空、失败关闭与并发处置的规范行为。
| 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.Runtime (>= 0.0.1-preview.3)
- Sparkdo.Runtime.Contracts (>= 0.0.1-preview.3)
NuGet packages (8)
Showing the top 5 NuGet packages that depend on Sparkdo.Hosting:
| Package | Downloads |
|---|---|
|
Sparkdo.VirtualFileSystem
用于物化 Sparkdo 应用与包资产的虚拟文件系统运行时。 |
|
|
Sparkdo.Mediation
Sparkdo Mediation 的 generated dispatch runtime 与 application bootstrap 集成。 |
|
|
Sparkdo.App
提供编译与宿主支持的 Sparkdo 应用编写元包。 |
|
|
Sparkdo.Console
Sparkdo 统一运行时的控制台宿主适配。 |
|
|
Sparkdo.Scheduler
Sparkdo Scheduler runtime package and embedded source generator asset. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0-preview.2 | 131 | 7/20/2026 |
| 2.0.0-preview.1 | 108 | 7/18/2026 |
| 0.0.1-preview.3 | 46 | 8/26/2026 |
| 0.0.1-preview.2 | 49 | 8/25/2026 |
| 0.0.1-preview.1 | 55 | 8/25/2026 |