acquire method
Acquires a lock for the provided operation
and returns a
LockIdentifier holding it.
ttl
is the time to live for the lock, after which it will be
automatically released.
retryPeriod
is the time to wait before retrying to acquire the lock, if
it is already held by another operation.
This method will keep retrying until the lock is acquired or this LockDriftProvider is closed.
Implementation
Future<LockIdentifier> acquire(
String operation, {
Duration ttl = const Duration(seconds: 30),
Duration retryPeriod = const Duration(milliseconds: 200),
}) async {
final LockIdentifier holder = LockIdentifier.generate();
bool acquired = false;
while (!acquired && !isClosed) {
await safe((db) async {
final lock = LockRow(
operation: operation,
holder: holder.val,
lockedAt: PreciseDateTime.now(),
);
final row = await db
.into(db.locks)
.insertReturningOrNull(
lock,
onConflict: DoUpdate(
(_) => lock,
where: (e) =>
e.operation.equals(operation) &
// TODO: Check whether this accounts `NULL` values.
e.lockedAt.isSmallerOrEqualValue(
(lock.lockedAt!).subtract(ttl).microsecondsSinceEpoch,
),
),
mode: InsertMode.insertOrRollback,
);
acquired = row?.holder == holder.val;
}, tag: 'lock.acquire($operation)');
if (!acquired) {
await Future.delayed(retryPeriod);
}
}
return holder;
}