DbSignal.Extensions.Hosting 1.0.2

dotnet add package DbSignal.Extensions.Hosting --version 1.0.2
                    
NuGet\Install-Package DbSignal.Extensions.Hosting -Version 1.0.2
                    
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="DbSignal.Extensions.Hosting" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DbSignal.Extensions.Hosting" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="DbSignal.Extensions.Hosting" />
                    
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 DbSignal.Extensions.Hosting --version 1.0.2
                    
#r "nuget: DbSignal.Extensions.Hosting, 1.0.2"
                    
#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 DbSignal.Extensions.Hosting@1.0.2
                    
#: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=DbSignal.Extensions.Hosting&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=DbSignal.Extensions.Hosting&version=1.0.2
                    
Install as a Cake Tool

DbSignal.Extensions.Hosting

Register a feed and a handler. The library owns the loop.

builder.Services.AddDbSignal(o =>
{
    o.UseFeed(_ => SqlServerFeed.For(connectionString).Watch("dbo.Products").Build());
    o.RequireAtLeast(ChangeDetail.KeysChanged);
})
.AddHandler<ProductCacheInvalidator>();
public sealed class ProductCacheInvalidator : IChangeHandler
{
    public Task HandleAsync(ChangeBatch batch, CancellationToken ct)
    {
        foreach (var table in batch.Tables)
            foreach (var key in table.Keys)
                cache.Evict(key.Values[0]);

        return Task.CompletedTask;
    }
}

That is the whole integration. No BackgroundService to write, no retry loop, no checkpoint bookkeeping.

What it does for you

  • Runs the feed for the lifetime of the application, as a hosted service.
  • Dispatches each batch to every registered handler, resolved from a fresh DI scope — so a scoped DbContext behaves exactly as it does in a web request.
  • Saves the checkpoint after handlers succeed, never before. That ordering is what makes at-least-once true: a crash mid-handler replays the batch instead of skipping it.
  • Retries with exponential backoff when the feed faults, capped, so a database coming back up is not hit by every workstation at once.
  • Handles retention expiry — on ResyncRequiredException it logs a warning telling you to reload your cache, then resumes from now rather than silently delivering nothing.

The line worth writing

o.RequireAtLeast(ChangeDetail.KeysChanged);

Point that at SQLite, which can only report "something changed", and the application refuses to start with a message naming both tiers. Without it, a "patch the changed rows" app pointed at the wrong provider runs happily and quietly does a fraction of its job.

Provider-neutral on purpose

Configuration takes UseFeed(Func<IServiceProvider, IChangeFeed>) rather than UseSqlServer(connectionString). This package therefore references no database driver — adding a provider to your app never widens this package's dependency graph, and this package never dictates your driver version.

Handlers must be idempotent

Delivery is at-least-once. A crash between handling a batch and persisting its checkpoint replays that batch. One handler throwing does not stop its siblings from seeing the batch, and by default that batch is delivered again — with backoff, and with the checkpoint held where it is — until a handler accepts it. Set RetryFailedBatches = false if a poison batch blocking the stream would be worse than dropping it.

Retrying holds the stream at the failed batch rather than reading past it. It has to: a provider advances its own cursor as it yields, so the next batch off the feed covers only what happened afterwards. Reading on and then saving that later position would carry the checkpoint over changes no handler ever accepted, and no restart could reach them again.

Checkpoints are kept in memory unless you supply a store with UseCheckpointStore<T>(). Deliberately not a file by default: writing checkpoints somewhere you did not choose shows up months later as a stale resume nobody can explain.

Targets net8.0. MIT licensed. Source and full documentation.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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

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
1.0.2 115 8/27/2026
1.0.1 180 8/15/2026
1.0.0 103 8/7/2026
0.2.0 113 8/6/2026