Sparkdo.Hosting 0.0.1-preview.3

This is a prerelease version of Sparkdo.Hosting.
There is a newer prerelease version of this package available.
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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Sparkdo.Hosting" Version="0.0.1-preview.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sparkdo.Hosting" Version="0.0.1-preview.3" />
                    
Directory.Packages.props
<PackageReference Include="Sparkdo.Hosting" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Sparkdo.Hosting --version 0.0.1-preview.3
                    
#r "nuget: Sparkdo.Hosting, 0.0.1-preview.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Sparkdo.Hosting@0.0.1-preview.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Sparkdo.Hosting&version=0.0.1-preview.3&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Sparkdo.Hosting&version=0.0.1-preview.3&prerelease
                    
Install as a Cake Tool

Sparkdo.Runtime.Hosting

Sparkdo.Runtime.Hosting 为 Sparkdo Runtime 提供框架无关的宿主生命周期。它负责把已经准备好的 IRuntimeRegistrationTableCatalogInputs 与可选的 HostBindingSnapshot 组织成一次可观察、可停止、可重协调的运行时会话;它不引用 Microsoft.Extensions.Hosting、依赖注入容器、配置系统、控制台或 Web 框架。

这个包适合需要自行掌控进程模型、生命周期信号、重启协调和关闭时限的应用、嵌入式宿主与平台适配层。使用 .NET Generic Host、Microsoft DI 或 IConfiguration 时,应改用 Sparkdo.Runtime.Hosting.MicrosoftExtensions,由该适配包完成接线。

包定位

需求 应选择的包
自行创建和停止运行时,不依赖任何宿主框架 Sparkdo.Runtime.Hosting
使用 IHostApplicationBuilderIServiceCollectionIConfiguration、健康检查或 OpenTelemetry Sparkdo.Runtime.Hosting.MicrosoftExtensions
需要控制台信号、退出码与进程重启语义 Sparkdo.Runtime.Console,或直接使用 Sparkdo.Runtime.Hosting.MicrosoftExtensions 提供的 RuntimeConsoleConfigurationHost

基础包依赖 Sparkdo.Runtime.ContractsSparkdo.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 已成功发布,RuntimeCurrentRevision 可用。
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.StartedReconciliation.Outcome == ReconciliationOutcome.Published 时为 true
  • Creation 保留 Runtime 创建结果;Catalog 保留 Catalog 创建和验证结果;Reconciliation 保留首次发布的结构化结果和原因代码。
  • 注册表创建 Runtime、创建 Catalog 或提交首次重协调失败时,宿主返回失败的结构化结果,并清理可安全清理的 Runtime。
  • 调用方传入的取消令牌在启动过程中被取消时,StartAsync 抛出 OperationCanceledException,宿主转为 Failed
  • 成功的首次启动结果会被缓存;重复调用 StartAsync 会得到同一成功结果。处于 StartingStopping 时,调用会返回当前状态的未完成结果,不能据此取得 Runtime。

启动成功后,Runtime 才可使用。不要在 CreatedStartingStoppingFailed 状态调用其成员,也不要把 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 在重协调时使用。

重启请求

当重协调结果为 RestartRequestedQuarantinedRuntimeHost 需要通过 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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