acquire method

Future<LockIdentifier> acquire(
  1. String operation, {
  2. Duration ttl = const Duration(seconds: 30),
  3. Duration retryPeriod = const Duration(milliseconds: 200),
})

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;
}