🐛 Fixes sync issue

This commit is contained in:
2025-09-23 14:58:25 +08:00
parent b785d0098b
commit fdd7bd3c9d

View File

@@ -65,24 +65,37 @@ public partial class ChatService(
logger.LogDebug($"Updated message {message.Id} with {embedsList.Count} link previews"); logger.LogDebug($"Updated message {message.Id} with {embedsList.Count} link previews");
// Create sync message for link preview update // Create and store sync message for link preview update
var syncMessage = dbMessage.Clone(); var syncMessage = new Message
syncMessage.Type = "messages.update.links"; {
syncMessage.UpdatedAt = dbMessage.UpdatedAt; Type = "messages.update.links",
ChatRoomId = dbMessage.ChatRoomId,
SenderId = dbMessage.SenderId,
Nonce = Guid.NewGuid().ToString(),
Meta = new Dictionary<string, object>
{
["original_message_id"] = dbMessage.Id,
["embeds"] = embedsList
},
CreatedAt = dbMessage.UpdatedAt,
UpdatedAt = dbMessage.UpdatedAt
};
dbContext.ChatMessages.Add(syncMessage);
await dbContext.SaveChangesAsync();
// Send sync message to clients // Send sync message to clients
syncMessage.Sender = dbMessage.Sender;
syncMessage.ChatRoom = dbMessage.ChatRoom;
using var syncScope = scopeFactory.CreateScope(); using var syncScope = scopeFactory.CreateScope();
var syncCrs = syncScope.ServiceProvider.GetRequiredService<ChatRoomService>(); var syncCrs = syncScope.ServiceProvider.GetRequiredService<ChatRoomService>();
var syncMembers = await syncCrs.ListRoomMembers(dbMessage.ChatRoomId); var syncMembers = await syncCrs.ListRoomMembers(dbMessage.ChatRoomId);
await SendWebSocketPacketToRoomMembersAsync(syncMessage, "messages.update.links", syncMembers, syncScope); await DeliverMessageAsync(
syncMessage,
// Also notify clients of the updated message via regular WebSocket syncMessage.Sender,
await newChat.DeliverMessageAsync( syncMessage.ChatRoom,
dbMessage,
dbMessage.Sender,
dbMessage.ChatRoom,
WebSocketPacketType.MessageUpdate,
notify: false notify: false
); );
} }
@@ -158,8 +171,12 @@ public partial class ChatService(
return message; return message;
} }
private async Task SendWebSocketPacketToRoomMembersAsync(Message message, string type, List<ChatMember> members, private async Task DeliverWebSocketMessage(
IServiceScope scope) Message message,
string type,
List<ChatMember> members,
IServiceScope scope
)
{ {
var scopedNty = scope.ServiceProvider.GetRequiredService<RingService.RingServiceClient>(); var scopedNty = scope.ServiceProvider.GetRequiredService<RingService.RingServiceClient>();
@@ -228,7 +245,7 @@ public partial class ChatService(
var members = await scopedCrs.ListRoomMembers(room.Id); var members = await scopedCrs.ListRoomMembers(room.Id);
await SendWebSocketPacketToRoomMembersAsync(message, type, members, scope); await DeliverWebSocketMessage(message, type, members, scope);
if (notify) if (notify)
{ {
@@ -603,18 +620,13 @@ public partial class ChatService(
var timestamp = Instant.FromUnixTimeMilliseconds(lastSyncTimestamp); var timestamp = Instant.FromUnixTimeMilliseconds(lastSyncTimestamp);
// Get all messages that have been modified since the last sync // Get all messages that have been modified since the last sync
var modifiedMessages = await db.ChatMessages var syncMessages = await db.ChatMessages
.IgnoreQueryFilters() .IgnoreQueryFilters()
.Include(m => m.Sender) .Include(m => m.Sender)
.Where(m => m.ChatRoomId == roomId) .Where(m => m.ChatRoomId == roomId)
.Where(m => m.UpdatedAt > timestamp || m.DeletedAt > timestamp) .Where(m => m.UpdatedAt > timestamp || m.DeletedAt > timestamp)
.ToListAsync(); .ToListAsync();
var syncMessages = modifiedMessages
.Select(message => CreateSyncMessage(message, timestamp))
.OfType<Message>()
.ToList();
// Load member accounts for messages that need them // Load member accounts for messages that need them
if (syncMessages.Count > 0) if (syncMessages.Count > 0)
{ {
@@ -647,34 +659,6 @@ public partial class ChatService(
}; };
} }
private static Message? CreateSyncMessage(Message message, Instant sinceTimestamp)
{
// Handle deleted messages
if (message.DeletedAt.HasValue && message.DeletedAt > sinceTimestamp)
{
return new Message
{
Id = message.Id,
Type = "messages.delete",
SenderId = message.SenderId,
Sender = message.Sender,
ChatRoomId = message.ChatRoomId,
ChatRoom = message.ChatRoom,
CreatedAt = message.CreatedAt,
UpdatedAt = message.DeletedAt.Value
};
}
// Handle updated/edited messages
if (message.EditedAt.HasValue)
{
var syncMessage = message.Clone();
syncMessage.Type = "messages.update";
return syncMessage;
}
return message;
}
public async Task<Message> UpdateMessageAsync( public async Task<Message> UpdateMessageAsync(
Message message, Message message,
@@ -713,15 +697,30 @@ public partial class ChatService(
// Mark as edited if content or attachments changed // Mark as edited if content or attachments changed
if (isContentChanged || isAttachmentsChanged) if (isContentChanged || isAttachmentsChanged)
{
message.EditedAt = SystemClock.Instance.GetCurrentInstant(); message.EditedAt = SystemClock.Instance.GetCurrentInstant();
}
message.UpdatedAt = SystemClock.Instance.GetCurrentInstant();
db.Update(message); db.Update(message);
await db.SaveChangesAsync(); await db.SaveChangesAsync();
// Create and store sync message for the update
var syncMessage = new Message
{
Type = "messages.update",
ChatRoomId = message.ChatRoomId,
SenderId = message.SenderId,
Content = message.Content,
Attachments = message.Attachments,
Nonce = Guid.NewGuid().ToString(),
Meta = message.Meta != null
? new Dictionary<string, object>(message.Meta) { ["message_id"] = message.Id }
: new Dictionary<string, object> { ["message_id"] = message.Id },
CreatedAt = message.UpdatedAt,
UpdatedAt = message.UpdatedAt
};
db.ChatMessages.Add(syncMessage);
await db.SaveChangesAsync();
// Process link preview in the background if content was updated // Process link preview in the background if content was updated
if (isContentChanged) if (isContentChanged)
_ = Task.Run(async () => await ProcessMessageLinkPreviewAsync(message)); _ = Task.Run(async () => await ProcessMessageLinkPreviewAsync(message));
@@ -729,11 +728,15 @@ public partial class ChatService(
if (message.Sender.Account is null) if (message.Sender.Account is null)
message.Sender = await crs.LoadMemberAccount(message.Sender); message.Sender = await crs.LoadMemberAccount(message.Sender);
// Send sync message to clients
syncMessage.Sender = message.Sender;
syncMessage.ChatRoom = message.ChatRoom;
_ = DeliverMessageAsync( _ = DeliverMessageAsync(
message, syncMessage,
message.Sender, syncMessage.Sender,
message.ChatRoom, syncMessage.ChatRoom,
WebSocketPacketType.MessageUpdate notify: false
); );
return message; return message;
@@ -761,11 +764,36 @@ public partial class ChatService(
db.Update(message); db.Update(message);
await db.SaveChangesAsync(); await db.SaveChangesAsync();
_ = DeliverMessageAsync( // Create and store sync message for the deletion
message, var syncMessage = new Message
message.Sender, {
message.ChatRoom, Type = "messages.delete",
WebSocketPacketType.MessageDelete ChatRoomId = message.ChatRoomId,
SenderId = message.SenderId,
Nonce = Guid.NewGuid().ToString(),
Meta = new Dictionary<string, object>
{
["message_id"] = message.Id
},
CreatedAt = message.DeletedAt.Value,
UpdatedAt = message.DeletedAt.Value
};
db.ChatMessages.Add(syncMessage);
await db.SaveChangesAsync();
// Send sync message to clients
if (message.Sender.Account is null)
message.Sender = await crs.LoadMemberAccount(message.Sender);
syncMessage.Sender = message.Sender;
syncMessage.ChatRoom = message.ChatRoom;
await DeliverMessageAsync(
syncMessage,
syncMessage.Sender,
syncMessage.ChatRoom,
notify: false
); );
} }
} }