Sparkdo.Runtime 0.0.1-preview.3

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

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

Sparkdo.Runtime.Testing

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 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