From 0b2c9a08c603abd6468fe6b8521ac3301f67ee21 Mon Sep 17 00:00:00 2001 From: Meleki Date: Fri, 27 Feb 2026 08:13:44 +0100 Subject: [PATCH] DB: Message + Attachments in einer Transaktion speichern (1x fsync statt N+1) --- Endpoints/ChatEndpoint.cs | 28 ++++++++++---------------- Services/DatabaseService.cs | 40 +++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/Endpoints/ChatEndpoint.cs b/Endpoints/ChatEndpoint.cs index 2413111..1f6c06f 100644 --- a/Endpoints/ChatEndpoint.cs +++ b/Endpoints/ChatEndpoint.cs @@ -133,28 +133,22 @@ public static class ChatEndpoint var attachmentInfos = lastUserMsg.GetAttachments(); var attachmentBlocks = lastUserMsg.GetAttachmentBlocks(); - var messageId = await db.SaveMessage(new MessageRecord + var attachmentRecords = attachmentBlocks.Select(b => new AttachmentRecord + { + Type = b.Type, + MediaType = b.MediaType, + FileName = b.FileName, + Data = b.Data + }).ToList(); + + await db.SaveMessageWithAttachments(new MessageRecord { ChainId = chainId, Iteration = 0, Role = "user", Type = "text", - Content = textContent, - AttachmentCount = attachmentBlocks.Count - }); - - // Attachments separat speichern - foreach (var block in attachmentBlocks) - { - await db.SaveAttachment(new AttachmentRecord - { - MessageId = messageId, - Type = block.Type, - MediaType = block.MediaType, - FileName = block.FileName, - Data = block.Data - }); - } + Content = textContent + }, attachmentRecords); } var systemPrompt = new List diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index d348844..ca5cdfc 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -360,18 +360,42 @@ public class DatabaseService ", record); } - // ── Attachments ── - - public async Task SaveAttachment(AttachmentRecord attachment) + /// + /// Speichert Message + Attachments in einer Transaktion (1x fsync statt N+1). + /// + public async Task SaveMessageWithAttachments(MessageRecord record, List attachments) { using var conn = CreateConnection(); - attachment.CreatedAt = DateTime.UtcNow.ToString("o"); - await conn.ExecuteAsync(@" - INSERT INTO attachments (message_id, type, media_type, file_name, data, created_at) - VALUES (@MessageId, @Type, @MediaType, @FileName, @Data, @CreatedAt) - ", attachment); + using var tx = conn.BeginTransaction(); + + record.CreatedAt = DateTime.UtcNow.ToString("o"); + record.AttachmentCount = attachments?.Count ?? 0; + var messageId = await conn.ExecuteScalarAsync(@" + INSERT INTO messages (chain_id, role, type, content, tool_name, tool_call_id, is_error, iteration, attachment_count, created_at) + VALUES (@ChainId, @Role, @Type, @Content, @ToolName, @ToolCallId, @IsError, @Iteration, @AttachmentCount, @CreatedAt); + SELECT last_insert_rowid(); + ", record, tx); + + if (attachments != null) + { + var now = DateTime.UtcNow.ToString("o"); + foreach (var att in attachments) + { + att.MessageId = messageId; + att.CreatedAt = now; + await conn.ExecuteAsync(@" + INSERT INTO attachments (message_id, type, media_type, file_name, data, created_at) + VALUES (@MessageId, @Type, @MediaType, @FileName, @Data, @CreatedAt) + ", att, tx); + } + } + + tx.Commit(); + return messageId; } + // ── Attachments ── + public async Task> GetAttachments(long messageId) { using var conn = CreateConnection();