CasCap.Common.Services
5.2.0
Prefix Reserved
dotnet add package CasCap.Common.Services --version 5.2.0
NuGet\Install-Package CasCap.Common.Services -Version 5.2.0
<PackageReference Include="CasCap.Common.Services" Version="5.2.0" />
<PackageVersion Include="CasCap.Common.Services" Version="5.2.0" />
<PackageReference Include="CasCap.Common.Services" />
paket add CasCap.Common.Services --version 5.2.0
#r "nuget: CasCap.Common.Services, 5.2.0"
#:package CasCap.Common.Services@5.2.0
#addin nuget:?package=CasCap.Common.Services&version=5.2.0
#tool nuget:?package=CasCap.Common.Services&version=5.2.0
CasCap.Common.Services
Run selected .NET background features by name, observe their lifecycle and expose assembly-backed application metadata.
Installation
dotnet add package CasCap.Common.Services
Target frameworks: net10.0, net11.0
Usage
Register implementations as
IBgFeature,
then supply the enabled names to the launcher:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CasCap.Common.Abstractions;
using CasCap.Common.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSingleton<IBgFeature, WorkerFeature>();
builder.Services.AddApplicationHostLifecycle(builder.Configuration);
builder.Services.AddFeatureFlagService(
new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Worker" });
using var host = builder.Build();
await host.RunAsync();
return host.Services.GetApplicationExitCode();
public sealed class WorkerFeature(ILogger<WorkerFeature> logger) : IBgFeature
{
public string FeatureName => "Worker";
public async Task ExecuteAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug("{ClassName} poll completed", nameof(WorkerFeature));
await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
}
}
}
Feature matching is case-insensitive. A feature named IBgFeature.AlwaysEnabled ("All") runs
regardless of the selected set. Registration supplies IOptions<FeatureFlagConfig>; it does not
automatically read an EnabledFeatures JSON section.
AddApplicationHostLifecycle binds CasCap:HostLifecycleConfig, configures
HostOptions.ShutdownTimeout, and registers ApplicationExitState:
{
"CasCap": {
"HostLifecycleConfig": {
"ShutdownTimeoutMs": 30000
}
}
}
Set the Kubernetes terminationGracePeriodSeconds longer than this timeout, including any
PreStop duration and a safety margin.
UTC Cron Scheduling
CoalescingScheduleRunner in CasCap.Common.Services accepts a parsed Cronos
expression, an injected TimeProvider, an awaited callback and a cancellation token.
Five-field expressions use minute precision; seconds require explicit CronFormat.IncludeSeconds.
await CoalescingScheduleRunner.RunAsync(
Cronos.CronExpression.Parse("0 * * * *"),
TimeProvider.System,
async (scheduledForUtc, token) => await RunJobAsync(scheduledForUtc, token),
stoppingToken);
Occurrences are strictly after the cursor and use UTC. Each schedule runs sequentially; after
completion, missed occurrences are coalesced rather than replayed. Startup/manual execution,
distributed ownership, durable requests, retries and idempotency belong to the consumer.
Cancellation stops pending delays and is passed into callbacks; callback failures propagate.
RunWithTimeoutAsync cancels a cooperative operation and awaits its cleanup before reporting a
timeout. It does not forcibly abandon work that ignores cancellation.
Feature Supervision Activity
- No matching features is a startup failure.
- A child may finish while siblings continue. Faults from enabled children propagate to the host.
- If all children finish before cancellation, the launcher reports an unexpected lifecycle failure.
- A finite job must request
IHostApplicationLifetime.StopApplication()before returning. - Host cancellation cancels and awaits outstanding features, including their cleanup.
- A child fault requests host shutdown immediately, then cancels and awaits its siblings before propagating the failure.
- A child fault marks
ApplicationExitStateas failed before requesting shutdown. On .NET 10, the process entry point returnsGetApplicationExitCode()afterRunAsyncto report a nonzero result. - On .NET 11 with
BackgroundServiceExceptionBehavior.StopHost,Host.StopAsyncandRunAsyncrethrow background failures after cleanup. Preserve that failure at the process boundary rather than suppressing it; the exit state remains available for custom exception-handling entry points. AddFeatureFlagServiceregisters the exit state automatically. CallAddApplicationExitState()directly in hosts that also need to report startup or non-feature outcomes through the same process boundary.- A directly registered
BackgroundServiceoutsideFeatureFlagBgServicemust mark the same state before requesting fatal shutdown, or use another supervisor that does. - Align host and container termination budgets for uncooperative cleanup.
flowchart TD
HOST["Host startup"] --> MATCH["Match registered features against enabled names"]
MATCH --> RUN["Run matching features and All features"]
RUN --> WATCH["Observe child tasks"]
WATCH -->|Child finishes, siblings remain| WATCH
WATCH -->|Child faults or all finish without stopping| FAIL["Request host shutdown, cancel and await siblings, propagate failure"]
WATCH -->|Host cancellation or requested stop| STOP["Cancel and await children, then clean shutdown"]
Configuration Examples
Feature Execution Only
The registration in Usage enables the selected features without periodic metadata logging.
Feature Execution with Metadata
Pass addApplicationMetadataService: true to register ApplicationMetadataBgService and
ApplicationMetadata. The latter reads version, source revision and build context from assembly
attributes, not live Git state.
builder.Services.AddFeatureFlagService(enabledFeatures, addApplicationMetadataService: true);
The optional metadata service binds ApplicationMetadataConfig. It writes one Information line
with the repository, version, branch and commit at startup and then every LogInterval, which
defaults to fifteen minutes and must be positive:
{
"ApplicationMetadataConfig": {
"LogInterval": "01:00:00"
}
}
| 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
- CasCap.Common.Abstractions (>= 5.2.0)
- CasCap.Common.Extensions (>= 5.2.0)
- Cronos (>= 0.13.0)
- Microsoft.Extensions.Hosting (>= 10.0.14)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.14)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.14)
-
net11.0
- CasCap.Common.Abstractions (>= 5.2.0)
- CasCap.Common.Extensions (>= 5.2.0)
- Cronos (>= 0.13.0)
- Microsoft.Extensions.Hosting (>= 11.0.0)
- Microsoft.Extensions.Options.DataAnnotations (>= 11.0.0)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on CasCap.Common.Services:
| Package | Downloads |
|---|---|
|
CasCap.Api.SignalCli
Typed .NET client for the signal-cli REST API with REST polling and JSON-RPC WebSocket transports, health checks, and INotifier integration. |
|
|
CasCap.Common.OpenTelemetry
Reusable OpenTelemetry configuration with standard metrics, traces, and log exporters. |
|
|
CasCap.Api.Voice
Provider-neutral speech-to-text and text-to-speech components for .NET applications. |
|
|
CasCap.Common.Hosting.AspNetCore
ASP.NET Core hosting defaults for feature-gated controllers, Serilog, and OpenTelemetry metrics, traces, and logs. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.2.0 | 107 | 11/14/2026 |
| 5.1.0 | 426 | 11/5/2026 |
| 5.0.0 | 251 | 11/1/2026 |
| 4.17.0 | 343 | 10/24/2026 |
| 4.16.0 | 296 | 10/21/2026 |
| 4.15.0 | 161 | 10/6/2026 |
| 4.14.4 | 270 | 10/4/2026 |
| 4.14.3 | 168 | 9/28/2026 |
| 4.14.2 | 306 | 9/25/2026 |
| 4.14.1 | 369 | 9/23/2026 |
| 4.14.0 | 352 | 9/19/2026 |
| 4.13.0 | 151 | 9/15/2026 |
| 4.12.8 | 183 | 9/10/2026 |
| 4.12.7 | 152 | 9/4/2026 |
| 4.12.6 | 137 | 9/1/2026 |
| 4.12.5 | 149 | 8/20/2026 |
| 4.12.4 | 160 | 8/18/2026 |
| 4.12.3 | 165 | 7/15/2026 |
| 4.12.2 | 179 | 6/26/2026 |
| 4.12.1 | 172 | 6/14/2026 |