scenarioResync function

Future<void> scenarioResync(
  1. FakeServer server,
  2. WorldSeed w,
  3. ScenarioClient client
)

04 16.3, the resync_required branch: the log no longer holds the client's cursor (retention); the client keeps its outbox, loads the snapshot, reloads the focused thread and goes on live from the head without reconnecting.

Implementation

Future<void> scenarioResync(
  FakeServer server,
  WorldSeed w,
  ScenarioClient client,
) async {
  await client.start();
  await client.focusThread(w.releaseNotes);
  await client.goOffline();
  w.post(w.sam, w.releaseNotes, 'Posted during the gap');
  server.world.dropEventsUpTo(server.world.headSeq);
  final id = await client.send(w.releaseNotes, 'Kept in the outbox');
  final before = server.gateway.connections.length;
  await client.goOnline();
  await waitFor(
    'resync notice',
    () => client.notices.contains('resynced:retention'),
  );
  final number = server.gateway.connections.last.number;
  _check(
    server.gateway.connections.length == before + 1,
    'one new connection, no reconnect',
  );
  _check(
    server.gateway.sentOn(number).any((f) => f.op == 'resync_required'),
    'the server sent resync_required',
  );
  await waitFor(
    'the outbox entry sent',
    () async => (await client.outbox()).isEmpty,
  );
  await waitFor(
    'own message',
    () async => (await _withId(client, w.releaseNotes, id)).isNotEmpty,
  );
  await waitFor(
    'the reloaded thread',
    () async =>
        [for (final m in await client.messages(w.releaseNotes)) m.text]
            .contains('Posted during the gap'),
  );
  _check(server.gateway.connections.last.open, 'the connection stayed open');
  _contract(server);
}