write method

Future<TrajectoryRequestSpill?> write({
  1. required TrajectoryRequestDetail detail,
  2. String? rawWireDump,
  3. String redactWireDump(
    1. String
    )?,
})

Writes detail (plus the built rawWireDump, when the request carried one) as one JSON blob and returns the spill outcome. Null on any write failure — the caller falls back to the legacy inline persistence (AC6 shape: the capture is never lost, never a crash).

redactWireDump is the host's active pipeline pass (E1: the dump is redacted under the config active at capture time) and the dump rides the same wireDumpMaxChars cap as the inline record did.

The FIRST write of a store instance also runs the boot-time TTL sweep (sweepOncePerBoot) — the store is built lazily at the first request of a session, so hosts need no extra wiring.

Implementation

Future<TrajectoryRequestSpill?> write({
  required TrajectoryRequestDetail detail,
  String? rawWireDump,
  String Function(String)? redactWireDump,
}) async {
  await sweepOncePerBoot();
  final dump = rawWireDump == null
      ? null
      : trajectoryBuildWireDump(rawWireDump, redact: redactWireDump);
  final payload = jsonEncode({
    'detail': detail.toJson(),
    if (dump != null) 'wireDump': dump.toJson(),
  });
  final sid = _sessionId();
  if (_counterSession != sid) {
    _counterSession = sid;
    _counter = 0;
  }
  if (_counter == 0) {
    // Sequence numbers must survive a process restart on a resumed
    // session: probe the dir once and continue past the highest
    // existing file (a failed probe starts at 1 — worst case a legacy
    // file of the same name is superseded, never merged).
    _counter = await _maxExistingSequence(sid);
  }
  _counter++;
  final file = '${trajectoryRequestBlobDir(sid)}/$_counter.json';
  final written = await _env.writeBinaryFile(file, utf8.encode(payload));
  if (written.isErr) return null;
  await _maybeSweep(payload.length);
  return TrajectoryRequestSpill(file: file, wireDumpHash: dump?.hash);
}