prostgles-server 4.2.79 → 4.2.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PubSubManager/getInitQuery.d.ts +5 -1
- package/dist/PubSubManager/getInitQuery.d.ts.map +1 -1
- package/dist/PubSubManager/getInitQuery.js +48 -30
- package/dist/PubSubManager/getInitQuery.js.map +1 -1
- package/dist/PubSubManager/initPubSubManager.d.ts +1 -0
- package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/initPubSubManager.js +33 -3
- package/dist/PubSubManager/initPubSubManager.js.map +1 -1
- package/lib/PubSubManager/getInitQuery.ts +50 -31
- package/lib/PubSubManager/initPubSubManager.ts +35 -3
- package/package.json +1 -1
- package/tests/server/package-lock.json +5 -5
|
@@ -5,5 +5,9 @@ export declare const DB_OBJ_NAMES: {
|
|
|
5
5
|
readonly schema_watch_func: "prostgles.schema_watch_func";
|
|
6
6
|
readonly schema_watch_trigger: "prostgles_schema_watch_trigger_new";
|
|
7
7
|
};
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Initialize the prostgles schema and functions needed for realtime data and schema changes
|
|
10
|
+
* undefined returned if the database contains the apropriate prostgles schema
|
|
11
|
+
*/
|
|
12
|
+
export declare const getPubSubManagerInitQuery: (this: PubSubManager) => Promise<string | undefined>;
|
|
9
13
|
//# sourceMappingURL=getInitQuery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getInitQuery.d.ts","sourceRoot":"","sources":["../../lib/PubSubManager/getInitQuery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getInitQuery.d.ts","sourceRoot":"","sources":["../../lib/PubSubManager/getInitQuery.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsC,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIpF,eAAO,MAAM,YAAY;;;;;CAKf,CAAC;AAqkBX;;;GAGG;AACH,eAAO,MAAM,yBAAyB,SAAwB,aAAa,KAAG,QAAQ,MAAM,GAAG,SAAS,CAoBvG,CAAA"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getPubSubManagerInitQuery = exports.DB_OBJ_NAMES = void 0;
|
|
4
|
+
const prostgles_types_1 = require("prostgles-types");
|
|
5
|
+
const DboBuilderTypes_1 = require("../DboBuilder/DboBuilderTypes");
|
|
4
6
|
const PubSubManager_1 = require("./PubSubManager");
|
|
5
7
|
const { version } = require("../../package.json");
|
|
6
8
|
const orphanTriggerCheck_1 = require("./orphanTriggerCheck");
|
|
@@ -10,12 +12,22 @@ exports.DB_OBJ_NAMES = {
|
|
|
10
12
|
schema_watch_func: "prostgles.schema_watch_func",
|
|
11
13
|
schema_watch_trigger: "prostgles_schema_watch_trigger_new"
|
|
12
14
|
};
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const PROSTGLES_SCHEMA_EXISTS_QUERY = `
|
|
16
|
+
SELECT 1
|
|
17
|
+
FROM information_schema.columns
|
|
18
|
+
WHERE table_schema = 'prostgles'
|
|
19
|
+
AND table_name = 'versions'
|
|
20
|
+
AND column_name = 'schema_md5'
|
|
21
|
+
`;
|
|
22
|
+
const PROSTGLES_SCHEMA_VERSION_OK_QUERY = `
|
|
23
|
+
SELECT 1
|
|
24
|
+
FROM prostgles.versions
|
|
25
|
+
WHERE (string_to_array(version, '.')::int[] > string_to_array(\${version}, '.')::int[])
|
|
26
|
+
OR (string_to_array(version, '.')::int[] = string_to_array(\${version}, '.')::int[])
|
|
27
|
+
AND schema_md5 = \${schema_md5}
|
|
28
|
+
`;
|
|
29
|
+
const getInitQuery = (debugMode) => `
|
|
30
|
+
BEGIN; -- TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
|
19
31
|
|
|
20
32
|
--SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
|
21
33
|
|
|
@@ -27,9 +39,6 @@ DO
|
|
|
27
39
|
$do$
|
|
28
40
|
BEGIN
|
|
29
41
|
|
|
30
|
-
/* Reduce deadlocks */
|
|
31
|
-
PERFORM pg_sleep(random());
|
|
32
|
-
|
|
33
42
|
/* Drop older version. */
|
|
34
43
|
IF EXISTS (SELECT 1 FROM information_schema.schemata WHERE schema_name = 'prostgles') THEN
|
|
35
44
|
|
|
@@ -37,23 +46,14 @@ BEGIN
|
|
|
37
46
|
IF
|
|
38
47
|
/* Backwards compatibility. Cannot check schema version */
|
|
39
48
|
NOT EXISTS(
|
|
40
|
-
|
|
41
|
-
FROM information_schema.columns
|
|
42
|
-
WHERE table_schema = 'prostgles'
|
|
43
|
-
AND table_name = 'versions'
|
|
44
|
-
AND column_name = 'schema_md5'
|
|
49
|
+
${PROSTGLES_SCHEMA_EXISTS_QUERY}
|
|
45
50
|
)
|
|
46
51
|
THEN
|
|
47
52
|
DROP SCHEMA IF EXISTS prostgles CASCADE;
|
|
48
53
|
ELSIF
|
|
49
54
|
/* There is no newer version or same same version but different schema */
|
|
50
55
|
NOT EXISTS (
|
|
51
|
-
|
|
52
|
-
FROM prostgles.versions
|
|
53
|
-
WHERE
|
|
54
|
-
(string_to_array(version, '.')::int[] > string_to_array(${(0, PubSubManager_1.asValue)(version)}, '.')::int[])
|
|
55
|
-
OR (string_to_array(version, '.')::int[] = string_to_array(${(0, PubSubManager_1.asValue)(version)}, '.')::int[])
|
|
56
|
-
AND schema_md5 = ${(0, PubSubManager_1.asValue)(schema_md5)}
|
|
56
|
+
${PROSTGLES_SCHEMA_VERSION_OK_QUERY}
|
|
57
57
|
)
|
|
58
58
|
THEN
|
|
59
59
|
DROP SCHEMA IF EXISTS prostgles CASCADE;
|
|
@@ -81,7 +81,7 @@ BEGIN
|
|
|
81
81
|
COMMENT ON TABLE prostgles.versions IS 'Stores the prostgles schema creation query hash and package version number to identify when a newer schema needs to be re-created';
|
|
82
82
|
|
|
83
83
|
INSERT INTO prostgles.versions(version, schema_md5)
|
|
84
|
-
VALUES(${(0, PubSubManager_1.asValue)(version)},
|
|
84
|
+
VALUES(${(0, PubSubManager_1.asValue)(version)}, \${schema_md5})
|
|
85
85
|
ON CONFLICT DO NOTHING;
|
|
86
86
|
|
|
87
87
|
|
|
@@ -305,7 +305,7 @@ BEGIN
|
|
|
305
305
|
THEN concat_ws('; ', 'error', err_text, err_detail, err_hint, 'query: ' || query )
|
|
306
306
|
ELSE COALESCE(v_trigger.cids, '')
|
|
307
307
|
END
|
|
308
|
-
${
|
|
308
|
+
${debugMode ? (", COALESCE(current_query(), 'current_query ??'), ' ', query") : ""}
|
|
309
309
|
), 7999/4) -- Some chars are 2bytes -> 'Ω'
|
|
310
310
|
);
|
|
311
311
|
END LOOP;
|
|
@@ -504,7 +504,7 @@ BEGIN
|
|
|
504
504
|
json_build_object(
|
|
505
505
|
'TG_OP', TG_OP,
|
|
506
506
|
'duration', (EXTRACT(EPOCH FROM now()) * 1000) - start_time,
|
|
507
|
-
'query', ${
|
|
507
|
+
'query', ${debugMode ? 'LEFT(current_query(), 400)' : "'Only shown in debug mode'"}
|
|
508
508
|
)
|
|
509
509
|
)::TEXT, 7999/4)
|
|
510
510
|
);
|
|
@@ -566,7 +566,7 @@ BEGIN
|
|
|
566
566
|
${(0, PubSubManager_1.asValue)(PubSubManager_1.NOTIF_TYPE.schema)},
|
|
567
567
|
tg_tag ,
|
|
568
568
|
TG_event,
|
|
569
|
-
${
|
|
569
|
+
${debugMode ? 'curr_query' : "'Only shown in debug mode'"}
|
|
570
570
|
), 7999/4)
|
|
571
571
|
);
|
|
572
572
|
END LOOP;
|
|
@@ -587,12 +587,30 @@ BEGIN
|
|
|
587
587
|
END
|
|
588
588
|
$do$;
|
|
589
589
|
|
|
590
|
-
|
|
591
590
|
COMMIT;
|
|
592
591
|
`;
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
592
|
+
/**
|
|
593
|
+
* Initialize the prostgles schema and functions needed for realtime data and schema changes
|
|
594
|
+
* undefined returned if the database contains the apropriate prostgles schema
|
|
595
|
+
*/
|
|
596
|
+
const getPubSubManagerInitQuery = async function () {
|
|
597
|
+
const initQuery = getInitQuery(this.dboBuilder.prostgles.opts.DEBUG_MODE);
|
|
598
|
+
const { schema_md5 = "none" } = await this.db.oneOrNone("SELECT md5($1) as schema_md5", [initQuery.trim()]);
|
|
599
|
+
const query = DboBuilderTypes_1.pgp.as.format(initQuery, { schema_md5, version });
|
|
600
|
+
const existingSchema = await this.db.any(PROSTGLES_SCHEMA_EXISTS_QUERY);
|
|
601
|
+
if (!existingSchema.length) {
|
|
602
|
+
return query;
|
|
603
|
+
}
|
|
604
|
+
const { existingSchemaVersions } = await (0, prostgles_types_1.tryCatch)(async () => {
|
|
605
|
+
const existingSchemaVersions = await this.db.any(PROSTGLES_SCHEMA_VERSION_OK_QUERY, { schema_md5, version });
|
|
606
|
+
return {
|
|
607
|
+
existingSchemaVersions
|
|
608
|
+
};
|
|
609
|
+
});
|
|
610
|
+
if (!existingSchemaVersions?.length) {
|
|
611
|
+
return query;
|
|
612
|
+
}
|
|
613
|
+
return undefined;
|
|
596
614
|
};
|
|
597
|
-
exports.
|
|
615
|
+
exports.getPubSubManagerInitQuery = getPubSubManagerInitQuery;
|
|
598
616
|
//# sourceMappingURL=getInitQuery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getInitQuery.js","sourceRoot":"","sources":["../../lib/PubSubManager/getInitQuery.ts"],"names":[],"mappings":";;;AACA,mDAAoF;AACpF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAClD,6DAAwD;AAE3C,QAAA,YAAY,GAAG;IAC1B,uBAAuB,EAAE,mCAAmC;IAC5D,eAAe,EAAE,sCAAsC;IACvD,iBAAiB,EAAE,6BAA6B;IAChD,oBAAoB,EAAE,oCAAoC;CAClD,CAAC;
|
|
1
|
+
{"version":3,"file":"getInitQuery.js","sourceRoot":"","sources":["../../lib/PubSubManager/getInitQuery.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PubSubManager } from "./PubSubManager";
|
|
2
2
|
export declare const REALTIME_TRIGGER_CHECK_QUERY: "prostgles-server internal query used to manage realtime triggers";
|
|
3
|
+
export declare const tout: (ms: number) => Promise<unknown>;
|
|
3
4
|
export declare function initPubSubManager(this: PubSubManager): Promise<PubSubManager | undefined>;
|
|
4
5
|
//# sourceMappingURL=initPubSubManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initPubSubManager.d.ts","sourceRoot":"","sources":["../../lib/PubSubManager/initPubSubManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initPubSubManager.d.ts","sourceRoot":"","sources":["../../lib/PubSubManager/initPubSubManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,aAAa,EAAW,MAAM,iBAAiB,CAAC;AAExE,eAAO,MAAM,4BAA4B,oEAA8E,CAAC;AAExH,eAAO,MAAM,IAAI,OAAQ,MAAM,qBAA4C,CAAC;AAE5E,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAsM/F"}
|
|
@@ -1,17 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.initPubSubManager = exports.REALTIME_TRIGGER_CHECK_QUERY = void 0;
|
|
3
|
+
exports.initPubSubManager = exports.tout = exports.REALTIME_TRIGGER_CHECK_QUERY = void 0;
|
|
4
|
+
const prostgles_types_1 = require("prostgles-types");
|
|
4
5
|
const PostgresNotifListenManager_1 = require("../PostgresNotifListenManager");
|
|
5
6
|
const getWatchSchemaTagList_1 = require("../SchemaWatch/getWatchSchemaTagList");
|
|
6
7
|
const PubSubManager_1 = require("./PubSubManager");
|
|
7
8
|
const getInitQuery_1 = require("./getInitQuery");
|
|
8
9
|
exports.REALTIME_TRIGGER_CHECK_QUERY = "prostgles-server internal query used to manage realtime triggers";
|
|
10
|
+
const tout = (ms) => new Promise(res => setTimeout(res, ms));
|
|
11
|
+
exports.tout = tout;
|
|
9
12
|
async function initPubSubManager() {
|
|
10
13
|
if (!this.getIsDestroyed())
|
|
11
14
|
return undefined;
|
|
12
15
|
try {
|
|
13
|
-
const initQuery = await getInitQuery_1.
|
|
14
|
-
|
|
16
|
+
const initQuery = await getInitQuery_1.getPubSubManagerInitQuery.bind(this)();
|
|
17
|
+
/**
|
|
18
|
+
* High database activity might cause deadlocks.
|
|
19
|
+
* Must retry
|
|
20
|
+
*/
|
|
21
|
+
let didDeadlock = false;
|
|
22
|
+
let tries = 3;
|
|
23
|
+
let error;
|
|
24
|
+
while ((0, prostgles_types_1.isDefined)(initQuery) && tries > 0) {
|
|
25
|
+
try {
|
|
26
|
+
/** Try to reduce race condition deadlocks due to multiple clients connecting at the same time */
|
|
27
|
+
await (0, exports.tout)(Math.random());
|
|
28
|
+
await this.db.any(initQuery);
|
|
29
|
+
error = undefined;
|
|
30
|
+
tries = 0;
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
if (!didDeadlock && (0, prostgles_types_1.isObject)(e) && e.code === "40P01") {
|
|
34
|
+
didDeadlock = true;
|
|
35
|
+
tries = 5;
|
|
36
|
+
console.error("Deadlock detected. Retrying...");
|
|
37
|
+
}
|
|
38
|
+
error = e;
|
|
39
|
+
tries--;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (error) {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
15
45
|
if (!this.getIsDestroyed())
|
|
16
46
|
return;
|
|
17
47
|
/* Prepare App id */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initPubSubManager.js","sourceRoot":"","sources":["../../lib/PubSubManager/initPubSubManager.ts"],"names":[],"mappings":";;;AAAA,8EAA2E;AAC3E,gFAA6E;AAC7E,mDAAwE;AACxE,
|
|
1
|
+
{"version":3,"file":"initPubSubManager.js","sourceRoot":"","sources":["../../lib/PubSubManager/initPubSubManager.ts"],"names":[],"mappings":";;;AAAA,qDAAsD;AACtD,8EAA2E;AAC3E,gFAA6E;AAC7E,mDAAwE;AACxE,iDAA2D;AAC9C,QAAA,4BAA4B,GAAG,kEAA2E,CAAC;AAEjH,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AAA/D,QAAA,IAAI,QAA2D;AAErE,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;QAAE,OAAO,SAAS,CAAC;IAE7C,IAAI,CAAC;QAEH,MAAM,SAAS,GAAG,MAAM,wCAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAE/D;;;UAGE;QACF,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,KAAU,CAAC;QACf,OAAO,IAAA,2BAAS,EAAC,SAAS,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,iGAAiG;gBACjG,MAAM,IAAA,YAAI,EAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBAE1B,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC7B,KAAK,GAAG,SAAS,CAAC;gBAClB,KAAK,GAAG,CAAC,CAAC;YACZ,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,IAAG,CAAC,WAAW,IAAI,IAAA,0BAAQ,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAC,CAAC;oBACpD,WAAW,GAAG,IAAI,CAAC;oBACnB,KAAK,GAAG,CAAC,CAAC;oBACV,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBAClD,CAAC;gBACD,KAAK,GAAG,CAAC,CAAC;gBACV,KAAK,EAAG,CAAC;YACX,CAAC;QACH,CAAC;QACD,IAAG,KAAK,EAAC,CAAC;YACR,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YAAE,OAAO;QAEnC,oBAAoB;QACpB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAC/B,MAAM,kBAAkB,GAAG,IAAI,CAAC,mBAAmB,CAAC;YACpD,MAAM,yBAAyB,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,IAAA,6CAAqB,EAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC9K,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACf;;sBAEc,EACZ;gBACA,IAAI,CAAC,KAAK;gBACV,kBAAkB;gBAClB,yBAAyB;aAC1B,CACF,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,4CAA4C,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAChG,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpE,MAAM,+EAA+E,IAAI,CAAC,KAAK,aAAa,CAAC;YAC/G,CAAC;YAED,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;;yBAEC,IAAA,uBAAO,EAAC,IAAI,CAAC,KAAK,CAAC;OACrC,CAAC,CAAC;YAEH,4CAA4C;YAC5C,8CAA8C;YAE9C,8CAA8C;YAC9C,sCAAsC;YACtC,YAAY;YAEZ,iCAAiC;YAEjC,qDAAqD;YACrD,2EAA2E;YAC3E,wCAAwC;YACxC,iEAAiE;YACjE,wGAAwG;YACxG,0CAA0C;YAC1C,iDAAiD;YACjD,WAAW;YAEX,+FAA+F;YAC/F,wCAAwC;YACxC,qGAAqG;YACrG,oEAAoE;YACpE,oCAAoC;YACpC,yDAAyD;YACzD,+DAA+D;YAE/D,iBAAiB;YAEjB,4CAA4C;YAC5C,8EAA8E;YAE9E,qDAAqD;YACrD,oDAAoD;YAEpD,yGAAyG;YACzG,qDAAqD;YACrD,wDAAwD;YACxD,2IAA2I;YAC3I,mBAAmB;YAEnB,oBAAoB;YAEpB,YAAY;YACZ,UAAU;YAEV,uHAAuH;YACvH,4DAA4D;YAC5D,gBAAgB;YAChB,gBAAgB;YAChB,gBAAgB;YAChB,iCAAiC;YACjC,+CAA+C;YAC/C,kEAAkE;YAClE,eAAe;YACf,8CAA8C;YAC9C,eAAe;YACf,uBAAuB;YACvB,0BAA0B;YAC1B,gDAAgD;YAChD,kDAAkD;YAClD,6CAA6C;YAC7C,gBAAgB;YAChB,iBAAiB;YAEjB,kEAAkE;YAClE,uCAAuC;YACvC,uCAAuC;YACvC,mDAAmD;YAEnD,yCAAyC;YACzC,oBAAoB;YAEpB,mBAAmB;YAEnB,0FAA0F;YAC1F,2CAA2C;YAC3C,4BAA4B;YAC5B,cAAc;YACd,+BAA+B;YAC/B,4CAA4C;YAC5C,gEAAgE;YAChE,aAAa;YACb,iBAAiB;YACjB,gBAAgB;YAChB,gEAAgE;YAChE,2CAA2C;YAC3C,6CAA6C;YAC7C,0CAA0C;YAC1C,6CAA6C;YAC7C,kBAAkB;YAClB,oDAAoD;YACpD,gCAAgC;YAChC,kDAAkD;YAClD,+BAA+B;YAE/B,mBAAmB;YACnB,mCAAmC;YACnC,yBAAyB;YACzB,kBAAkB;YAElB,qGAAqG;YACrG,qBAAqB;YACrB,2EAA2E;YAC3E,sCAAsC;YACtC,2CAA2C;YAC3C,uDAAuD;YACvD,WAAW;YAEX,6BAA6B;YAC7B,cAAc;YACd,yCAAyC;YACzC,YAAY;YACZ,+BAA+B;YAC/B,cAAc;YACd,+FAA+F;YAC/F,wCAAwC;YACxC,UAAU;YACV,wEAAwE;YACxE,QAAQ;YAER,gCAAgC;YAChC,wCAAwC;YACxC,IAAI;QACN,CAAC;QAED,IAAI,CAAC,0BAA0B,GAAG,IAAI,uDAA0B,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,aAAa,EAAE,6BAAa,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAEjI,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAErC,OAAO,IAAI,CAAC;IAEd,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAtMD,8CAsMC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
|
|
2
|
+
import { tryCatch } from "prostgles-types";
|
|
3
|
+
import { pgp } from "../DboBuilder/DboBuilderTypes";
|
|
2
4
|
import { asValue, NOTIF_CHANNEL, NOTIF_TYPE, PubSubManager } from "./PubSubManager";
|
|
3
5
|
const { version } = require("../../package.json");
|
|
4
6
|
import { getAppCheckQuery } from "./orphanTriggerCheck";
|
|
@@ -10,14 +12,23 @@ export const DB_OBJ_NAMES = {
|
|
|
10
12
|
schema_watch_trigger: "prostgles_schema_watch_trigger_new"
|
|
11
13
|
} as const;
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
const PROSTGLES_SCHEMA_EXISTS_QUERY = `
|
|
16
|
+
SELECT 1
|
|
17
|
+
FROM information_schema.columns
|
|
18
|
+
WHERE table_schema = 'prostgles'
|
|
19
|
+
AND table_name = 'versions'
|
|
20
|
+
AND column_name = 'schema_md5'
|
|
21
|
+
`;
|
|
22
|
+
const PROSTGLES_SCHEMA_VERSION_OK_QUERY = `
|
|
23
|
+
SELECT 1
|
|
24
|
+
FROM prostgles.versions
|
|
25
|
+
WHERE (string_to_array(version, '.')::int[] > string_to_array(\${version}, '.')::int[])
|
|
26
|
+
OR (string_to_array(version, '.')::int[] = string_to_array(\${version}, '.')::int[])
|
|
27
|
+
AND schema_md5 = \${schema_md5}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const getInitQuery = (debugMode: boolean | undefined) => `
|
|
31
|
+
BEGIN; -- TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
|
21
32
|
|
|
22
33
|
--SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
|
23
34
|
|
|
@@ -29,9 +40,6 @@ DO
|
|
|
29
40
|
$do$
|
|
30
41
|
BEGIN
|
|
31
42
|
|
|
32
|
-
/* Reduce deadlocks */
|
|
33
|
-
PERFORM pg_sleep(random());
|
|
34
|
-
|
|
35
43
|
/* Drop older version. */
|
|
36
44
|
IF EXISTS (SELECT 1 FROM information_schema.schemata WHERE schema_name = 'prostgles') THEN
|
|
37
45
|
|
|
@@ -39,23 +47,14 @@ BEGIN
|
|
|
39
47
|
IF
|
|
40
48
|
/* Backwards compatibility. Cannot check schema version */
|
|
41
49
|
NOT EXISTS(
|
|
42
|
-
|
|
43
|
-
FROM information_schema.columns
|
|
44
|
-
WHERE table_schema = 'prostgles'
|
|
45
|
-
AND table_name = 'versions'
|
|
46
|
-
AND column_name = 'schema_md5'
|
|
50
|
+
${PROSTGLES_SCHEMA_EXISTS_QUERY}
|
|
47
51
|
)
|
|
48
52
|
THEN
|
|
49
53
|
DROP SCHEMA IF EXISTS prostgles CASCADE;
|
|
50
54
|
ELSIF
|
|
51
55
|
/* There is no newer version or same same version but different schema */
|
|
52
56
|
NOT EXISTS (
|
|
53
|
-
|
|
54
|
-
FROM prostgles.versions
|
|
55
|
-
WHERE
|
|
56
|
-
(string_to_array(version, '.')::int[] > string_to_array(${asValue(version)}, '.')::int[])
|
|
57
|
-
OR (string_to_array(version, '.')::int[] = string_to_array(${asValue(version)}, '.')::int[])
|
|
58
|
-
AND schema_md5 = ${asValue(schema_md5)}
|
|
57
|
+
${PROSTGLES_SCHEMA_VERSION_OK_QUERY}
|
|
59
58
|
)
|
|
60
59
|
THEN
|
|
61
60
|
DROP SCHEMA IF EXISTS prostgles CASCADE;
|
|
@@ -83,7 +82,7 @@ BEGIN
|
|
|
83
82
|
COMMENT ON TABLE prostgles.versions IS 'Stores the prostgles schema creation query hash and package version number to identify when a newer schema needs to be re-created';
|
|
84
83
|
|
|
85
84
|
INSERT INTO prostgles.versions(version, schema_md5)
|
|
86
|
-
VALUES(${asValue(version)},
|
|
85
|
+
VALUES(${asValue(version)}, \${schema_md5})
|
|
87
86
|
ON CONFLICT DO NOTHING;
|
|
88
87
|
|
|
89
88
|
|
|
@@ -307,7 +306,7 @@ BEGIN
|
|
|
307
306
|
THEN concat_ws('; ', 'error', err_text, err_detail, err_hint, 'query: ' || query )
|
|
308
307
|
ELSE COALESCE(v_trigger.cids, '')
|
|
309
308
|
END
|
|
310
|
-
${
|
|
309
|
+
${debugMode? (", COALESCE(current_query(), 'current_query ??'), ' ', query") : ""}
|
|
311
310
|
), 7999/4) -- Some chars are 2bytes -> 'Ω'
|
|
312
311
|
);
|
|
313
312
|
END LOOP;
|
|
@@ -506,7 +505,7 @@ BEGIN
|
|
|
506
505
|
json_build_object(
|
|
507
506
|
'TG_OP', TG_OP,
|
|
508
507
|
'duration', (EXTRACT(EPOCH FROM now()) * 1000) - start_time,
|
|
509
|
-
'query', ${
|
|
508
|
+
'query', ${debugMode? 'LEFT(current_query(), 400)' : "'Only shown in debug mode'"}
|
|
510
509
|
)
|
|
511
510
|
)::TEXT, 7999/4)
|
|
512
511
|
);
|
|
@@ -568,7 +567,7 @@ BEGIN
|
|
|
568
567
|
${asValue(NOTIF_TYPE.schema)},
|
|
569
568
|
tg_tag ,
|
|
570
569
|
TG_event,
|
|
571
|
-
${
|
|
570
|
+
${debugMode? 'curr_query' : "'Only shown in debug mode'"}
|
|
572
571
|
), 7999/4)
|
|
573
572
|
);
|
|
574
573
|
END LOOP;
|
|
@@ -589,11 +588,31 @@ BEGIN
|
|
|
589
588
|
END
|
|
590
589
|
$do$;
|
|
591
590
|
|
|
592
|
-
|
|
593
591
|
COMMIT;
|
|
594
|
-
`
|
|
595
|
-
|
|
596
|
-
|
|
592
|
+
`
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Initialize the prostgles schema and functions needed for realtime data and schema changes
|
|
596
|
+
* undefined returned if the database contains the apropriate prostgles schema
|
|
597
|
+
*/
|
|
598
|
+
export const getPubSubManagerInitQuery = async function(this: PubSubManager): Promise<string | undefined> {
|
|
599
|
+
|
|
600
|
+
const initQuery = getInitQuery(this.dboBuilder.prostgles.opts.DEBUG_MODE);
|
|
601
|
+
const { schema_md5 = "none" } = await this.db.oneOrNone("SELECT md5($1) as schema_md5", [initQuery.trim()]);
|
|
602
|
+
const query = pgp.as.format(initQuery, { schema_md5, version });
|
|
603
|
+
const existingSchema = await this.db.any(PROSTGLES_SCHEMA_EXISTS_QUERY);
|
|
604
|
+
if(!existingSchema.length){
|
|
605
|
+
return query;
|
|
606
|
+
}
|
|
607
|
+
const { existingSchemaVersions } = await tryCatch(async () => {
|
|
608
|
+
const existingSchemaVersions = await this.db.any(PROSTGLES_SCHEMA_VERSION_OK_QUERY, { schema_md5, version });
|
|
609
|
+
return {
|
|
610
|
+
existingSchemaVersions
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
if(!existingSchemaVersions?.length){
|
|
614
|
+
return query;
|
|
615
|
+
}
|
|
597
616
|
|
|
598
|
-
return
|
|
617
|
+
return undefined;
|
|
599
618
|
}
|
|
@@ -1,16 +1,48 @@
|
|
|
1
|
+
import { isDefined, isObject } from "prostgles-types";
|
|
1
2
|
import { PostgresNotifListenManager } from "../PostgresNotifListenManager";
|
|
2
3
|
import { getWatchSchemaTagList } from "../SchemaWatch/getWatchSchemaTagList";
|
|
3
4
|
import { NOTIF_CHANNEL, PubSubManager, asValue } from "./PubSubManager";
|
|
4
|
-
import {
|
|
5
|
+
import { getPubSubManagerInitQuery } from "./getInitQuery";
|
|
5
6
|
export const REALTIME_TRIGGER_CHECK_QUERY = "prostgles-server internal query used to manage realtime triggers" as const;
|
|
6
7
|
|
|
8
|
+
export const tout = (ms: number) => new Promise(res => setTimeout(res, ms));
|
|
9
|
+
|
|
7
10
|
export async function initPubSubManager(this: PubSubManager): Promise<PubSubManager | undefined> {
|
|
8
11
|
if (!this.getIsDestroyed()) return undefined;
|
|
9
12
|
|
|
10
13
|
try {
|
|
11
14
|
|
|
12
|
-
const initQuery = await
|
|
13
|
-
|
|
15
|
+
const initQuery = await getPubSubManagerInitQuery.bind(this)();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* High database activity might cause deadlocks.
|
|
19
|
+
* Must retry
|
|
20
|
+
*/
|
|
21
|
+
let didDeadlock = false;
|
|
22
|
+
let tries = 3;
|
|
23
|
+
let error: any;
|
|
24
|
+
while (isDefined(initQuery) && tries > 0) {
|
|
25
|
+
try {
|
|
26
|
+
/** Try to reduce race condition deadlocks due to multiple clients connecting at the same time */
|
|
27
|
+
await tout(Math.random());
|
|
28
|
+
|
|
29
|
+
await this.db.any(initQuery);
|
|
30
|
+
error = undefined;
|
|
31
|
+
tries = 0;
|
|
32
|
+
} catch (e: any) {
|
|
33
|
+
if(!didDeadlock && isObject(e) && e.code === "40P01"){
|
|
34
|
+
didDeadlock = true;
|
|
35
|
+
tries = 5;
|
|
36
|
+
console.error("Deadlock detected. Retrying...");
|
|
37
|
+
}
|
|
38
|
+
error = e;
|
|
39
|
+
tries --;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if(error){
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
|
|
14
46
|
if (!this.getIsDestroyed()) return;
|
|
15
47
|
|
|
16
48
|
/* Prepare App id */
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"../..": {
|
|
23
23
|
"name": "prostgles-server",
|
|
24
|
-
"version": "4.2.
|
|
24
|
+
"version": "4.2.79",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"bluebird": "^3.7.2",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"@types/pg": "^8.11.5",
|
|
43
43
|
"@types/pg-cursor": "^2.7.2",
|
|
44
44
|
"@types/sharp": "^0.30.4",
|
|
45
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
46
|
-
"@typescript-eslint/parser": "^
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
|
46
|
+
"@typescript-eslint/parser": "^7.14.1",
|
|
47
47
|
"eslint": "^8.51.0",
|
|
48
48
|
"socket.io": "^4.7.5",
|
|
49
49
|
"typescript": "^5.3.3"
|
|
@@ -1711,8 +1711,8 @@
|
|
|
1711
1711
|
"@types/pg": "^8.11.5",
|
|
1712
1712
|
"@types/pg-cursor": "^2.7.2",
|
|
1713
1713
|
"@types/sharp": "^0.30.4",
|
|
1714
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
1715
|
-
"@typescript-eslint/parser": "^
|
|
1714
|
+
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
|
1715
|
+
"@typescript-eslint/parser": "^7.14.1",
|
|
1716
1716
|
"bluebird": "^3.7.2",
|
|
1717
1717
|
"body-parser": "^1.20.2",
|
|
1718
1718
|
"check-disk-space": "^3.4.0",
|