From a4f64fec47b8cafb638d6643df2b56b9e152d3d3 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Mon, 06 Apr 2026 15:49:12 +0200
Subject: [PATCH] fix: always rebuild index from log on startup, flush index after every append

---
 lib/services/message_store.dart |   41 ++++++++++++++---------------------------
 1 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/lib/services/message_store.dart b/lib/services/message_store.dart
index 71a7655..1497228 100644
--- a/lib/services/message_store.dart
+++ b/lib/services/message_store.dart
@@ -64,33 +64,18 @@
       final logFile = File(_logPath(dir));
       final indexFile = File(_indexPath(dir));
 
-      // Try loading saved index first (fast path).
-      if (indexFile.existsSync()) {
-        try {
-          final raw = indexFile.readAsStringSync();
-          final decoded = jsonDecode(raw) as Map<String, dynamic>;
-          for (final entry in decoded.entries) {
-            _index[entry.key] =
-                (entry.value as List<dynamic>).map((e) => e as int).toList();
-          }
-        } catch (_) {
-          _index.clear();
-        }
-      }
-
-      // Count actual lines in log to set _lineCount.
+      // Always rebuild index from log (the saved index.json may be stale
+      // if the app was killed before a flush).
       if (logFile.existsSync()) {
         final content = logFile.readAsStringSync();
         _lineCount = content.isEmpty
             ? 0
             : content.trimRight().split('\n').length;
+        if (_lineCount > 0) {
+          await _rebuildIndex(logFile);
+        }
       } else {
         _lineCount = 0;
-      }
-
-      // If the index was missing or corrupt, rebuild from log.
-      if (_index.isEmpty && _lineCount > 0) {
-        await _rebuildIndex(logFile);
       }
 
       TraceService.instance.addTrace(
@@ -143,15 +128,15 @@
       logFile.writeAsStringSync(line, mode: FileMode.append);
 
       // Update in-memory index.
-      _index.putIfAbsent(sessionId, () => []).add(_lineCount);
+      final lineNum = _lineCount;
+      _index.putIfAbsent(sessionId, () => []).add(lineNum);
       _lineCount++;
 
-      // Periodically flush index to disk.
-      _appendsSinceFlush++;
-      if (_appendsSinceFlush >= _indexFlushInterval) {
-        _flushIndex(dir);
-        _appendsSinceFlush = 0;
-      }
+      TraceService.instance.addTrace('MsgStoreV2 APPEND',
+          '${sessionId.substring(0, 8)} line=$lineNum total=$_lineCount idx=${_index[sessionId]?.length ?? 0}');
+
+      // Flush index after every append to prevent data loss on app kill.
+      _flushIndex(dir);
     } catch (e) {
       TraceService.instance.addTrace('MsgStoreV2 APPEND ERROR', '$e');
     }
@@ -173,6 +158,8 @@
 
       // Read all lines at once then pick the ones we need.
       final allLines = logFile.readAsLinesSync();
+      TraceService.instance.addTrace('MsgStoreV2 LOAD detail',
+          '${sessionId.substring(0, 8)}: fileLines=${allLines.length} indexEntries=${lineNumbers.length} lineCount=$_lineCount');
       final messages = <Message>[];
 
       for (final n in lineNumbers) {

--
Gitblit v1.3.1