Momentum.Runtime
0.9.0
dotnet add package Momentum.Runtime --version 0.9.0
NuGet\Install-Package Momentum.Runtime -Version 0.9.0
<PackageReference Include="Momentum.Runtime" Version="0.9.0" />
<PackageVersion Include="Momentum.Runtime" Version="0.9.0" />
<PackageReference Include="Momentum.Runtime" />
paket add Momentum.Runtime --version 0.9.0
#r "nuget: Momentum.Runtime, 0.9.0"
#:package Momentum.Runtime@0.9.0
#addin nuget:?package=Momentum.Runtime&version=0.9.0
#tool nuget:?package=Momentum.Runtime&version=0.9.0
Momentum.Runtime
The hosting runtime of Momentum, an event-driven, multi-tenant workflow framework for .NET:
AddMomentumRuntime(...)— one call wires the internal event bus, per-tenant routing with retries and dead-lettering, execution recording to PostgreSQL, tenant provisioning/suspend/decommission, Quartz cron hosting, and the DLQ replay pollerRegisterAllStepsAsync()— idempotently maps every generated API step as a minimal-API endpoint and schedules cron steps- Options validated at startup (
MomentumOptions), configurable via delegate orIConfiguration - Production startup rejects the built-in non-persisting store unless
AllowNoOpInfrastructureInProductionis explicitly enabled - Custom
InfrastructureStoreBaseimplementations must override every store facet in Production unless explicitly allowed - Production rejects missing external transport for generated external subscribers/publishers unless explicitly allowed
Install
dotnet add package Momentum.Abstractions
dotnet add package Momentum.SourceGenerator
dotnet add package Momentum.Runtime
Momentum.Runtime targets .NET 10. Momentum.SourceGenerator must be referenced by
each project that declares steps.
Application startup
using Momentum.Runtime.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMomentumRuntime(options =>
{
options.InfrastructureConnectionString = builder.Configuration
.GetConnectionString("Infrastructure")!;
options.TenantConnectionTemplate = builder.Configuration
.GetConnectionString("TenantTemplate")!;
});
var app = builder.Build();
await app.RegisterAllStepsAsync();
app.Run();
Example configuration:
{
"ConnectionStrings": {
"Infrastructure": "Host=postgres;Database=momentum",
"TenantTemplate": "Host=postgres;Database={database_name}"
}
}
AddMomentumRuntime registers internal event routing, execution persistence, tenant
routing, retry/dead-letter handling, and Quartz scheduling. Do not separately register
another Quartz hosted service. RegisterAllStepsAsync discovers generated step
registrations, maps API endpoints, and schedules cron steps.
Production startup rejects the built-in non-persisting store and missing external transport when generated external subscribers or publishers exist, unless the relevant explicit opt-out is configured.
Durable scheduled internal events
Schedule an internal event at an absolute DateTimeOffset or after a TimeSpan.
Declare its type in Config.Emits and bind the tenant business transaction so the
business write and deadline commit together:
using Momentum;
using Momentum.Runtime.Messaging;
using (MomentumSchedulingTransaction.Use(tenantId, transaction))
{
// Perform the business write using this same PostgreSQL transaction.
await bus.ScheduleAsync(deadlineEvent, TimeSpan.FromSeconds(60), cancellationToken);
await transaction.CommitAsync(cancellationToken);
}
Use a connection from ITenantConnectionProvider. Infrastructure persistence and
TenantConnectionTemplate must be configured. The transaction belongs to the
application; an unbound scheduling call fails. The tenant outbox is created on
first use, or can be provisioned through migrations using
MomentumSchedulingSchema.TenantOutboxSql when runtime credentials cannot create
tables.
Committed deadlines survive restart and transfer into the existing durable relay
when due. Suspended tenants hold their schedules until resume. Delivery uses the
normal subscriptions, retries, and dead letters; handlers must be idempotent.
MomentumMessageContext.ScheduledMessageId remains stable through retry and
replay. The source workflow can finish without cancelling its deadlines.
IScheduledMessageStore.GetPendingScheduledMessagesAsync exposes tenant-scoped
pending schedules for back-office integration after transfer from the tenant
outbox. The caller must authorize tenant access. ScheduledMessagePollInterval
defaults to one second and ScheduledMessageBatchSize to 100; outages and backlog
can delay delivery beyond its earliest eligible time.
License
Momentum is free for qualifying non-commercial open-source projects. Commercial use requires a separate written license agreement. The complete terms are included in the package.
Runtime metrics
The runtime emits exporter-independent metrics through the Momentum.Runtime
System.Diagnostics.Metrics meter. Install Momentum.OpenTelemetry and call
AddMomentumOpenTelemetry to collect them over OTLP. That package documents the
stable instrument contract, dimensions, and cardinality budget.
Trace propagation
Momentum carries W3C traceparent/tracestate explicitly across internal channels,
retry entries, the PostgreSQL relay and event outbox, and Wolverine transport headers.
Fan-out handlers are sibling consumer spans of the publishing span. Crash outbox
re-emission continues the stored context; delayed dead-letter replay starts a new
trace with a link to the original failure. Missing or malformed stored context never
blocks delivery or replay, and workflow correlation is independent of trace sampling.
Span contract
| Operation | Span name | Kind |
|---|---|---|
| API step | momentum.step.api |
Internal (child of ASP.NET server span) |
| Internal event step | momentum.step.internal |
Consumer |
| External event step | momentum.step.external |
Internal (child of Wolverine consumer span) |
| Cron step | momentum.step.cron |
Internal |
| Event publication | momentum.event.publish |
Producer |
| Relay delivery | momentum.relay.consume |
Consumer |
| Outbox recovery | momentum.outbox.reemit |
Producer |
| Dead-letter replay | momentum.dead_letter.replay |
Producer, linked to the failure |
Step, delivery, retry, workflow, and tenant details are attributes rather than span
name components, keeping operation names low-cardinality. Failed StepResult values
set error status. Escaped exceptions record their CLR type but not messages, stack
traces, payloads, or application data.
| 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
- Dapper (>= 2.1.79)
- Momentum.Abstractions (>= 0.9.0)
- Npgsql (>= 9.0.5)
- Quartz (>= 3.19.1)
- Quartz.Extensions.Hosting (>= 3.19.1)
- WolverineFx (>= 5.40.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.