Table of Contents

RuntimeReplicationConfig source

This page is part of the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at source.md, and llms.txt lists every page.

The source of the RuntimeReplicationConfig sample.

Program.cs

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Orleans.Hosting;
using Orleans.Lattice;
using Orleans.Lattice.Api.Replication;
using Orleans.Lattice.Replication;

// Runtime per-tree replication configuration sample.
//
// This sample hosts a single-silo Orleans cluster and drives replication
// enablement at RUNTIME through the control facade instead of the static
// LatticeReplicationOptions.ReplicatedTrees options map. The facade writes to the replicated
// sys-replication-config CRDT system tree; every cluster that enrolls that
// tree converges on the same per-tree enabled/mode decision.
//
// The flow is scripted and non-interactive: it enables a tree, reports the
// live config, demonstrates that an in-place mode change is rejected, then
// disables the tree and exits. There is no auth stack registered, so the
// default allow-all access gate authorizes every facade call; a production
// deployment would register Orleans.Lattice.Auth and author through the
// fail-closed API access gate.

const string TreeName = "orders";

using var host = Host.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
    {
        logging.ClearProviders();
        logging.SetMinimumLevel(LogLevel.None);
    })
    .UseOrleans(silo =>
    {
        silo.UseLocalhostClustering(serviceId: "runtime-replication-config-sample", clusterId: "site-a");
        silo.AddMemoryGrainStorageAsDefault();
        silo.UseInMemoryReminderService();
        silo.AddLattice((services, name) => services.AddMemoryGrainStorage(name));

        // Enable the replication engine for this cluster. No peers are declared:
        // this single-silo sample exercises the local authoring and reporting
        // path, not cross-cluster shipping. ClusterId stamps this cluster's
        // origin and satisfies the runtime preconditions for enablement.
        // enableRuntimeConfig: true enrols the sys-replication-config tree so
        // runtime enablement decisions are themselves a replicated CRDT - the one
        // static enrolment the runtime-config model requires; every other tree is
        // enabled dynamically through the facade below.
        silo.AddLatticeReplication(
            opts =>
            {
                opts.ClusterId = "site-a";
            },
            enableRuntimeConfig: true);

        // Register the runtime replication control API. This binds
        // ILatticeReplicationControl over the config authority.
        silo.AddLatticeReplicationApi();
    })
    .Build();

Console.Write("Silo starting...");
await host.StartAsync();
Console.WriteLine(" ready.");
Console.WriteLine();

var control = host.Services.GetRequiredService<ILatticeReplicationControl>();

// 1. Enable replication for the "orders" tree under an OrSet merge mode. The
//    mode is fixed at enable-time and cannot be changed in place afterwards.
Console.WriteLine($"Enabling replication for tree '{TreeName}' under {LatticeMergeMode.OrSet}...");
var enabled = await control.EnableReplicationAsync(TreeName, LatticeMergeMode.OrSet);
Console.WriteLine(
    $"  enabled: tree={enabled.TreeId} mode={enabled.Mode} " +
    $"alreadyEnabled={enabled.AlreadyEnabled} bootstrapRequested={enabled.BootstrapRequested}");
Console.WriteLine();

// 2. Report the live per-tree configuration as converged in the config tree.
await PrintConfigAsync(control);

// 3. An in-place mode change is rejected by design. The sanctioned path to
//    change a tree's merge mode is disable-then-re-enable, which re-bootstraps.
Console.WriteLine($"Attempting an in-place mode change to {LatticeMergeMode.LwwRegister} (expected to be rejected)...");
try
{
    await control.EnableReplicationAsync(TreeName, LatticeMergeMode.LwwRegister);
    Console.WriteLine("  unexpected: the mode change was NOT rejected.");
}
catch (LatticeReplicationModeChangeRejectedException ex)
{
    Console.WriteLine($"  rejected as expected: {ex.Message}");
}
Console.WriteLine();

// 4. Disable replication for the tree. This removes the tree's resolved runtime
//    mode (its fixed merge mode is kept) and never purges data already
//    replicated to peers. It does not tear down a shipper that is already
//    running: one that keeps shipping has its entries dropped (and the batch
//    acknowledged) by peers that resolve no mode.
Console.WriteLine($"Disabling replication for tree '{TreeName}'...");
var disabled = await control.DisableReplicationAsync(TreeName);
Console.WriteLine($"  disabled: tree={disabled.TreeId} alreadyDisabled={disabled.AlreadyDisabled}");
Console.WriteLine();

// 5. Report the config again to show the tree is now disabled.
await PrintConfigAsync(control);

Console.WriteLine("Sample complete. Stopping silo...");
await host.StopAsync();
Console.WriteLine("Done.");

static async Task PrintConfigAsync(ILatticeReplicationControl control)
{
    var report = await control.GetReplicationConfigAsync();
    Console.WriteLine($"Replication config ({report.Trees.Count} tree(s)):");
    foreach (var tree in report.Trees)
    {
        var mode = tree.Mode?.ToString() ?? "(none)";
        Console.WriteLine(
            $"  tree={tree.TreeId} enabled={tree.Enabled} mode={mode} ambiguous={tree.Ambiguous}");
    }

    Console.WriteLine();
}

RuntimeReplicationConfig.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <RootNamespace>Orleans.Lattice.Samples.RuntimeReplicationConfig</RootNamespace>
    <AssemblyName>Orleans.Lattice.Samples.RuntimeReplicationConfig</AssemblyName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.11" />
    <PackageReference Include="Microsoft.Orleans.Server" Version="10.2.2" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\..\src\lattice\Orleans.Lattice.csproj" />
    <ProjectReference Include="..\..\src\lattice.replication\Orleans.Lattice.Replication.csproj" />
    <ProjectReference Include="..\..\src\lattice.api.replication\Orleans.Lattice.Api.Replication.csproj" />
  </ItemGroup>

</Project>