Sparkdo.Runtime
0.0.1-preview.2
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
<PackageReference Include="Sparkdo.Runtime" Version="0.0.1-preview.2" />
<PackageVersion Include="Sparkdo.Runtime" Version="0.0.1-preview.2" />
<PackageReference Include="Sparkdo.Runtime" />
paket add Sparkdo.Runtime --version 0.0.1-preview.2
#r "nuget: Sparkdo.Runtime, 0.0.1-preview.2"
#:package Sparkdo.Runtime@0.0.1-preview.2
#addin nuget:?package=Sparkdo.Runtime&version=0.0.1-preview.2&prerelease
#tool nuget:?package=Sparkdo.Runtime&version=0.0.1-preview.2&prerelease
Sparkdo.Runtime
Sparkdo.Runtime 是 Sparkdo 的执行内核。它从显式 IRuntimeRegistrationTable 创建 IRuntime,验证注册与 Catalog,构建计划和候选能力,执行重协调,维护活动快照,并管理导出租约、排空、停止与隔离。
本包只依赖 Sparkdo.Runtime.Contracts。它不扫描程序集,不直接依赖 Generic Host、依赖注入或配置框架;这些集成由相邻适配器包完成。
何时使用
在以下情况下直接使用内核:
- 应用已有显式注册表,或由
Sparkdo.Runtime.Generators生成了RuntimeCompositionTable。 - 需要在没有
Microsoft.Extensions.Hosting的进程、嵌入式宿主或专用服务框架中管理运行时生命周期。 - 需要直接提交 Catalog、传入
HostBindingSnapshot、读取重协调结果,或在自定义控制面中管理停止结果。 - 需要通过
SnapshotScope和Lease<T>访问一个一致快照中的导出。
若应用已经使用适配器,优先让适配器拥有内核:
- 使用独立宿主生命周期时,使用
Sparkdo.Runtime.Hosting。 - 使用 Generic Host、Microsoft DI 和配置时,使用
Sparkdo.Runtime.Hosting.MicrosoftExtensions。 - 使用控制台信号、
SIGTERM和退出码时,使用Sparkdo.Runtime.Console,或使用组合适配器。 - 将配置读取转换为
CatalogInputs时,使用Sparkdo.Runtime.Configuration或Sparkdo.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.Succeeded、Validation 和 Reason。 |
IRuntime.SubmitReconciliationAsync(ReconciliationRequest) |
根据 Catalog、可选 Host 绑定与预期版本执行一次重协调。 | 按 ReconciliationOutcome 分支,不能把完成任务等同于已发布。 |
IRuntime.OpenScope() |
尝试固定当前活动快照。 | 检查 ScopeOpenResult.Succeeded 和非空 Scope。 |
SnapshotScope.AcquireAsync<T>(Export<T>) |
在固定快照内获取导出并创建租约。 | 释放 Lease<T>;处理 ExportNotFoundException 与 CapabilityUnavailableException。 |
IRuntime.StopAsync(RuntimeStopOptions) |
关闭新接纳、协调在途工作并排空活动快照。 | 检查 RuntimeStopStatus,尤其是 DrainTimedOut 和 Quarantined。 |
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.Issues和Reason后修正组合或部署条件。- 不要在创建失败后继续调用
CreateCatalog、SubmitReconciliationAsync或通过空引用绕过验证。 - 注册表在创建中被冻结并校验;生产注册实现不得在创建后改变
Environment、Entries或Contributions的含义。
重协调结果
一次 SubmitReconciliationAsync 可以与其他提交并发发生。相同请求可共享执行,新的候选请求可替代待处理工作;调用方必须把 ReconciliationResult 当作最终事实。
| 结果 | 含义 | 推荐处理 |
|---|---|---|
Published |
新快照已发布且可用于新作用域。 | 更新控制面版本与健康状态。 |
Rejected |
请求、Catalog、策略或生命周期条件被拒绝。 | 记录 Reason、Observation,修正输入后按业务策略重试。 |
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);
}
上例中的 requiredExport 和 UseAsync 是应用代码提供的边界;SnapshotScope、Lease<T> 和 AcquireAsync 是实际运行时 API。不要把作用域或租约提升为单例、缓存对象或后台任务的跨调用状态。
停止、排空与隔离
StopAsync 关闭新作用域接纳,取消在途和待处理的重协调,等待活动快照中的作用域与租约排空,再执行退役与清理。RuntimeStopOptions.DrainTimeout 必须为正数;未指定时内核使用默认排空期限。
| 状态 | 内核状态 | 宿主必须做什么 |
|---|---|---|
Stopped |
无活动快照,运行时不可用。 | 完成进程或服务关闭。 |
DrainTimedOut |
新接纳关闭,现有工作未按时释放。 | 保持实例不可用,记录 Reason 和 Observation,由编排器处置。 |
Quarantined |
取消确认、清理或生命周期状态无法安全证明。 | 停止普通流量,收集诊断并执行恢复或重启。 |
停止不是“忽略返回值的清理调用”。特别是 DrainTimedOut 与 Quarantined 不能报告为正常停止,也不能继续向该内核开放新作用域。
观测与运维
通过 RuntimeOptions 提供 ObservationOptions 和 ImmutableArray<IObservationSink>。内核将观测异步分派到有界队列,并由 ObservationOptions 控制容量、溢出方式、属性上限和排空期限。
生产接入应做到:
- 为每个
IObservationSink.TryWrite实现无阻塞、快速失败或受控排队语义,避免观测接收器阻塞核心状态转换。 - 将所有
ReconciliationResult.Observation、ScopeOpenResult.Observation和RuntimeStopResult.Observation与业务请求、Catalog Revision 和宿主实例关联。 - 把
RuntimeReason.Code作为稳定的自动化分类字段,把参数作为诊断上下文;不要通过解析异常文本决定恢复动作。 - 为
Rejected、RestartRequested、DrainTimedOut和Quarantined建立明确的告警、重试、重启或人工介入策略。
生产接入清单
- 组合根直接引用
Sparkdo.Runtime.Generators,声明SparkdoRuntimeCompositionRequired=true,并消费生成的RuntimeCompositionTable.Instance。 - 启动前创建
CatalogInputs,并检查CatalogCreationResult;不要将未经验证的 JSON、环境变量或服务容器对象直接传给能力。 - 需要宿主对象时,以
HostBindingSnapshot传入,并让每次更新带有新的 Revision 和 Source。 - 所有重协调、打开作用域和停止调用都处理结构化结果,不把异常作为唯一失败信号。
- 每个业务请求都在最小作用域内创建并释放
SnapshotScope与Lease<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 | 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.Contracts (>= 0.0.1-preview.2)
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 |