watch method
Watches mountId and auto-syncs on local changes and on an interval
poll. Runs until until completes; when omitted it runs until the returned
future is never completed (the caller cancels via process signal).
Directory mounts also react to filesystem events.
Implementation
Future<void> watch(
String mountId, {
Duration interval = const Duration(seconds: 15),
Duration debounce = const Duration(milliseconds: 500),
void Function(String message)? log,
DriveProgress? onProgress,
Future<void>? until,
}) async {
final record = require(mountId);
var running = false;
Timer? debounceTimer;
Future<void> trigger(String why) async {
if (running) return;
running = true;
try {
final o = await sync(mountId, onProgress: onProgress);
if (o.isConflict) {
log?.call('conflict ($why): ${o.conflict!.message}');
} else if (o.direction != null) {
log?.call(
'synced ${o.direction!.wireValue} ($why): ${o.applied} change(s)',
);
}
} on Object catch (e) {
log?.call('sync failed ($why): $e');
} finally {
running = false;
}
}
StreamSubscription<FileSystemEvent>? fsSub;
if (!record.isGit && record.localPath != null) {
fsSub = Directory(record.localPath!).watch(recursive: true).listen((_) {
debounceTimer?.cancel();
debounceTimer = Timer(debounce, () => trigger('fs'));
});
}
final timer = Timer.periodic(interval, (_) => trigger('poll'));
await trigger('initial');
log?.call('watching ${record.id} (Ctrl-C to stop)');
try {
// Run until cancelled: either the caller-supplied [until] completes, or
// (when none is given) the process is interrupted.
await (until ?? Completer<void>().future);
} finally {
await fsSub?.cancel();
timer.cancel();
debounceTimer?.cancel();
}
}