Sparkdo.Scheduler.EntityFrameworkCore
3.0.0-preview.1
dotnet add package Sparkdo.Scheduler.EntityFrameworkCore --version 3.0.0-preview.1
NuGet\Install-Package Sparkdo.Scheduler.EntityFrameworkCore -Version 3.0.0-preview.1
<PackageReference Include="Sparkdo.Scheduler.EntityFrameworkCore" Version="3.0.0-preview.1" />
<PackageVersion Include="Sparkdo.Scheduler.EntityFrameworkCore" Version="3.0.0-preview.1" />
<PackageReference Include="Sparkdo.Scheduler.EntityFrameworkCore" />
paket add Sparkdo.Scheduler.EntityFrameworkCore --version 3.0.0-preview.1
#r "nuget: Sparkdo.Scheduler.EntityFrameworkCore, 3.0.0-preview.1"
#:package Sparkdo.Scheduler.EntityFrameworkCore@3.0.0-preview.1
#addin nuget:?package=Sparkdo.Scheduler.EntityFrameworkCore&version=3.0.0-preview.1&prerelease
#tool nuget:?package=Sparkdo.Scheduler.EntityFrameworkCore&version=3.0.0-preview.1&prerelease
Sparkdo.Scheduler.EntityFrameworkCore
Sparkdo Scheduler 的通用 Entity Framework Core 持久化 provider。实现全部六个
异步 store 端口(IExecutionQueue / IScheduleStore / IExecutorStore /
IHistoryStore / IShardStore / ISchedulerStoreDiagnostics),并通过
Sparkdo.Scheduler.Testing 的 provider conformance 认证到
MultiNodePersistent 级别(含 persistent-recovery 与 transaction 探针;多节点证据
来自 SQLite 共享文件的 conformance,DR 仍不承诺)。
接入
builder.Services.AddScheduler();
builder.Services.AddSchedulerEntityFrameworkCore(
configureDbContext: (_, options) => options.UseNpgsql(connectionString));
// 建表:可重复调用——以 metadata 表为哨兵判本模型这一套表在不在,缺则补建整套 DDL(含 schema)。
// 使用 EF 迁移的宿主改为应用迁移。
await builder.Services.BuildServiceProvider()
.GetRequiredService<IDbContextFactory<SchedulerStoreDbContext>>()
.EnsureSchedulerStoreSchemaAsync();
- 建表不依赖「整库无表」:同一个库里放多套前缀或挂在多个 schema 下(多租户、
或同一测试工程的 net10.0 / net11.0 并行实例)都能各自建出自己的表。判据是
metadata 表能否读到(哨兵只看这一张:它被人删剩半套而这张还在时不会被补齐),
库为空或库还不存在时走
EnsureCreated,顺带把库/文件本身建出来。 两个实例同时首建同一套表不安全——后到的会在建表时收到 provider 的 「表已存在」错误,所以多实例部署要么固定由一个实例初始化,要么改用 EF 迁移。 - 调用时机无关:六个 store 端口以 Replace 语义覆盖
AddScheduler的 in-memory 默认注册(在AddScheduler之前调用同样生效)。 - 数据库 provider 由宿主在
configureDbContext里选择(Npgsql / Sqlite / SqlServer 等任何关系 provider);本包只拥有 Scheduler 自己的表模型。 - 表前缀(默认
Scheduler)、可选 schema 与 claim 扫描批量 (ClaimBatchSize,默认 200)通过SchedulerEntityFrameworkCoreOptions配置。
设计要点
- 高性能:候选阶段瘦投影(不含 payload blob,批量可配);claim 的 placement /
并发 / lease / fencing 判定在
Serializable隔离的事务单元内原子完成(Sqlite 上 为 BEGIN IMMEDIATE 全库写串行,属正确性优先的取舍;换 Npgsql 后可结合乐观 Revision 进一步放宽);并发冲突或唯一键冲突时整个单元重试(全新事务,从起点重跑)。 - fencing token:以执行行为单位单调递增,跨状态转换保留,stale lease 恢复后的下一次 claim 拿到更大 token。
- 值转换:
DateTimeOffset一律 UTC ticks(long),枚举 int,结构化字段 (headers / trace / 策略)走 System.Text.Json 源生成 metadata,无运行时反射序列化。 - DbContext 池化:端口按操作从
IDbContextFactory取池化 context,线程安全 且避免长事务持有连接;表前缀 / schema 经IDbContextOptionsExtension注入, 与池化共存。 - 启动校验:
SchedulerStoreStartupValidator(IHostedService)核对 schema 版本, 表不可达或版本不匹配时 fail closed 拒绝启动,并给出可操作的错误信息。 - 诊断:快照附带有界指标(schema 版本、活跃租约数);完整快照为全量语义 (与 in-memory 一致),大规模部署请以指标为准。
- 开放扩展点:
ISchedulerStoreInterceptor(提交前/提交后)允许宿主介入每个 持久化单元(审计、多租户路由、测试故障注入);ConfigureSchedulerStore模型扩展允许把 Scheduler 实体映射进宿主自有 DbContext。
多 provider 证据
conformance 出证默认在 SQLite 上运行;NpgsqlSchedulerStoreConformanceTests
在设置 SPARKDO_SCHEDULER_NPGSQL 环境变量(指向可用 PostgreSQL 连接串)时
运行同一套 conformance(独立 schema,运行后清理),实现 provider 无关性的
运行期证据闭环。实现层面无任何原生 SQL 或 provider 专属片段。
租约时钟
LeaseClock 选项决定租约判定的时钟来源,默认 Caller(调用方传入 now,节点时钟
同步由运维保证)。LeaseClock=Store 时 lease 窗口锚定与过期判定以数据库引擎时钟为
权威(SQLite 即宿主机 UTC;Postgres 用 now()),每次 lease 操作多一次时钟读数,
调用方时钟偏斜无法偷走仍然存活的租约;启动校验会探测时钟读数,不支持的数据库
provider fail closed 拒绝启动。快照随附引擎读数,runtime 的时钟漂移审计据此度量。
能力声明
PersistentRecovery | Transactions | DistributedClaim | StoreClock | LeaseRenewal | FencingTokens | OccurrenceUniqueness | History | Sharding | QueryWatermark | HistoryCleanup。DistributedClaim 与 StoreClock 经多节点 conformance 出证
(ProviderConformanceReport.Combine 合并单 kit 与多节点证据),认证到
MultiNodePersistent;灾难恢复(DR)仍不承诺。声明 StoreClock 的场景要求宿主
cluster factory 按用例的 RequiredClusterFeatures 切到 LeaseClock=Store:本 provider
的 store 时钟即数据库引擎时钟(会自然前进),所以 store 时钟下真正过期租约的正向
回收与"偏斜调用方时钟偷不走活租约"的负向断言都能满足;只有负向证据的 provider 拿不到
StoreClock 证据。
AOT 说明
EF Core 模型构建与关系事务依赖动态代码,本包显式豁免 AOT/裁剪(csproj 注释); 宿主应用的其他部分不受影响。
| 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. net11.0 is compatible. |
-
net10.0
- Microsoft.EntityFrameworkCore (>= 10.0.8)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.8)
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Caching.Memory (>= 10.0.8)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.8)
- Microsoft.Extensions.DependencyInjection (>= 10.0.8)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.8)
- Microsoft.Extensions.FileProviders.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Logging (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Options (>= 10.0.8)
- Microsoft.Extensions.Primitives (>= 10.0.8)
- Sparkdo.Scheduler (>= 3.0.0-preview.1)
- Sparkdo.Scheduler.Abstractions (>= 3.0.0-preview.1)
-
net11.0
- Microsoft.EntityFrameworkCore (>= 10.0.8)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.8)
- Microsoft.Extensions.Caching.Memory (>= 10.0.8)
- Microsoft.Extensions.DependencyInjection (>= 10.0.8)
- Microsoft.Extensions.Logging (>= 10.0.8)
- Sparkdo.Scheduler (>= 3.0.0-preview.1)
- Sparkdo.Scheduler.Abstractions (>= 3.0.0-preview.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0-preview.1 | 60 | 10/30/2026 |