stopAndAwaitProxiedStateStore function

Future<void> stopAndAwaitProxiedStateStore({
  1. required String workspacePath,
  2. required String pidRootPath,
  3. Set<int> recordedPids = const {},
})

Stops the proxied store serving workspacePath and does not return until it is GONE.

Order is the whole point. The proxy and its dolt sql-server hold the data directory a delete removes; a delete that races them leaves a server running over a path that no longer exists, and the next fixture store on the host can bind to it and fail with a refusal that names neither.

The kill set is seeded from THREE accounts because none is complete alone: recordedPids — what a verified identity already named — plus bd's own PID artifacts under pidRootPath, which name a forked child a whole exec before ps can recognise it, plus the live census, which is the only account of the successor bd spawns to serve the very command that stopped the last one. The census arm is wider than the store processes on purpose: a store process killed while its client still runs simply comes back.

bd dolt stop is NOT the instrument. It is a MODE CHANGE — it migrates the workspace back to embedded storage, which a CGO-free binary cannot even open — and it re-spawns a proxy to serve its own command, so the process it leaves behind is never the one it reported stopping.

LOUD on residue it cannot remove, via waitForProxiedStateStoreExit. Idempotent, so a registered teardown may follow a manual call.

Implementation

Future<void> stopAndAwaitProxiedStateStore({
  required String workspacePath,
  required String pidRootPath,
  Set<int> recordedPids = const {},
}) async {
  final named = <int>{
    ...recordedPids,
    ...proxiedStateStorePids(pidRootPath: pidRootPath),
  };
  // bd's own record is signalled FIRST, before any census: a forked child is
  // in these files a whole exec before it is recognisable in `ps`.
  for (final target in named) {
    Process.killPid(target, ProcessSignal.sigkill);
  }
  await waitForProxiedStateStoreExit(
    survivingPids: () => _reapStoreResidue(workspacePath, named),
    heldLockPaths: () => _heldProxyLocks(pidRootPath),
    now: DateTime.now,
    delay: (duration) => Future<void>.delayed(duration),
  );
}