Scry.Server.Delta 0.1.0-beta.5

This is a prerelease version of Scry.Server.Delta.
dotnet add package Scry.Server.Delta --version 0.1.0-beta.5
                    
NuGet\Install-Package Scry.Server.Delta -Version 0.1.0-beta.5
                    
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="Scry.Server.Delta" Version="0.1.0-beta.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Scry.Server.Delta" Version="0.1.0-beta.5" />
                    
Directory.Packages.props
<PackageReference Include="Scry.Server.Delta" />
                    
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 Scry.Server.Delta --version 0.1.0-beta.5
                    
#r "nuget: Scry.Server.Delta, 0.1.0-beta.5"
                    
#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 Scry.Server.Delta@0.1.0-beta.5
                    
#: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=Scry.Server.Delta&version=0.1.0-beta.5&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Scry.Server.Delta&version=0.1.0-beta.5&prerelease
                    
Install as a Cake Tool

Scry.Server.Delta

Conditional requests for Scry, backed by Delta.

A query asked as a URL can be answered 304 Not Modified when nothing has changed since the caller last asked. The hard part of that is proving it, and Delta supplies the proof: one cheap read of the database's own change marker, rather than executing the query again.

builder.Services.AddScry<SampleContext>(
    _ =>
    {
        _.UseDeltaFreshness<SampleContext>();
    });

That is the whole wiring. Everything above it — the ETag, the If-None-Match comparison, the 304, the cache directives — is Scry.Server's, and works with any freshness source through ScryOptions.QueryFreshness. This package supplies the one most apps want.

<a id='snippet-useDeltaFreshness'></a>

/// <summary>
/// Answers a repeated query with <c>304 Not Modified</c> while nothing has been written, by
/// reading <typeparamref name="TContext"/>'s own change marker through Delta's
/// <c>GetLastTimeStamp</c> — the transaction log's end position on SQL Server,
/// <c>pg_last_committed_xact</c> on PostgreSQL.
/// </summary>
/// <remarks>
/// <para>
/// One read of a marker the database already maintains, in place of executing the query and
/// writing its rows. That trade pays in almost any read-heavy app and does not pay where the data
/// changes on every request, since the marker moves for a write to anything at all.
/// </para>
/// <para>
/// The marker trails a commit rather than moving with it — a couple of hundred milliseconds on
/// SQL Server — so inside that window a client that has just written can be told its copy is
/// still current. A client that needs read-after-write sends <c>Cache-Control: no-cache</c>,
/// which skips the comparison and re-executes.
/// </para>
/// <para>
/// Where any source carries a row or attachment policy, its rows depend on who asked, and
/// <see cref="ScryOptions.CacheScope"/> has to say what a cached response belongs to.
/// <c>MapScry</c> refuses to start otherwise.
/// </para>
/// </remarks>
public static ScryOptions UseDeltaFreshness<TContext>(this ScryOptions options)
    where TContext : DbContext
{
    options.QueryFreshness = async (context, cancel) =>
    {
        var data = context.RequestServices.GetRequiredService<TContext>();
        var timeStamp = await data.GetLastTimeStamp(cancel);

        // A marker that says nothing identifies nothing, so the request is answered in full rather
        // than with an ETag that has a hole where its freshness should be.
        return timeStamp.Length == 0 ? null : timeStamp;
    };

    return options;
}

<sup><a href='/src/Scry.Server.Delta/ScryDeltaExtensions.cs#L9-L49' title='Snippet source file'>snippet source</a> | <a href='#snippet-useDeltaFreshness' title='Start of snippet'>anchor</a></sup>

Where a source carries a row policy, its rows depend on who asked, so ScryOptions.CacheScope has to say what a cached response belongs to — MapScry refuses to start otherwise.

Docs: Caching and 304 Not Modified

Product 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. 
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
0.1.0-beta.5 34 8/30/2026