Sparkdo.Hosting 0.0.1-preview.1

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.1
                    
NuGet\Install-Package Sparkdo.Hosting -Version 0.0.1-preview.1
                    
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.1" />
                    
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.1" />
                    
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.1
                    
#r "nuget: Sparkdo.Hosting, 0.0.1-preview.1"
                    
#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.1
                    
#: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.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Sparkdo.Hosting&version=0.0.1-preview.1&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.Hosting.MicrosoftExtensions

Sparkdo 统一运行时的 Generic Host 与 Microsoft DI 适配。

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0-preview.2 132 7/20/2026
2.0.0-preview.1 108 7/18/2026
0.0.1-preview.3 58 8/26/2026
0.0.1-preview.2 63 8/25/2026
0.0.1-preview.1 70 8/25/2026