acquire static method
Acquires the lock at path, blocking until it is held.
Polls a held lock from pollInterval, doubling up to maxPollInterval.
If heartbeatInterval is set, the file's modified time is refreshed while
the lock is held so StaleLockPolicy.age backstops measure idle time, not
time spent doing the guarded work.
Throws TimeoutException if the lock cannot be acquired within timeout.
Implementation
static Future<InterProcessLock> acquire(
String path, {
required StaleLockPolicy staleWhen,
Duration timeout = const Duration(minutes: 6),
Duration pollInterval = const Duration(milliseconds: 50),
Duration maxPollInterval = const Duration(seconds: 1),
Duration? heartbeatInterval,
}) async {
final file = File(path);
final token = _mintToken();
final elapsed = Stopwatch()..start();
// Backoff doubles from pollInterval up to maxPollInterval while waiting.
var backoff = pollInterval;
while (true) {
try {
file.createSync(exclusive: true);
file.writeAsStringSync(token);
final lock = InterProcessLock._(file, token);
if (heartbeatInterval != null) lock._startHeartbeat(heartbeatInterval);
return lock;
} on FileSystemException {
// Read once so the staleness check and the reclaim target the same lock.
final observed = _readOrEmpty(file);
if (_isStale(file, observed, staleWhen)) {
_tryDeleteIfMatches(file, observed);
continue;
}
if (elapsed.elapsed > timeout) {
throw TimeoutException(
'Timed out acquiring the lock at ${file.path}',
timeout,
);
}
await Future<void>.delayed(backoff);
backoff = Duration(
microseconds: min(
backoff.inMicroseconds * 2,
maxPollInterval.inMicroseconds,
),
);
}
}
}