@imqueue/pg-pubsub
Version:
Reliable PostgreSQL LISTEN/NOTIFY with inter-process lock support
166 lines (165 loc) • 5.17 kB
TypeScript
import { AnyLock } from './types';
import { PgIpLockOptions } from './types/PgIpLockOptions';
/**
* Implements manageable inter-process locking mechanism over
* existing PostgreSQL connection for a given `LISTEN` channel.
*
* It uses periodic locks acquire retries and implements graceful shutdown
* using `SIGINT`, `SIGTERM` and `SIGABRT` OS signals, by which safely releases
* an acquired lock, which causes an event to other similar running instances
* on another processes (or on another hosts) to capture free lock.
*
* By running inside Docker containers this would work flawlessly on
* implementation auto-scaling services, as docker destroys containers
* gracefully.
*
* Currently, the only known issue could happen only if, for example, database
* or software (or hardware) in the middle will cause a silent disconnect. For
* some period of time, despite the fact that there are other live potential
* listeners some messages can go into void. This time period can be tuned by
* bypassing wanted `acquireInterval` argument. By the way, take into account
* that too short period and number of running services may cause huge flood of
* lock acquire requests to a database, so selecting the proper number should be
* a thoughtful trade-off between overall system load and reliability level.
*
* Usually you do not need to instantiate this class directly - it will be done
* by a PgPubSub instances on their needs. Therefore, you may re-use this piece
* of code in some other implementations, so it is exported as is.
*/
export declare class PgIpLock implements AnyLock {
readonly channel: string;
readonly options: PgIpLockOptions;
readonly uniqueKey?: string | undefined;
/**
* DB lock schema name getter
*
* @return {string}
*/
get schemaName(): string;
/**
* Calls destroy() on all created instances at a time
*
* @return {Promise<void>}
*/
static destroy(): Promise<void>;
/**
* Returns true if at least one instance was created, false - otherwise
*
* @return {boolean}
*/
static hasInstances(): boolean;
private static instances;
private acquired;
private notifyHandler;
private acquireTimer?;
/**
* @constructor
* @param {string} channel - source channel name to manage locking on
* @param {PgIpLockOptions} options - lock instantiate options
* @param {string} [uniqueKey] - unique key for specific message
*/
constructor(channel: string, options: PgIpLockOptions, uniqueKey?: string | undefined);
/**
* Initializes inter-process locks storage in database and starts
* listening of lock release events, as well as initializes lock
* acquire retry timer.
*
* @return {Promise<void>}
*/
init(): Promise<void>;
/**
* This would provide release handler which will be called once the
* lock is released and the channel name would be bypassed to a given
* handler
*
* @param {(channel: string) => void} handler
*/
onRelease(handler: (channel: string) => void): void;
/**
* Acquires a lock on the current channel. Returns true on success,
* false - otherwise
*
* @return {Promise<boolean>}
*/
acquire(): Promise<boolean>;
/**
* Returns true if lock schema exists, false - otherwise
*
* @return {Promise<boolean>}
*/
private schemaExists;
/**
* Acquires a lock with ID
*
* @return {Promise<void>}
*/
private acquireUniqueLock;
/**
* Acquires a lock by unique channel
*
* @return {Promise<void>}
*/
private acquireChannelLock;
/**
* Releases acquired lock on this channel. After lock is released, another
* running process or host would be able to acquire the lock.
*
* @return {Promise<void>}
*/
release(): Promise<void>;
/**
* Returns current lock state, true if acquired, false - otherwise.
*
* @return {boolean}
*/
isAcquired(): boolean;
/**
* Destroys this lock properly.
*
* @return {Promise<void>}
*/
destroy(): Promise<void>;
/**
* Starts listening lock release channel
*
* @return {Promise<void>}
*/
private listen;
/**
* Stops listening lock release channel
*
* @return {Promise<void>}
*/
private unlisten;
/**
* Creates lock db schema
*
* @return {Promise<void>}
*/
private createSchema;
/**
* Creates lock table with delete trigger, which notifies on record removal
*
* @return {Promise<void>}
*/
private createLock;
/**
* Creates unique locks by IDs in the database
*
* @return {Promise<void>}
*/
private createUniqueLock;
/**
* Creates locks by channel names in the database
*
* @return {Promise<void>}
*/
private createChannelLock;
/**
* Creates deadlocks check routine used on lock acquaintance
*
* @return {Promise<void>}
*/
private createDeadlockCheck;
}
export declare const RX_LOCK_CHANNEL: RegExp;