Real‑time Data Synchronization with .NET 8, Azure Cosmos DB Change Feed, and SignalR

Mahmut Sarıkaya 4 dk okuma 6 Görüntülenme 0
Real‑time Data Synchronization with .NET 8, Azure Cosmos DB Change Feed, and SignalR

Ever wondered how a cloud‑native application can push database changes to every connected client instantly, without polling?

Understanding the Change Feed in Azure Cosmos DB

Azure Cosmos DB emits a chronological stream of inserts, updates, and deletes through its Change Feed. The service guarantees at‑least‑once delivery and retains feed items for up to five days, which is enough for most real‑time scenarios. In Q4 2023 Microsoft reported that more than 30 % of new Cosmos DB workloads leverage the Change Feed for event‑driven architectures, highlighting its maturity.

Setting Up a .NET 8 Project for Real‑Time Sync

Start with the .NET 8 SDK (minimum version 8.0.100). Create a Web API project, add the SignalR and Azure Cosmos packages, and register the required services. The following snippet shows a minimal Program.cs that configures SignalR, a singleton CosmosClient, and a custom ChangeFeedProcessorService responsible for reading the feed.

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Azure.Cosmos;
using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSignalR();
builder.Services.AddSingleton<CosmosClient>(sp =>
    new CosmosClient("<your-endpoint>", "<your-key>"));
builder.Services.AddSingleton<ChangeFeedProcessorService>();
var app = builder.Build();
app.MapHub<SyncHub>("/syncHub");
app.Run();

Replace <your-endpoint> and <your-key> with the values from the Azure portal. The project compiles with dotnet build and runs on any OS that supports .NET 8.

Implementing a SignalR Hub

The hub is the thin layer that forwards change‑feed payloads to connected browsers. Keep the hub stateless; SignalR handles connection groups and scaling automatically when deployed to Azure App Service or Azure Kubernetes Service.

using Microsoft.AspNetCore.SignalR;

public class SyncHub : Hub
{
    public async Task BroadcastChange(string payload)
    {
        await Clients.All.SendAsync("ReceiveChange", payload);
    }
}

Wiring Change Feed to SignalR

The core of the solution lives in a background service that registers a ChangeFeedProcessor. For each batch, deserialize the document, optionally filter by container, and invoke the hub method via IHubContext<SyncHub>. The example below processes up to 100 items per poll and acknowledges progress using the lease container.

using Microsoft.Azure.Cosmos;
using Microsoft.AspNetCore.SignalR;
using System.Text.Json;

public class ChangeFeedProcessorService : IHostedService
{
    private readonly CosmosClient _client;
    private readonly IHubContext<SyncHub> _hubContext;
    private ChangeFeedProcessor _processor;

    public ChangeFeedProcessorService(CosmosClient client, IHubContext<SyncHub> hubContext)
    {
        _client = client;
        _hubContext = hubContext;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        var container = _client.GetContainer("myDatabase", "myContainer");
        var leaseContainer = _client.GetContainer("myDatabase", "leaseContainer");

        _processor = container.GetChangeFeedProcessorBuilder<dynamic>("syncProcessor", async (IReadOnlyCollection<dynamic> changes, CancellationToken ct) =>
        {
            foreach (var doc in changes)
            {
                var json = JsonSerializer.Serialize(doc);
                await _hubContext.Clients.All.SendAsync("ReceiveChange", json, ct);
            }
        })
        .WithInstanceName("instance-1")
        .WithLeaseContainer(leaseContainer)
        .WithMaxItems(100)
        .Build();

        await _processor.StartAsync();
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        if (_processor != null)
        {
            await _processor.StopAsync();
        }
    }
}

Deploy the service with dotnet publish and configure the Azure App Service to run the compiled DLL. The lease container ensures exactly‑once processing across multiple instances.

Client‑Side Subscription with SignalR

On the browser side, a lightweight JavaScript module opens a WebSocket connection to /syncHub. Whenever the server pushes a change, the callback updates the UI—e.g., inserting a new row into a table without a full page refresh.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/syncHub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

connection.on("ReceiveChange", data => {
    console.log("Change received:", data);
    // Example: append a row to a table
    const obj = JSON.parse(data);
    const row = document.createElement('tr');
    row.innerHTML = `<td>${obj.id}</td><td>${obj.status}</td>`;
    document.querySelector('#dataTable tbody').appendChild(row);
});

connection.start().catch(err => console.error(err));

Because SignalR falls back to long‑polling when WebSockets are unavailable, the same code works in older corporate networks, guaranteeing delivery.

Performance Tips and Common Pitfalls

1. **Batch size matters** – Setting WithMaxItems too high can increase latency; a sweet spot for most workloads is 50‑200 items per batch. 2. **Lease container throughput** – Allocate at least 400 RU/s for the lease container when you expect 1 000 changes per second; otherwise the processor may stall. 3. **Idempotency** – Since the Change Feed is at‑least‑once, design your hub method to handle duplicate payloads, for example by checking a GUID stored in the client state. 4. **Scaling** – Deploy multiple instances of the .NET service; each will share the same lease container and automatically balance the feed partitions.

Conclusion

By combining Azure Cosmos DB’s Change Feed with .NET 8’s robust hosting model and SignalR’s real‑time push capabilities, developers can build truly reactive applications that scale from a handful of users to millions. The approach eliminates polling, reduces latency to sub‑second levels, and leverages Azure’s managed services for reliability.

Sources

  • Microsoft Azure Cosmos DB documentation – Change Feed
  • Microsoft ASP.NET Core SignalR official guide
  • Azure Architecture Center – Real‑time analytics patterns

Author: Mahmut Sarıkaya — sarikayadev.com

Etiketler: #.net 8 #azure cosmos db #change feed #signalr #real-time sync
Paylaş:
M

Yazar

Mahmut Sarıkaya

yazılım Geliştirici

Yorumlar

Henüz yorum yok. İlk yorumu siz yapın!

Yorum Bırakın

8 + 7 =