In this lesson, you will learn how to maintain data integrity in multi-user environments by implementing optimistic locking and conflict resolution for shared document editing.
When multiple users edit a document simultaneously via SignalR, the greatest challenge is ensuring that updates don't overwrite each other in a way that destroys data. Instead of locking the document and preventing others from working (pessimistic locking), we use optimistic locking.
The Concept
Every document version in your database or state store includes a Version number. When a client sends an update, they must include the version number they are basing their change on. If the current server version matches the client's version, the update is accepted and the version increments. If the version has already changed, a conflict has occurred, and the server rejects the request.
Implementation Pattern
Here is how you might structure this logic within a SignalR Hub method:
public async Task UpdateDocument(int documentId, string newContent, int clientVersion)
{
var document = await _repository.GetByIdAsync(documentId);
if (document.Version != clientVersion)
{
// Conflict detected! Notify the client to re-sync
await Clients.Caller.SendAsync("ConflictDetected", document.Content, document.Version);
return;
}
// Apply change and increment
document.Content = newContent;
document.Version++;
await _repository.UpdateAsync(document);
// Broadcast success
await Clients.Others.SendAsync("DocumentUpdated", newContent, document.Version);
}
Conflict Resolution
When a conflict occurs, the client must handle the ConflictDetected signal. The strategy here is usually "Rebase and Retry." The client updates its local state with the server's current version (which it just received in the signal) and then reapplies its local changes on top of that new state. In complex scenarios, you might implement a "three-way merge" or a Operational Transformation (OT) algorithm to resolve differences at the character level, but for standard document editing, the version-check pattern ensures you never lose a user’s atomic input.
Key Takeaway: Optimistic locking preserves document integrity by using version tracking to detect collisions, requiring clients to reconcile state whenever their local version becomes stale.