Skip to content

Commit 37b536b

Browse files
committed
fix : solving concurrent access
1 parent b81dada commit 37b536b

File tree

4 files changed

+81
-29
lines changed

4 files changed

+81
-29
lines changed

lib/background/background.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ String currentLanguage = 'en';
1717
@pragma('vm:entry-point')
1818
Future<void> serviceMain(ServiceInstance service) async {
1919
// Initialize persistent logging for background isolate
20-
final logsDb = await openMostroDatabase('logs.db');
20+
final logsDb = await openMostroDatabase(getLogsDatabaseName(LogContext.mobile));
2121
final logStorage = LogStorage(db: logsDb);
22-
initializeLogger(logStorage);
22+
initializeLogger(logStorage, LogContext.mobile);
2323

2424
final Map<String, Map<String, dynamic>> activeSubscriptions = {};
2525
final nostrService = NostrService();

lib/background/desktop_background_service.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class DesktopBackgroundService implements BackgroundService {
3030
BackgroundIsolateBinaryMessenger.ensureInitialized(token);
3131

3232
// Initialize persistent logging for desktop background isolate
33-
final logsDb = await openMostroDatabase('logs.db');
33+
final logsDb = await openMostroDatabase(getLogsDatabaseName(LogContext.desktop));
3434
final logStorage = LogStorage(db: logsDb);
35-
initializeLogger(logStorage);
35+
initializeLogger(logStorage, LogContext.desktop);
3636

3737
final nostrService = NostrService();
3838

lib/main.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ Future<void> main() async {
2929

3030
final mostroDatabase = await openMostroDatabase('mostro.db');
3131
final eventsDatabase = await openMostroDatabase('events.db');
32-
final logsDatabase = await openMostroDatabase('logs.db');
32+
final logsDatabase = await openMostroDatabase(getLogsDatabaseName(LogContext.main));
3333

3434
final logStorage = LogStorage(db: logsDatabase);
35-
initializeLogger(logStorage);
35+
initializeLogger(logStorage, LogContext.main);
3636

3737
final settings = SettingsNotifier(sharedPreferences);
3838
await settings.init();

lib/services/logger_service.dart

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,39 @@ class _AlwaysStackTraceFilter extends LogFilter {
208208
bool shouldLog(LogEvent event) => true;
209209
}
210210

211-
// Global storage reference for persistent logging
212-
LogStorage? _globalLogStorage;
211+
/// Isolate context for logging
212+
enum LogContext {
213+
main,
214+
mobile,
215+
desktop,
216+
}
217+
218+
// Global storage references for isolated logging (one per isolate)
219+
final Map<LogContext, LogStorage> _logStorages = {};
220+
LogContext? _currentContext;
221+
222+
/// Get the database filename for a specific context
223+
String getLogsDatabaseName(LogContext context) {
224+
switch (context) {
225+
case LogContext.main:
226+
return 'logs_main.db';
227+
case LogContext.mobile:
228+
return 'logs_mobile.db';
229+
case LogContext.desktop:
230+
return 'logs_desktop.db';
231+
}
232+
}
213233

214-
/// Initialize the logger with persistent storage
215-
/// MUST be called before using the logger
216-
void initializeLogger(LogStorage logStorage) {
217-
_globalLogStorage = logStorage;
234+
/// Initialize the logger with persistent storage for a specific isolate context
235+
/// MUST be called before using the logger in each isolate
236+
///
237+
/// Example:
238+
/// - Main app: initializeLogger(logStorage, LogContext.main)
239+
/// - Mobile background: initializeLogger(logStorage, LogContext.mobile)
240+
/// - Desktop background: initializeLogger(logStorage, LogContext.desktop)
241+
void initializeLogger(LogStorage logStorage, LogContext context) {
242+
_logStorages[context] = logStorage;
243+
_currentContext = context;
218244
// Reset cached loggers to pick up new storage
219245
_cachedSimpleLogger = null;
220246
_cachedFullLogger = null;
@@ -224,9 +250,9 @@ Logger? _cachedSimpleLogger;
224250
Logger? _cachedFullLogger;
225251

226252
Logger get logger {
227-
// Use persistent storage if initialized, otherwise fallback to memory
228-
final LogOutput primaryOutput = _globalLogStorage != null
229-
? PersistentLogOutput(_globalLogStorage!)
253+
// Use persistent storage if initialized for current context, otherwise fallback to memory
254+
final LogOutput primaryOutput = _currentContext != null && _logStorages.containsKey(_currentContext)
255+
? PersistentLogOutput(_logStorages[_currentContext]!)
230256
: MemoryLogOutput.instance;
231257

232258
if (Config.fullLogsInfo) {
@@ -255,38 +281,64 @@ Logger get logger {
255281
}
256282

257283

258-
/// Get all logs from storage
284+
/// Get all logs from ALL storages (main, mobile, desktop) merged and sorted
259285
Future<List<LogEntry>> getAllLogs() async {
260-
if (_globalLogStorage == null) {
286+
if (_logStorages.isEmpty) {
261287
// Fallback to memory buffer if storage not initialized
262288
return MemoryLogOutput.instance.getAllLogs();
263289
}
264-
return await _globalLogStorage!.getAllLogs();
290+
291+
// Collect logs from all isolate storages
292+
final allLogs = <LogEntry>[];
293+
for (final storage in _logStorages.values) {
294+
final logs = await storage.getAllLogs();
295+
allLogs.addAll(logs);
296+
}
297+
298+
// Sort by timestamp descending (newest first)
299+
allLogs.sort((a, b) => b.timestamp.compareTo(a.timestamp));
300+
301+
return allLogs;
265302
}
266303

267-
/// Watch logs with real-time updates
268-
Stream<List<LogEntry>> watchLogs() {
269-
if (_globalLogStorage == null) {
304+
/// Watch logs with real-time updates from ALL storages
305+
Stream<List<LogEntry>> watchLogs() async* {
306+
if (_logStorages.isEmpty) {
270307
// Fallback: return memory buffer as stream
271-
return Stream.value(MemoryLogOutput.instance.getAllLogs());
308+
yield MemoryLogOutput.instance.getAllLogs();
309+
return;
310+
}
311+
312+
// Periodically fetch and merge logs from all storages
313+
await for (final _ in Stream.periodic(const Duration(milliseconds: 500))) {
314+
final allLogs = await getAllLogs();
315+
yield allLogs;
272316
}
273-
return _globalLogStorage!.watchLogs();
274317
}
275318

276-
/// Clear all logs
319+
/// Clear all logs from ALL storages
277320
Future<void> clearAllLogs() async {
278-
if (_globalLogStorage == null) {
321+
if (_logStorages.isEmpty) {
279322
MemoryLogOutput.instance.clear();
280323
return;
281324
}
282-
await _globalLogStorage!.clearAll();
325+
326+
// Clear all isolate storages
327+
for (final storage in _logStorages.values) {
328+
await storage.clearAll();
329+
}
283330
}
284331

285-
/// Get total log count
332+
/// Get total log count from ALL storages
286333
Future<int> getLogCount() async {
287-
if (_globalLogStorage == null) {
334+
if (_logStorages.isEmpty) {
288335
return MemoryLogOutput.instance.logCount;
289336
}
290-
return await _globalLogStorage!.getLogCount();
337+
338+
int total = 0;
339+
for (final storage in _logStorages.values) {
340+
total += await storage.getLogCount();
341+
}
342+
return total;
291343
}
292344

0 commit comments

Comments
 (0)