feat(#51): queue-sync file log + parked-drain re-run logging + manual force-drain action

pull/209/head
Strycher 1 week ago
parent 2005e5f8c7
commit 0b4796a707

@ -32,6 +32,8 @@ import '../services/background_service.dart';
import '../services/timeout_prediction_service.dart';
import '../services/translation_service.dart';
import '../services/notification_service.dart';
import '../services/queue_sync_file_log_stub.dart'
if (dart.library.io) '../services/queue_sync_file_log_io.dart';
import 'meshcore_connector_usb.dart';
import 'meshcore_connector_tcp.dart';
import '../storage/channel_message_store.dart';
@ -3547,11 +3549,13 @@ class MeshCoreConnector extends ChangeNotifier {
await sendFrame(buildSetDeviceTimeFrame(now));
}
// Mirror queue-sync events to the in-app App Debug Log (plus the console) so
// a missed/stuck drain is diagnosable from the device. See #51.
// Mirror queue-sync events to an always-on file sink (survives the app being
// closed during a drain), the in-app App Debug Log (when enabled), and the
// console, so a missed/stuck drain stays diagnosable. See #51.
void _logQueueSync(String msg) {
debugPrint('[QueueSync] $msg');
_appDebugLogService?.info(msg, tag: 'QueueSync');
unawaited(appendQueueSyncLine(msg));
}
Future<void> syncQueuedMessages({bool force = false}) async {
@ -4064,6 +4068,7 @@ class MeshCoreConnector extends ChangeNotifier {
if (_deferQueuedContactMessagesUntilContacts) {
unawaited(_processDeferredQueuedContactMessages());
} else if (_pendingQueueSync) {
_logQueueSync('post-channel-frame: firing parked queue drain');
_pendingQueueSync = false;
unawaited(syncQueuedMessages(force: true));
}
@ -4424,6 +4429,7 @@ class MeshCoreConnector extends ChangeNotifier {
_deferQueuedContactMessagesUntilContacts = false;
notifyListeners();
if (_pendingQueueSync && isConnected) {
_logQueueSync('post-deferred-contacts: firing parked queue drain');
_pendingQueueSync = false;
unawaited(syncQueuedMessages(force: true));
}

@ -605,6 +605,24 @@ class _SettingsScreenState extends State<SettingsScreen> {
);
},
),
const Divider(height: 1),
ListTile(
leading: const Icon(Icons.sync_problem_outlined),
title: const Text('Sync queued messages now'),
subtitle: const Text(
'Force-pull messages the radio is holding — diagnostic for #51 '
'(radio reports a count but the app shows none). Logs the flow '
'for diagnostics.',
),
trailing: const Icon(Icons.download),
onTap: () {
context.read<MeshCoreConnector>().syncQueuedMessages(force: true);
showDismissibleSnackBar(
context,
content: const Text('Requested queued-message drain (force)'),
);
},
),
],
),
);

@ -0,0 +1,40 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';
// Always-on file sink for queue-sync diagnostics, independent of the in-app App
// Debug Log toggle (off by default, and its in-memory buffer is lost when the
// app is closed during a drain). Lands at
// <app documents>/offband-queuesync.log. See #51.
//
// The IOSink is intentionally held open for the app's lifetime (append-only,
// low-frequency) rather than open/close per line; the OS closes the handle on
// process exit. `_sinkFuture ??= _openSink()` assigns synchronously before the
// await, so concurrent callers share one sink no double-open on the event
// loop.
Future<IOSink>? _sinkFuture;
Future<IOSink> _openSink() async {
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/offband-queuesync.log');
debugPrint('[QueueSync] file sink: ${file.path}');
final sink = file.openWrite(mode: FileMode.append);
sink.writeln(
'\n===== offband queue-sync session '
'${DateTime.now().toIso8601String()} =====',
);
return sink;
}
Future<void> appendQueueSyncLine(String msg) async {
try {
final sink = await (_sinkFuture ??= _openSink());
sink.writeln('${DateTime.now().toIso8601String()} $msg');
await sink.flush();
} catch (e) {
_sinkFuture = null; // allow re-init on the next event
debugPrint('[QueueSync] file sink error: $e');
}
}

@ -0,0 +1,3 @@
// Web/default stub: no local filesystem, so queue-sync diagnostics fall back to
// the in-app App Debug Log only. See #51.
Future<void> appendQueueSyncLine(String msg) async {}
Loading…
Cancel
Save

Powered by TurnKey Linux.