pub struct PgAdvisoryLock { /* private fields */ }
Expand description

A mutex-like type utilizing Postgres advisory locks.

Advisory locks are a mechanism provided by Postgres to have mutually exclusive or shared locks tracked in the database with application-defined semantics, as opposed to the standard row-level or table-level locks which may not fit all use-cases.

This API provides a convenient wrapper for generating and storing the integer keys that advisory locks use, as well as RAII guards for releasing advisory locks when they fall out of scope.

This API only handles session-scoped advisory locks (explicitly locked and unlocked, or automatically released when a connection is closed).

It is also possible to use transaction-scoped locks but those can be used by beginning a transaction and calling the appropriate lock functions (e.g. SELECT pg_advisory_xact_lock()) manually, and cannot be explicitly released, but are automatically released when a transaction ends (is committed or rolled back).

Session-level locks can be acquired either inside or outside a transaction and are not tied to transaction semantics; a lock acquired inside a transaction is still held when that transaction is committed or rolled back, until explicitly released or the connection is closed.

Locks can be acquired in either shared or exclusive modes, which can be thought of as read locks and write locks, respectively. Multiple shared locks are allowed for the same key, but a single exclusive lock prevents any other lock being taken for a given key until it is released.

Implementations§

source§

impl PgAdvisoryLock

source

pub fn new(key_string: impl AsRef<str>) -> Self

Construct a PgAdvisoryLock using the given string as a key.

This is intended to make it easier to use an advisory lock by using a human-readable string for a key as opposed to manually generating a unique integer key. The generated integer key is guaranteed to be stable and in the single 64-bit integer keyspace (see PgAdvisoryLockKey for details).

This is done by applying the Hash-based Key Derivation Function (HKDF; IETF RFC 5869) to the bytes of the input string, but in a way that the calculated integer is unlikely to collide with any similar implementations (although we don’t currently know of any). See the source of this method for details.

Example
use sqlx::postgres::{PgAdvisoryLock, PgAdvisoryLockKey};

let lock = PgAdvisoryLock::new("my first Postgres advisory lock!");
// Negative values are fine because of how Postgres treats advisory lock keys.
// See the documentation for the `pg_locks` system view for details.
assert_eq!(lock.key(), &PgAdvisoryLockKey::BigInt(-5560419505042474287));
source

pub fn with_key(key: PgAdvisoryLockKey) -> Self

Construct a PgAdvisoryLock with a manually supplied key.

source

pub fn key(&self) -> &PgAdvisoryLockKey

Returns the current key.

source

pub async fn acquire<C: AsMut<PgConnection>>( &self, conn: C ) -> Result<PgAdvisoryLockGuard<'_, C>>

Acquires an exclusive lock using pg_advisory_lock(), waiting until the lock is acquired.

For a version that returns immediately instead of waiting, see Self::try_acquire().

A connection-like type is required to execute the call. Allowed types include PgConnection, PoolConnection<Postgres> and Transaction<Postgres>, as well as mutable references to any of these.

The returned guard queues a pg_advisory_unlock() call on the connection when dropped, which will be executed the next time the connection is used, or when returned to a PgPool in the case of PoolConnection<Postgres>.

Postgres allows a single connection to acquire a given lock more than once without releasing it first, so in that sense the lock is re-entrant. However, the number of unlock operations must match the number of lock operations for the lock to actually be released.

See Postgres’ documentation for the Advisory Lock Functions for details.

source

pub async fn try_acquire<C: AsMut<PgConnection>>( &self, conn: C ) -> Result<Either<PgAdvisoryLockGuard<'_, C>, C>>

Acquires an exclusive lock using pg_try_advisory_lock(), returning immediately if the lock could not be acquired.

For a version that waits until the lock is acquired, see Self::acquire().

A connection-like type is required to execute the call. Allowed types include PgConnection, PoolConnection<Postgres> and Transaction<Postgres>, as well as mutable references to any of these. The connection is returned if the lock could not be acquired.

The returned guard queues a pg_advisory_unlock() call on the connection when dropped, which will be executed the next time the connection is used, or when returned to a PgPool in the case of PoolConnection<Postgres>.

Postgres allows a single connection to acquire a given lock more than once without releasing it first, so in that sense the lock is re-entrant. However, the number of unlock operations must match the number of lock operations for the lock to actually be released.

See Postgres’ documentation for the Advisory Lock Functions for details.

source

pub async fn force_release<C: AsMut<PgConnection>>( &self, conn: C ) -> Result<(C, bool)>

Execute pg_advisory_unlock() for this lock’s key on the given connection.

This is used by PgAdvisoryLockGuard::release_now() and is also provided for manually releasing the lock from connections returned by PgAdvisoryLockGuard::leak().

An error should only be returned if there is something wrong with the connection, in which case the lock will be automatically released by the connection closing anyway.

The boolean value is that returned by pg_advisory_lock(). If it is false, it indicates that the lock was not actually held by the given connection and that a warning has been logged by the Postgres server.

Trait Implementations§

source§

impl Clone for PgAdvisoryLock

source§

fn clone(&self) -> PgAdvisoryLock

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for PgAdvisoryLock

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V