claimPeerRun function
Attaches to the shared run id, creating it on first claim.
createRun is called only by the first peer, inside the lock, so N peers
never produce N runs. Rethrows whatever createRun throws.
Implementation
Future<PeerClaim> claimPeerRun(
int projectId,
String runTitle,
Future<int> Function() createRun, {
Map<String, String>? env,
}) async {
final paths = handoffPaths(projectId, runTitle, env);
if (!acquireHandoffLock(paths.lockPath, const Duration(seconds: 60))) {
throw StateError(
'Tracera: timed out waiting for handoff lock ${paths.lockPath}',
);
}
try {
final state = _readHandoffState(paths.idPath);
if (state != null) {
if (_handoffIdStale(paths.idPath)) {
_tryDeleteFile(paths.idPath);
logDebug(
'Tracera: peer handoff .id file stale '
'(>${handoffIdStaleAfter.inHours}h), creating a new run',
);
} else {
if (!_tryWriteHandoffState(
paths.idPath,
state.runId,
state.refs + 1,
state.claimed + 1,
)) {
throw StateError(
'Tracera: peer handoff could not write ${paths.idPath}',
);
}
logDebug(
'Tracera: peer handoff attach run #${state.runId} '
'(refs=${state.refs + 1}, claimed=${state.claimed + 1})',
);
return PeerClaim(state.runId, false);
}
}
final runId = await createRun();
if (!_tryWriteHandoffState(paths.idPath, runId, 1, 1)) {
throw StateError('Tracera: peer handoff could not write ${paths.idPath}');
}
logDebug('Tracera: peer handoff created run #$runId');
return PeerClaim(runId, true);
} finally {
releaseHandoffLock(paths.lockPath);
}
}