Every ephemeral OfflineSyncDatabase shares one context but initializes a recorder of its own, and each rebuilt the projections of every space when the context's first initialize had changed the registry: on every session and every merge, until the process stopped (upstream #150). A new device, or one whose app changed its synced tables, spent about 3 s of every inbound merge on it with a library of 8,000 cards, a server after such a migration as much on every request. The context now runs the rebuild once (Once): wrappers initializing while it runs await the same run, later ones skip it, and a failed run is tried again by the next. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
21 lines
571 B
Dart
21 lines
571 B
Dart
import 'package:meta/meta.dart';
|
|
|
|
/// Runs an action once for everyone who asks: a caller while it runs awaits
|
|
/// the same run, and one after it is done gets it done; only a run that
|
|
/// failed is run again by the next caller.
|
|
@internal
|
|
class Once {
|
|
Future<void>? _run;
|
|
|
|
/// Runs [action] unless it ran or runs already, and completes with that
|
|
/// run.
|
|
Future<void> run(Future<void> Function() action) async {
|
|
final run = _run ??= action();
|
|
try {
|
|
await run;
|
|
} catch (_) {
|
|
if (identical(_run, run)) _run = null;
|
|
rethrow;
|
|
}
|
|
}
|
|
}
|