Honker.Lock (honker v0.1.4)

Copy Markdown

Advisory locks on top of honker_lock_* SQL functions. Elixir has no RAII, so the caller manages the lock lifetime explicitly:

case Honker.Lock.try_acquire(db, "nightly-report", "worker-1", 60) do
  {:ok, nil} -> :already_held
  {:ok, %Honker.Lock{} = lock} ->
    try do
      do_work()
    after
      Honker.Lock.release(lock, db)
    end
end

heartbeat/3 refreshes the TTL. If it returns {:ok, false}, another owner has stolen the lock — stop doing the work the lock guards.

Summary

Functions

Refresh (extend) the lock's TTL.

Release the lock. Returns {:ok, true} if we still held it and it was released, {:ok, false} if the TTL had already expired and the lock wasn't ours anymore.

Attempt to acquire the lock. Returns {:ok, %Honker.Lock{}} if acquired, {:ok, nil} if another owner already holds it.

Functions

heartbeat(lock, database, ttl_s)

Refresh (extend) the lock's TTL.

honker_lock_acquire uses INSERT OR IGNORE internally, so it can't extend the TTL on an already-held row — we have to UPDATE expires_at directly (matching what the Python scheduler does).

Returns {:ok, true} if we still own it, {:ok, false} if the TTL already expired and someone else took it (row now has a different owner) or the row is gone entirely. Check the return value — holding the %Honker.Lock{} struct is not a guarantee.

release(lock, database)

Release the lock. Returns {:ok, true} if we still held it and it was released, {:ok, false} if the TTL had already expired and the lock wasn't ours anymore.

try_acquire(database, name, owner, ttl_s)

Attempt to acquire the lock. Returns {:ok, %Honker.Lock{}} if acquired, {:ok, nil} if another owner already holds it.