In enterprise collaboration and instant messaging systems, the Chat Subsystem balances high-throughput real-time streaming with strict delivery guarantees:
- Multi-Node Backplane Routing: User A connects to Web Node 1 while User B connects to Node 2; Node 1 must route outbound messages to Node 2 in sub-milliseconds;
- Offline Reconnection Gaps: Mobile clients reconnecting after network dropouts must sync unread messages via sequence numbers without message loss;
- Channel Access Security: Callers must be prevented from eavesdropping on private channels by spoofing channel identifiers.
BitzOrcas.Modern Chat Module implements “WebSocket Gateways + Redis Pub/Sub Backplane + Monotonic Sequence Persistence”:
Real-Time Chat & Broadcast Topology
Step 1: Monotonic Sequence Entity ChatMessage
using BitzOrcas.Domain.Entities;using BitzOrcas.Persistence.Metadata;
namespace BitzOrcas.Chat.Domain;
// 1. Table mapping and composite unique channel sequence index[BitzTable("SysChatMessage", IsTenant = true, IsSoftDelete = false, Description = "Chat Message Stream")][BitzIndex("IX_SysChatMessage_Channel_Seq", nameof(ChannelId), nameof(SequenceNo), IsUnique = true)]public sealed class ChatMessage : Entity<string>{ [BitzColumn(Length = 64, IsRequired = true)] public string ChannelId { get; set; } = string.Empty;
[BitzColumn(Length = 64, IsRequired = true)] public string SenderUserId { get; set; } = string.Empty;
// 2. Monotonically increasing sequence number (1, 2, 3... for offline sync) [BitzColumn(IsRequired = true)] public long SequenceNo { get; set; }
[BitzColumn(Length = 4000, IsRequired = true)] public string Content { get; set; } = string.Empty;
[BitzColumn(IsRequired = true)] public DateTimeOffset SentAt { get; set; }}Step 2: Send Message Command Slice & Cluster Broadcast
using BitzOrcas.Application.Abstractions.Realtime;using BitzOrcas.Domain.Results;using BitzOrcas.Chat.Domain;
public sealed class SendChatMessageCommandHandler( IChatMessageRepository messageRepo, IRealtimePublisher realtimePublisher, IAppClock clock){ public async ValueTask<Result> Handle(SendChatMessageCommand command, CancellationToken ct) { // 1. Acquire next sequence number and persist message var nextSeq = await messageRepo.GetNextSequenceNoAsync(command.ChannelId, ct); var msg = new ChatMessage { ChannelId = command.ChannelId, SenderUserId = command.SenderUserId, SequenceNo = nextSeq, Content = command.Content, SentAt = clock.UtcNow };
await messageRepo.SaveAsync(msg, ct);
// 2. Broadcast across cluster via Redis Backplane await realtimePublisher.PublishToChannelAsync( channel: $"chat:{command.ChannelId}", payload: new ChatMessageBroadcastDto(msg.Id, msg.SenderUserId, msg.Content, msg.SequenceNo), ct);
return Result.Success(); }}Summary
The Chat Module powers seamless enterprise collaboration:
- Monotonic Sequence Sync: Enables gapless recovery upon mobile reconnection;
- Distributed Backplane: Linear horizontal cluster scaling for thousands of concurrent sockets;
- Tenant Channel Scoping: Channels are strictly partitioned by tenant namespaces.