Restructure step 0 done: notice table test, flaky-link proxy, liveness on the engine clock, STARSYNC_PROFILE
ci / core (push) Successful in 27s
ci / server (push) Successful in 1m4s
ci / updater-windows (push) Successful in 5m56s

- notice_table_test: one row per AppEvent variant through noticeFor.
- FlakyProxy (core/testing.dart): pass, blackhole (half-open), delay,
  hold, cut after N bytes, reset; demo tests against today's server.
- Liveness (stale/drop/ping) on the engine clock, so grace can be tested
  with a fake clock; Connection takes an injectable clock.
- AppDirs with STARSYNC_PROFILE=<name>: separate data and logs, so two
  instances run on one machine.
- DEVELOPMENT: scenario list per restructure step; test tags follow the
  new step order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-15 20:05:52 +03:00
1 parent eac45746ce
commit f4ca02c3cf
23 files changed
+959 -48

No files matched your search

+12 -5
View File
@@ -196,23 +196,30 @@ class Connection {
final Duration reconnectDelay;
/// No state broadcast for this long means the connection is lost.
final Duration silenceLimit;
/// The clock [silenceLimit] is measured on (UTC; a test passes a fake
/// one). The heartbeat that checks it stays a real 1 s timer.
final DateTime Function() now;
Connection(
{void Function(AppEvent event)? notify,
SyncClient? client,
this.hello = defaultHello,
this.reconnectDelay = const Duration(milliseconds: 1500),
this.silenceLimit = const Duration(seconds: 5)})
this.silenceLimit = const Duration(seconds: 5),
DateTime Function()? now})
: _notify = notify ?? ((_) {}),
now = now ?? _utcNow,
client = client ?? SyncClient() {
_subs = [
this.client.status.listen(_onStatus),
this.client.states.listen((_) => _lastStateAt = DateTime.now().toUtc()),
this.client.states.listen((_) => _lastStateAt = this.now()),
];
}
late final List<StreamSubscription> _subs;
static DateTime _utcNow() => DateTime.now().toUtc();
final _state = signal<ConnState>(const ConnClosed());
/// Every change is notified, a repeat too.
ReadonlySignal<ConnState> get state => _state;
@@ -368,7 +375,7 @@ class Connection {
_notify(const ConnectionBack());
}
_resumeToken = client.token;
_lastStateAt = DateTime.now().toUtc();
_lastStateAt = now();
_set(const ConnOnline());
_startHeartbeat();
}
@@ -400,13 +407,13 @@ class Connection {
/// Every second while connected: a clock sample, the diagnostics, and
/// the silence check.
void _beat() {
final now = DateTime.now().toUtc();
final t = now();
if (client.token.isNotEmpty) client.sendPing();
diag
..share = AppSettings.instance.shareDiagnostics.peek()
..tick();
final last = _lastStateAt;
if (!_closed && last != null && now.difference(last) >= silenceLimit) {
if (!_closed && last != null && t.difference(last) >= silenceLimit) {
_silence.add(null);
if (!_state.peek().retrying) _dropped();
}