@@ -56,8 +56,10 @@ export class PgIpLock implements AnyLock {
5656 *
5757 * @return {string }
5858 */
59- public static get schemaName ( ) : string {
60- return ident ( SCHEMA_NAME ) ;
59+ public get schemaName ( ) : string {
60+ const suffix = this . uniqueKey ? '_unique' : '' ;
61+
62+ return ident ( SCHEMA_NAME + suffix ) ;
6163 }
6264
6365 /**
@@ -110,8 +112,10 @@ export class PgIpLock implements AnyLock {
110112 * @return {Promise<void> }
111113 */
112114 public async init ( ) : Promise < void > {
113- await this . createSchema ( ) ;
114- await Promise . all ( [ this . createLock ( ) , this . createDeadlockCheck ( ) ] ) ;
115+ if ( ! await this . schemaExists ( ) ) {
116+ await this . createSchema ( ) ;
117+ await Promise . all ( [ this . createLock ( ) , this . createDeadlockCheck ( ) ] ) ;
118+ }
115119
116120 if ( this . notifyHandler && ! this . uniqueKey ) {
117121 this . options . pgClient . on ( 'notification' , this . notifyHandler ) ;
@@ -184,6 +188,21 @@ export class PgIpLock implements AnyLock {
184188 return this . acquired ;
185189 }
186190
191+ /**
192+ * Returns true if lock schema exists, false - otherwise
193+ *
194+ * @return {Promise<boolean> }
195+ */
196+ private async schemaExists ( ) : Promise < boolean > {
197+ const { rows } = await this . options . pgClient . query ( `
198+ SELECT schema_name
199+ FROM information_schema.schemata
200+ WHERE schema_name = '${ this . schemaName } '
201+ ` ) ;
202+
203+ return ( rows . length > 0 ) ;
204+ }
205+
187206 /**
188207 * Acquires a lock with ID
189208 *
@@ -192,16 +211,15 @@ export class PgIpLock implements AnyLock {
192211 private async acquireUniqueLock ( ) : Promise < void > {
193212 // noinspection SqlResolve
194213 await this . options . pgClient . query ( `
195- INSERT INTO ${ PgIpLock . schemaName } .lock (id, channel, app)
214+ INSERT INTO ${ this . schemaName } .lock (id, channel, app)
196215 VALUES (
197216 ${ literal ( this . uniqueKey ) } ,
198217 ${ literal ( this . channel ) } ,
199218 ${ literal ( this . options . pgClient . appName ) }
200219 ) ON CONFLICT (id) DO
201- UPDATE SET app = ${ PgIpLock . schemaName } .deadlock_check(
202- ${ PgIpLock . schemaName } .lock.app,
203- ${ literal ( this . options . pgClient . appName ) } ,
204- NOW()
220+ UPDATE SET app = ${ this . schemaName } .deadlock_check(
221+ ${ this . schemaName } .lock.app,
222+ ${ literal ( this . options . pgClient . appName ) }
205223 )
206224 ` ) ;
207225 }
@@ -214,15 +232,14 @@ export class PgIpLock implements AnyLock {
214232 private async acquireChannelLock ( ) : Promise < void > {
215233 // noinspection SqlResolve
216234 await this . options . pgClient . query ( `
217- INSERT INTO ${ PgIpLock . schemaName } .lock (channel, app)
235+ INSERT INTO ${ this . schemaName } .lock (channel, app)
218236 VALUES (
219237 ${ literal ( this . channel ) } ,
220238 ${ literal ( this . options . pgClient . appName ) }
221239 ) ON CONFLICT (channel) DO
222- UPDATE SET app = ${ PgIpLock . schemaName } .deadlock_check(
223- ${ PgIpLock . schemaName } .lock.app,
224- ${ literal ( this . options . pgClient . appName ) } ,
225- NOW()
240+ UPDATE SET app = ${ this . schemaName } .deadlock_check(
241+ ${ this . schemaName } .lock.app,
242+ ${ literal ( this . options . pgClient . appName ) }
226243 )
227244 ` ) ;
228245 }
@@ -237,7 +254,7 @@ export class PgIpLock implements AnyLock {
237254 if ( this . uniqueKey ) {
238255 // noinspection SqlResolve
239256 await this . options . pgClient . query ( `
240- DELETE FROM ${ PgIpLock . schemaName } .lock
257+ DELETE FROM ${ this . schemaName } .lock
241258 WHERE id=${ literal ( this . uniqueKey ) }
242259 ` ) ;
243260 } else {
@@ -247,7 +264,7 @@ export class PgIpLock implements AnyLock {
247264
248265 // noinspection SqlResolve
249266 await this . options . pgClient . query ( `
250- DELETE FROM ${ PgIpLock . schemaName } .lock
267+ DELETE FROM ${ this . schemaName } .lock
251268 WHERE channel=${ literal ( this . channel ) }
252269 ` ) ;
253270 }
@@ -319,7 +336,7 @@ export class PgIpLock implements AnyLock {
319336 */
320337 private async createSchema ( ) : Promise < void > {
321338 await this . options . pgClient . query ( `
322- CREATE SCHEMA IF NOT EXISTS ${ PgIpLock . schemaName }
339+ CREATE SCHEMA IF NOT EXISTS ${ this . schemaName }
323340 ` ) ;
324341 }
325342
@@ -351,25 +368,25 @@ export class PgIpLock implements AnyLock {
351368 IF NOT EXISTS (
352369 SELECT *
353370 FROM information_schema.columns
354- WHERE table_schema = '${ PgIpLock . schemaName } '
371+ WHERE table_schema = '${ this . schemaName } '
355372 AND table_name = 'lock'
356373 AND column_name = 'id'
357374 ) THEN
358- DROP TABLE IF EXISTS ${ PgIpLock . schemaName } .lock;
375+ DROP TABLE IF EXISTS ${ this . schemaName } .lock;
359376 END IF;
360377 END
361378 $$
362379 ` ) ;
363380 await this . options . pgClient . query ( `
364- CREATE TABLE IF NOT EXISTS ${ PgIpLock . schemaName } ."lock" (
381+ CREATE TABLE IF NOT EXISTS ${ this . schemaName } ."lock" (
365382 "id" CHARACTER VARYING NOT NULL PRIMARY KEY,
366383 "channel" CHARACTER VARYING NOT NULL,
367384 "app" CHARACTER VARYING NOT NULL
368385 )
369386 ` ) ;
370387 await this . options . pgClient . query ( `
371388 DROP TRIGGER IF EXISTS notify_release_lock_trigger
372- ON ${ PgIpLock . schemaName } .lock
389+ ON ${ this . schemaName } .lock
373390 ` ) ;
374391 }
375392
@@ -385,40 +402,40 @@ export class PgIpLock implements AnyLock {
385402 IF EXISTS (
386403 SELECT *
387404 FROM information_schema.columns
388- WHERE table_schema = '${ PgIpLock . schemaName } '
405+ WHERE table_schema = '${ this . schemaName } '
389406 AND table_name = 'lock'
390407 AND column_name = 'id'
391408 ) THEN
392- DROP TABLE IF EXISTS ${ PgIpLock . schemaName } .lock;
409+ DROP TABLE IF EXISTS ${ this . schemaName } .lock;
393410 END IF;
394411 END
395412 $$
396413 ` ) ;
397414 await this . options . pgClient . query ( `
398- CREATE TABLE IF NOT EXISTS ${ PgIpLock . schemaName } ."lock" (
415+ CREATE TABLE IF NOT EXISTS ${ this . schemaName } ."lock" (
399416 "channel" CHARACTER VARYING NOT NULL PRIMARY KEY,
400417 "app" CHARACTER VARYING NOT NULL
401418 )
402419 ` ) ;
403420 // noinspection SqlResolve
404421 await this . options . pgClient . query ( `
405- CREATE OR REPLACE FUNCTION ${ PgIpLock . schemaName } .notify_lock()
422+ CREATE OR REPLACE FUNCTION ${ this . schemaName } .notify_lock()
406423 RETURNS TRIGGER LANGUAGE PLPGSQL AS $$
407424 BEGIN PERFORM PG_NOTIFY(OLD.channel, '1'); RETURN OLD; END; $$
408425 ` ) ;
409426
410427 await this . options . pgClient . query ( `
411428 DROP TRIGGER IF EXISTS notify_release_lock_trigger
412- ON ${ PgIpLock . schemaName } .lock
429+ ON ${ this . schemaName } .lock
413430 ` ) ;
414431
415432 try {
416433 await this . options . pgClient . query ( `
417434 CREATE CONSTRAINT TRIGGER notify_release_lock_trigger
418- AFTER DELETE ON ${ PgIpLock . schemaName } .lock
435+ AFTER DELETE ON ${ this . schemaName } .lock
419436 DEFERRABLE INITIALLY DEFERRED
420437 FOR EACH ROW EXECUTE PROCEDURE ${
421- PgIpLock . schemaName } .notify_lock()
438+ this . schemaName } .notify_lock()
422439 ` ) ;
423440 } catch ( e ) {
424441 /*ignore*/
@@ -432,10 +449,9 @@ export class PgIpLock implements AnyLock {
432449 */
433450 private async createDeadlockCheck ( ) : Promise < void > {
434451 await this . options . pgClient . query ( `
435- CREATE OR REPLACE FUNCTION ${ PgIpLock . schemaName } .deadlock_check(
452+ CREATE OR REPLACE FUNCTION ${ this . schemaName } .deadlock_check(
436453 old_app TEXT,
437- new_app TEXT,
438- call_time TIMESTAMP WITH TIME ZONE
454+ new_app TEXT
439455 )
440456 RETURNS TEXT LANGUAGE PLPGSQL AS $$
441457 DECLARE num_apps INTEGER;
0 commit comments