acquire method

Future<LeaseAcquire> acquire({
  1. required String sessionFilePath,
  2. required String sessionId,
  3. required String host,
  4. required String bootId,
  5. required int pid,
  6. String? sessionName,
})

Attempts to acquire the lease for a drive-open. A live lease is never seized — the caller becomes a viewer (LeaseBlocked). A free or expired lease is (re-)acquired atomically (temp + rename, E5); the write is verified by re-reading: a racer that renamed last owns it, the loser sees a foreign bootId and stands down.

Implementation

Future<LeaseAcquire> acquire({
  required String sessionFilePath,
  required String sessionId,
  required String host,
  required String bootId,
  required int pid,
  String? sessionName,
}) async {
  final found = await inspect(sessionFilePath);
  if (found.state == LeaseState.live) return LeaseBlocked(found.lease!);
  final nowIso = _now().toUtc().toIso8601String();
  final lease = SessionLease(
    host: host,
    sessionId: sessionId,
    pid: pid,
    bootId: bootId,
    sessionName: sessionName,
    heartbeatAt: nowIso,
    acquiredAt: nowIso,
  );
  final path = sidecarPath(sessionFilePath);
  final renamable = _env is RenamableFileSystem
      ? _env as RenamableFileSystem
      : null;
  if (renamable == null) {
    // No atomic rename on this backend (pure web stores): ownership
    // cannot be enforced safely — drive unleased rather than publish a
    // sidecar a concurrent reader could see half-written (E5).
    return LeaseUnenforced(lease);
  }
  // Atomic publish (E5): a unique temp per attempt, then one rename.
  // ponytail: rename-over leaves a microsecond double-claim window
  // (A publishes, B overwrites before A re-reads); the 5s heartbeat +
  // 15s staleness make it self-healing — a real fight shows up as both
  // sides heartbeating and needs a compare-and-swap primitive in
  // ExecutionEnv first.
  final tmp = '$path.${bootId.hashCode.toRadixString(36)}.tmp';
  final encoded = const JsonEncoder.withIndent('  ').convert(lease.toJson());
  final write = await _env.writeFile(tmp, encoded);
  final renamed = write.isOk ? await renamable.renamePath(tmp, path) : write;
  if (renamed.isErr) {
    // E4: a broken lease store never blocks opening a session — the
    // drive proceeds without enforcement (the honest kind of fail-open).
    await _env.remove(tmp, force: true);
    return LeaseUnenforced(lease);
  }
  // Verify ownership: the freshest rename wins; a loser stands down.
  final verify = await _readLease(path);
  if (verify == null) return LeaseUnenforced(lease);
  if (verify.bootId != bootId) return LeaseBlocked(verify);
  return LeaseAcquired(verify, replaced: found.lease);
}