Skip to content

Class: PostgresMutexDriver ​

The PostgreSQL driver ({type: 'postgres'}): the locks are shared by every instance connected to the same database with the same prefix. It needs the optional peer dependency pg (8); without it, the first acquisition fails with MutexDriverNotFoundException. It has two modes:

  • 'advisory' (the default): session advisory locks (pg_try_advisory_lock) taken on one connection of the driver, opened at the first use. They do not expire and need no renewal: PostgreSQL releases them when the connection closes, so a crashed process frees them at once. When the connection closes or fails, every lock it held is lost (a Mutex aborts their signals) and the next acquisition opens a new connection. A connection cut without the client noticing it is not detected by the renewals. No fencing token. The lock names are hashed to 64-bit keys, shared with the other advisory locks of the database. It does not work through a pooler in transaction mode (PgBouncer), which does not keep the session.
  • 'table': one row per lock in a table, created at the first use with its sequence <table>_fence. The rows expire by the database clock after their ttl unless renewed, so it works through the poolers and on the replicated setups writing to one primary, and each acquisition gets a fencing token from the sequence. A pool of 4 connections is used.

Example ​

typescript
import {PostgresMutexDriver, type DriverLock} from 'lakutata/com/mutex'

const driver: PostgresMutexDriver = new PostgresMutexDriver({
    host: '127.0.0.1',
    database: 'app',
    username: 'app',
    password: 'secret'
}, 'my-app:', 'table', 'app_locks')
const lock: DriverLock | undefined = await driver.acquire('invoice:7', 30000)
if (lock) await driver.release('invoice:7', lock)
await driver.close()

Extends ​

Constructors ​

Constructor ​

new PostgresMutexDriver(connection, prefix, mode?, table?): PostgresMutexDriver

Create a driver on a PostgreSQL database; it connects at its first use.

Parameters ​

connection ​

PostgresMutexConnection

The connection to the database.

prefix ​

string

The prefix added to the lock names.

mode? ​

"advisory" | "table"

'advisory' (the default) or 'table'.

table? ​

string

The table of the table mode, optionally qualified by its schema (locks.mutex); 'lakutata_mutex' by default.

Returns ​

PostgresMutexDriver

Throws ​

When the table is not a valid PostgreSQL name (letters, digits and _, not starting with a digit).

Overrides ​

MutexDriver.constructor

Properties ​

expiring ​

readonly expiring: boolean

true in the table mode (the rows expire), false in the advisory mode (the locks end with the connection).

Overrides ​

MutexDriver.expiring


onLost ​

onLost: (names) => void

Called with the names of the locks the driver lost at once, when the connection holding advisory locks closes or fails. A Mutex sets it; it does nothing by default.

Parameters ​

names ​

string[]

Returns ​

void

Inherited from ​

MutexDriver.onLost

Methods ​

acquire() ​

acquire(name, ttl): Promise<DriverLock | undefined>

Try to acquire a lock once: an advisory lock of the driver's connection, or a row inserted (or taken over when expired) in the table.

Parameters ​

name ​

string

The lock name.

ttl ​

number

How long the lock stays held without a renewal, in milliseconds (the table mode only).

Returns ​

Promise<DriverLock | undefined>

The lock (with a fencing token in the table mode), or undefined when another holder has it, this driver included.

Throws ​

When the package pg is not installed.

Overrides ​

MutexDriver.acquire


close() ​

close(): Promise<void>

Close the connection (PostgreSQL releases its advisory locks) and the pool; the rows of the table mode stay until they expire.

Returns ​

Promise<void>

Overrides ​

MutexDriver.close


extend() ​

extend(name, lock, ttl): Promise<boolean>

Renew a lock: in the table mode, push back the expiration of its row when it still holds this holder's token; in the advisory mode, check that the driver still holds it on its connection, by a query (a connection cut without notice fails it).

Parameters ​

name ​

string

The lock name.

lock ​

DriverLock

The lock acquired.

ttl ​

number

How long the lock stays held without another renewal, in milliseconds (the table mode only).

Returns ​

Promise<boolean>

Whether the lock is still held by this holder.

Overrides ​

MutexDriver.extend


release() ​

release(name, lock): Promise<boolean>

Release a lock still held by this holder: unlock the advisory lock, or delete the row.

Parameters ​

name ​

string

The lock name.

lock ​

DriverLock

The lock acquired.

Returns ​

Promise<boolean>

Whether it was released (false when the row expired and was taken, or the connection was lost).

Overrides ​

MutexDriver.release

Released under the MIT License.