UNPKG

@imqueue/pg-pubsub

Version:

Reliable PostgreSQL LISTEN/NOTIFY with inter-process lock support

166 lines (165 loc) 5.17 kB
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;