Sparkdo.Runtime 0.0.1-preview.2

This is a prerelease version of Sparkdo.Runtime.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Sparkdo.Runtime --version 0.0.1-preview.2
                    
NuGet\Install-Package Sparkdo.Runtime -Version 0.0.1-preview.2
                    
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.Runtime" Version="0.0.1-preview.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sparkdo.Runtime" Version="0.0.1-preview.2" />
                    
Directory.Packages.props
<PackageReference Include="Sparkdo.Runtime" />
                    
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.Runtime --version 0.0.1-preview.2
                    
#r "nuget: Sparkdo.Runtime, 0.0.1-preview.2"
                    
#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.Runtime@0.0.1-preview.2
                    
#: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.Runtime&version=0.0.1-preview.2&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Sparkdo.Runtime&version=0.0.1-preview.2&prerelease
                    
Install as a Cake Tool

Sparkdo.Runtime

Sparkdo.Runtime 是 Sparkdo 的执行内核。它从显式 IRuntimeRegistrationTable 创建 IRuntime,验证注册与 Catalog,构建计划和候选能力,执行重协调,维护活动快照,并管理导出租约、排空、停止与隔离。

本包只依赖 Sparkdo.Runtime.Contracts。它不扫描程序集,不直接依赖 Generic Host、依赖注入或配置框架;这些集成由相邻适配器包完成。

何时使用

在以下情况下直接使用内核:

  • 应用已有显式注册表,或由 Sparkdo.Runtime.Generators 生成了 RuntimeCompositionTable
  • 需要在没有 Microsoft.Extensions.Hosting 的进程、嵌入式宿主或专用服务框架中管理运行时生命周期。
  • 需要直接提交 Catalog、传入 HostBindingSnapshot、读取重协调结果,或在自定义控制面中管理停止结果。
  • 需要通过 SnapshotScopeLease<T> 访问一个一致快照中的导出。

若应用已经使用适配器,优先让适配器拥有内核:

  • 使用独立宿主生命周期时,使用 Sparkdo.Runtime.Hosting
  • 使用 Generic Host、Microsoft DI 和配置时,使用 Sparkdo.Runtime.Hosting.MicrosoftExtensions
  • 使用控制台信号、SIGTERM 和退出码时,使用 Sparkdo.Runtime.Console,或使用组合适配器。
  • 将配置读取转换为 CatalogInputs 时,使用 Sparkdo.Runtime.ConfigurationSparkdo.Runtime.Configuration.MicrosoftExtensions

安装与组合前提

dotnet add package Sparkdo.Runtime

Sparkdo.Runtime.Contracts 会作为项目引用随内核提供;应用代码通常仍应显式引用其命名空间:

using Sparkdo.Runtime;

运行时创建需要一个 IRuntimeRegistrationTable。生产组合根应使用 Sparkdo.Runtime.Generators 生成 RuntimeCompositionTable,而不是手写反射扫描或在启动时拼装不受验证的注册记录。

dotnet add package Sparkdo.Runtime.Generators

当组合根设置 SparkdoRuntimeCompositionRequired=true 时,内核包携带的构建规则要求该项目直接引用 Sparkdo.Runtime.Generators。缺少生成器资产时,构建会以 SRR1006 失败。

执行模型

flowchart TD
    A[显式注册表或生成的 RuntimeCompositionTable] --> B[RuntimeFactory.Create]
    B --> C{RuntimeCreationResult}
    C -->|成功| D[IRuntime]
    C -->|拒绝| E[ValidationReport 和 RuntimeReason]
    A --> F[CreateCatalog: CatalogInputs]
    F --> G[ReconciliationRequest]
    D --> H[SubmitReconciliationAsync]
    G --> H
    H --> I{ReconciliationResult}
    I -->|Published| J[活动 RuntimeSnapshot]
    J --> K[OpenScope]
    K --> L[SnapshotScope]
    L --> M[AcquireAsync: Lease T]
    D --> N[StopAsync]
    N --> O[关闭接纳与排空]

内核在创建阶段只读取一次注册表并冻结其注册快照,再执行绑定和选项校验。后续 Catalog 创建由该注册表负责;内核将经过验证的 Catalog 转换为计划与候选版本。发布成功后,新的 RuntimeSnapshot 成为新作用域的视图,既有作用域继续使用它们已固定的快照,直到自行释放。

主要 API

API 作用 关键检查
RuntimeFactory.Create(IRuntimeRegistrationTable, RuntimeOptions) 创建并校验运行时内核。 检查 RuntimeCreationResult.SucceededValidationReason
IRuntime.SubmitReconciliationAsync(ReconciliationRequest) 根据 Catalog、可选 Host 绑定与预期版本执行一次重协调。 ReconciliationOutcome 分支,不能把完成任务等同于已发布。
IRuntime.OpenScope() 尝试固定当前活动快照。 检查 ScopeOpenResult.Succeeded 和非空 Scope
SnapshotScope.AcquireAsync<T>(Export<T>) 在固定快照内获取导出并创建租约。 释放 Lease<T>;处理 ExportNotFoundExceptionCapabilityUnavailableException
IRuntime.StopAsync(RuntimeStopOptions) 关闭新接纳、协调在途工作并排空活动快照。 检查 RuntimeStopStatus,尤其是 DrainTimedOutQuarantined

RuntimeOptions 允许设置最大准备并发度、取消确认期限、ObservationOptions、观测接收器与 RuntimePolicy。把这些选项视为进程级运维策略,不要在单次业务请求中随意改变它们。

最小可运行示例

下面的程序可以直接用于验证内核的创建、首次发布、作用域、导出租约和停止流程。它使用 Sparkdo.Runtime.Testing 中的固定静态注册表,因此仅用于开发验证、包消费者冒烟测试和示例;生产应用应替换为生成的组合注册表。

dotnet add package Sparkdo.Runtime
dotnet add package Sparkdo.Runtime.Testing
using System;
using Sparkdo.Runtime;
using Sparkdo.Runtime.Testing;

var registrations = StaticRuntimeRegistrationTable.Create();

var catalogResult = registrations.CreateCatalog(CatalogInputs.Empty);
if (!catalogResult.Succeeded || catalogResult.Catalog is null)
{
    throw new InvalidOperationException("Catalog 创建失败。");
}

var creation = RuntimeFactory.Create(registrations);
if (!creation.Succeeded || creation.Runtime is null)
{
    throw new InvalidOperationException("Runtime 创建失败。");
}

var runtime = creation.Runtime;
if (runtime is not IAsyncDisposable ownedRuntime)
{
    throw new InvalidOperationException("直接创建的 Runtime 未提供异步释放能力。");
}

await using (ownedRuntime)
{
    var published = await runtime.SubmitReconciliationAsync(
        new ReconciliationRequest(catalogResult.Catalog));
    if (published.Outcome != ReconciliationOutcome.Published)
    {
        throw new InvalidOperationException("初始 Catalog 未发布。");
    }

    var opened = runtime.OpenScope();
    if (!opened.Succeeded || opened.Scope is null)
    {
        throw new InvalidOperationException("活动快照不可用。");
    }

    await using (opened.Scope)
    {
        await using var lease = await opened.Scope.AcquireAsync(registrations.CreateExport());
        Console.WriteLine(lease.Value);
    }

    var stopped = await runtime.StopAsync(new RuntimeStopOptions());
    if (stopped.Status != RuntimeStopStatus.Stopped)
    {
        throw new InvalidOperationException("Runtime 未正常停止。");
    }
}

示例中的 IAsyncDisposable 检查是直接内核组合的所有权边界:IRuntime 契约只定义控制面,当前内核实现支持异步释放,因此示例通过运行时检查取得该能力。宿主适配器创建内核时,应用不应重复释放其拥有的运行时。

生产组合入口

下列代码展示实际的生成边界。RuntimeCompositionTable 是由 Sparkdo.Runtime.Generators 在组合根生成的类型,不是本包提供的手写类;应用只消费它的 IRuntimeRegistrationTable 实例。

using Sparkdo.Runtime;

[assembly: RuntimeComposition("orders.api")]

// ----- 生成器负责的边界 -----
IRuntimeRegistrationTable registrations = RuntimeCompositionTable.Instance;

// ----- Runtime 内核负责的边界 -----
var catalogResult = registrations.CreateCatalog(CatalogInputs.Empty);
if (!catalogResult.Succeeded || catalogResult.Catalog is null)
{
    throw new InvalidOperationException("Catalog 创建失败。");
}

var creation = RuntimeFactory.Create(registrations);
if (!creation.Succeeded || creation.Runtime is null)
{
    throw new InvalidOperationException("Runtime 创建失败。");
}

var result = await creation.Runtime.SubmitReconciliationAsync(
    new ReconciliationRequest(catalogResult.Catalog));

生成器负责构建期工件收集、注册表生成和组合根验证。内核不读取项目文件、不发现程序集,也不替代生成器的构建协议。

生命周期、并发与失败关闭

创建失败

RuntimeFactory.Create 将注册、选项或内部创建失败表示为 RuntimeCreationResult

  • Succeeded == false 时,Runtime 为空;读取 Validation.IssuesReason 后修正组合或部署条件。
  • 不要在创建失败后继续调用 CreateCatalogSubmitReconciliationAsync 或通过空引用绕过验证。
  • 注册表在创建中被冻结并校验;生产注册实现不得在创建后改变 EnvironmentEntriesContributions 的含义。

重协调结果

一次 SubmitReconciliationAsync 可以与其他提交并发发生。相同请求可共享执行,新的候选请求可替代待处理工作;调用方必须把 ReconciliationResult 当作最终事实。

结果 含义 推荐处理
Published 新快照已发布且可用于新作用域。 更新控制面版本与健康状态。
Rejected 请求、Catalog、策略或生命周期条件被拒绝。 记录 ReasonObservation,修正输入后按业务策略重试。
Superseded 当前请求被更近的候选状态替代。 读取最新期望状态后重新决定,不要盲目重放旧请求。
RestartRequested 选定的切换或排空策略要求宿主重启。 交给 RuntimeHost、服务管理器或编排器执行受控重启。
Quarantined 内核无法安全确认状态或清理结果。 关闭普通请求,保留诊断,按事故流程恢复实例。

ExpectedCurrentRevision 用于保护控制面的版本比较。提交新的 HostBindingSnapshot 时应同时推进其 HostBindingRevision,并提供准确的 SourceIdentity;这样运行时能将宿主输入视为一次明确的快照,而非从可变容器中随时读取。

快照与租约

OpenScope() 是业务调用进入活动快照的入口:

  • 成功时,SnapshotScope 固定一个完整快照。该作用域内部的多次导出获取都在同一视图中完成。
  • 发布新 Catalog 后,旧作用域仍可完成已建立视图中的工作;新作用域使用新快照。
  • 作用域关闭后调用 AcquireAsync 会引发 ObjectDisposedException
  • Lease<T>.Value 只在租约未释放时可读取;释放后访问会引发 ObjectDisposedException
  • 导出获取的取消令牌会在 Provider 副作用之前被检查;为每次请求传递真实的取消令牌。

必须以如下结构管理所有权:

var opened = runtime.OpenScope();
if (!opened.Succeeded || opened.Scope is null)
{
    return;
}

await using (opened.Scope)
{
    await using var lease = await opened.Scope.AcquireAsync(requiredExport, cancellationToken);
    await UseAsync(lease.Value, cancellationToken);
}

上例中的 requiredExportUseAsync 是应用代码提供的边界;SnapshotScopeLease<T>AcquireAsync 是实际运行时 API。不要把作用域或租约提升为单例、缓存对象或后台任务的跨调用状态。

停止、排空与隔离

StopAsync 关闭新作用域接纳,取消在途和待处理的重协调,等待活动快照中的作用域与租约排空,再执行退役与清理。RuntimeStopOptions.DrainTimeout 必须为正数;未指定时内核使用默认排空期限。

状态 内核状态 宿主必须做什么
Stopped 无活动快照,运行时不可用。 完成进程或服务关闭。
DrainTimedOut 新接纳关闭,现有工作未按时释放。 保持实例不可用,记录 ReasonObservation,由编排器处置。
Quarantined 取消确认、清理或生命周期状态无法安全证明。 停止普通流量,收集诊断并执行恢复或重启。

停止不是“忽略返回值的清理调用”。特别是 DrainTimedOutQuarantined 不能报告为正常停止,也不能继续向该内核开放新作用域。

观测与运维

通过 RuntimeOptions 提供 ObservationOptionsImmutableArray<IObservationSink>。内核将观测异步分派到有界队列,并由 ObservationOptions 控制容量、溢出方式、属性上限和排空期限。

生产接入应做到:

  • 为每个 IObservationSink.TryWrite 实现无阻塞、快速失败或受控排队语义,避免观测接收器阻塞核心状态转换。
  • 将所有 ReconciliationResult.ObservationScopeOpenResult.ObservationRuntimeStopResult.Observation 与业务请求、Catalog Revision 和宿主实例关联。
  • RuntimeReason.Code 作为稳定的自动化分类字段,把参数作为诊断上下文;不要通过解析异常文本决定恢复动作。
  • RejectedRestartRequestedDrainTimedOutQuarantined 建立明确的告警、重试、重启或人工介入策略。

生产接入清单

  • 组合根直接引用 Sparkdo.Runtime.Generators,声明 SparkdoRuntimeCompositionRequired=true,并消费生成的 RuntimeCompositionTable.Instance
  • 启动前创建 CatalogInputs,并检查 CatalogCreationResult;不要将未经验证的 JSON、环境变量或服务容器对象直接传给能力。
  • 需要宿主对象时,以 HostBindingSnapshot 传入,并让每次更新带有新的 Revision 和 Source。
  • 所有重协调、打开作用域和停止调用都处理结构化结果,不把异常作为唯一失败信号。
  • 每个业务请求都在最小作用域内创建并释放 SnapshotScopeLease<T>;设定请求取消令牌和上层超时。
  • 以部署现实填写 RuntimeEnvironment 与能力的 CapabilityRuntime,尤其是 AOT、trimming、Profile、资源限制和允许的切换模式。
  • 设置与负载匹配的准备并发度、观测容量、取消确认期限和排空期限,并持续监测超时和隔离结果。
  • 让单一宿主拥有一个内核实例的停止与释放权;不要在应用、控制台适配器和 Generic Host 之间重复停止同一对象。

与邻近项目的边界

项目 职责边界
Sparkdo.Runtime.Contracts 定义本包使用的公共协议、值对象、接口、请求和结果;不执行运行时。
Sparkdo.Runtime.Generators 构建期收集工件、验证组合根并生成注册表;不管理执行期快照。
Sparkdo.Runtime.Hosting RuntimeFactory、首次发布、Catalog 更新和停止组织为框架无关的宿主生命周期。
Sparkdo.Runtime.Hosting.MicrosoftExtensions 把运行时宿主接入 Generic Host、Microsoft DI 与配置驱动流程。
Sparkdo.Runtime.Console 将控制台信号与退出码接入 RuntimeHost,不直接替代内核重协调。
Sparkdo.Runtime.Configuration 根据显式输入路由构造 CatalogInputs,不持有或执行 IRuntime
Sparkdo.Runtime.Configuration.MicrosoftExtensions IConfiguration 的显式键绑定为运行时输入。
Sparkdo.Runtime.Testing 提供静态注册表和测试夹具,仅用于验证。
Sparkdo.Runtime.Inspection 提供只读状态与拓扑投影,不暴露能力 Provider、导出实例或 Host 绑定对象。

验证命令

在仓库根目录执行:

dotnet restore src/runtime/Sparkdo.Runtime.slnx
dotnet build src/runtime/src/Sparkdo.Runtime.Contracts/Sparkdo.Runtime.Contracts.csproj --configuration Release --no-restore
dotnet build src/runtime/src/Sparkdo.Runtime/Sparkdo.Runtime.csproj --configuration Release --no-restore
dotnet test src/runtime/test/Sparkdo.Runtime.Specification.Tests/Sparkdo.Runtime.Specification.Tests.csproj --configuration Release --no-restore

真实组合根还应执行其自身的 dotnet build。发布到目标运行时标识符后,至少验证一次生成注册表、Catalog 创建、首次 Published、导出租约释放和 StopAsync 的完整路径。

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 (6)

Showing the top 5 NuGet packages that depend on Sparkdo.Runtime:

Package Downloads
Sparkdo.VirtualFileSystem

用于物化 Sparkdo 应用与包资产的虚拟文件系统运行时。

Sparkdo.Hosting

Sparkdo 运行时的 .NET 宿主适配与应用启动支持。

Sparkdo.Scheduler

Sparkdo Scheduler runtime package and embedded source generator asset.

Sparkdo.Instrumentation

提供 Sparkdo activity、metric 和 recorder 的运行时 instrumentation 支持。

Sparkdo.Runtime.Inspection

Sparkdo 统一运行时的只读检查投影。

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0-preview.2 135 7/20/2026
2.0.0-preview.1 123 7/18/2026
0.0.1-preview.3 66 8/26/2026
0.0.1-preview.2 74 8/25/2026
0.0.1-preview.1 92 8/25/2026