prostgles-server 3.0.70 → 3.0.72
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/PubSubManager.d.ts +4 -4
- package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/PubSubManager.js.map +1 -1
- package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/initPubSubManager.js +52 -36
- package/dist/PubSubManager/initPubSubManager.js.map +1 -1
- package/lib/AuthHandler.js +213 -209
- package/lib/DBEventsManager.js +34 -31
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.js +163 -155
- package/lib/DboBuilder/TableHandler.js +21 -20
- package/lib/DboBuilder/ViewHandler.js +23 -8
- package/lib/DboBuilder/runSQL.js +5 -5
- package/lib/DboBuilder.js +85 -65
- package/lib/FileManager.js +369 -364
- package/lib/PostgresNotifListenManager.js +26 -20
- package/lib/Prostgles.js +194 -177
- package/lib/PubSubManager/PubSubManager.d.ts +4 -4
- package/lib/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/PubSubManager.js +249 -239
- package/lib/PubSubManager/PubSubManager.ts +1 -1
- package/lib/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/initPubSubManager.js +52 -36
- package/lib/PubSubManager/initPubSubManager.ts +53 -37
- package/lib/PublishParser.js +7 -2
- package/lib/SchemaWatch.js +2 -1
- package/lib/TableConfig.js +94 -91
- package/package.json +2 -2
- package/tests/client/PID.txt +1 -1
- package/tests/client/tsconfig.json +2 -2
- package/tests/server/package-lock.json +3 -3
- package/tests/server/tsconfig.json +2 -2
|
@@ -26,7 +26,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
26
26
|
__setModuleDefault(result, mod);
|
|
27
27
|
return result;
|
|
28
28
|
};
|
|
29
|
-
var _a;
|
|
30
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
30
|
exports.omitKeys = exports.pickKeys = exports.PubSubManager = exports.log = exports.DEFAULT_SYNC_BATCH_SIZE = exports.asValue = void 0;
|
|
32
31
|
const utils_1 = require("../utils");
|
|
@@ -50,60 +49,112 @@ const log = (...args) => {
|
|
|
50
49
|
};
|
|
51
50
|
exports.log = log;
|
|
52
51
|
class PubSubManager {
|
|
52
|
+
static DELIMITER = '|$prstgls$|';
|
|
53
|
+
dboBuilder;
|
|
54
|
+
get db() {
|
|
55
|
+
return this.dboBuilder.db;
|
|
56
|
+
}
|
|
57
|
+
get dbo() {
|
|
58
|
+
return this.dboBuilder.dbo;
|
|
59
|
+
}
|
|
60
|
+
_triggers;
|
|
61
|
+
sockets;
|
|
62
|
+
subs;
|
|
63
|
+
syncs;
|
|
64
|
+
socketChannelPreffix;
|
|
65
|
+
onSchemaChange = undefined;
|
|
66
|
+
postgresNotifListenManager;
|
|
53
67
|
constructor(options) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
68
|
+
const { wsChannelNamePrefix, pgChannelName, onSchemaChange, dboBuilder } = options;
|
|
69
|
+
if (!dboBuilder.db || !dboBuilder.dbo) {
|
|
70
|
+
throw 'MISSING: db_pg, db';
|
|
71
|
+
}
|
|
72
|
+
this.onSchemaChange = onSchemaChange;
|
|
73
|
+
this.dboBuilder = dboBuilder;
|
|
74
|
+
this.sockets = {};
|
|
75
|
+
this.subs = {};
|
|
76
|
+
this.syncs = [];
|
|
77
|
+
this.socketChannelPreffix = wsChannelNamePrefix || "_psqlWS_";
|
|
78
|
+
(0, exports.log)("Created PubSubManager");
|
|
79
|
+
}
|
|
80
|
+
NOTIF_TYPE = {
|
|
81
|
+
data: "data_has_changed",
|
|
82
|
+
schema: "schema_has_changed"
|
|
83
|
+
};
|
|
84
|
+
NOTIF_CHANNEL = {
|
|
85
|
+
preffix: 'prostgles_',
|
|
86
|
+
getFull: (appID) => {
|
|
87
|
+
const finalAppId = appID ?? this.appID;
|
|
88
|
+
if (!finalAppId)
|
|
89
|
+
throw "No appID";
|
|
90
|
+
return this.NOTIF_CHANNEL.preffix + finalAppId;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
appID;
|
|
94
|
+
appCheckFrequencyMS = 10 * 1000;
|
|
95
|
+
appCheck;
|
|
96
|
+
// ,datname
|
|
97
|
+
// ,usename
|
|
98
|
+
// ,client_hostname
|
|
99
|
+
// ,client_port
|
|
100
|
+
// ,backend_start
|
|
101
|
+
// ,query_start
|
|
102
|
+
// ,query
|
|
103
|
+
// ,state
|
|
104
|
+
// console.log(await _db.any(`
|
|
105
|
+
// SELECT pid, application_name, state
|
|
106
|
+
// FROM pg_stat_activity
|
|
107
|
+
// WHERE application_name IS NOT NULL AND application_name != '' -- state = 'active';
|
|
108
|
+
// `))
|
|
109
|
+
static canCreate = async (db) => {
|
|
110
|
+
const canExecute = await (0, DboBuilder_1.canEXECUTE)(db);
|
|
111
|
+
const isSuperUs = await (0, Prostgles_1.isSuperUser)(db);
|
|
112
|
+
return { canExecute, isSuperUs, yes: canExecute && isSuperUs };
|
|
113
|
+
};
|
|
114
|
+
static create = async (options) => {
|
|
115
|
+
const res = new PubSubManager(options);
|
|
116
|
+
return await res.init();
|
|
117
|
+
};
|
|
118
|
+
destroyed = false;
|
|
119
|
+
destroy = () => {
|
|
120
|
+
this.destroyed = true;
|
|
121
|
+
if (this.appCheck) {
|
|
122
|
+
clearInterval(this.appCheck);
|
|
123
|
+
}
|
|
124
|
+
this.onSocketDisconnected();
|
|
125
|
+
// if(this.postgresNotifListenManager){
|
|
126
|
+
// this.postgresNotifListenManager.stopListening();
|
|
127
|
+
// }
|
|
128
|
+
if (!this.postgresNotifListenManager)
|
|
129
|
+
throw "this.postgresNotifListenManager missing";
|
|
130
|
+
this.postgresNotifListenManager.destroy();
|
|
131
|
+
};
|
|
132
|
+
canContinue = () => {
|
|
133
|
+
if (this.destroyed) {
|
|
134
|
+
console.trace("Could not start destroyed instance");
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
};
|
|
139
|
+
appChecking = false;
|
|
140
|
+
init = initPubSubManager_1.initPubSubManager.bind(this);
|
|
141
|
+
DB_OBJ_NAMES = {
|
|
142
|
+
trigger_add_remove_func: "prostgles.trigger_add_remove_func",
|
|
143
|
+
data_watch_func: "prostgles.prostgles_trigger_function",
|
|
144
|
+
schema_watch_func: "prostgles.schema_watch_func",
|
|
145
|
+
schema_watch_trigger: "prostgles_schema_watch_trigger_new"
|
|
146
|
+
};
|
|
147
|
+
static SCHEMA_ALTERING_QUERIES = ['CREATE TABLE', 'ALTER TABLE', 'DROP TABLE', 'CREATE VIEW', 'DROP VIEW', 'ALTER VIEW', 'CREATE TABLE AS', 'SELECT INTO'];
|
|
148
|
+
static EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID = "prostgles internal query that should be excluded from ";
|
|
149
|
+
prepareTriggers = async () => {
|
|
150
|
+
// SELECT * FROM pg_catalog.pg_event_trigger WHERE evtname
|
|
151
|
+
if (!this.appID)
|
|
152
|
+
throw "prepareTriggers failed: this.appID missing";
|
|
153
|
+
if (this.dboBuilder.prostgles.opts.watchSchema && !(await (0, Prostgles_1.isSuperUser)(this.db))) {
|
|
154
|
+
console.warn("prostgles watchSchema requires superuser db user. Will not watch using event triggers");
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
await this.db.any(`
|
|
107
158
|
BEGIN;-- ISOLATION LEVEL SERIALIZABLE;
|
|
108
159
|
|
|
109
160
|
/** ${PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID}
|
|
@@ -203,170 +254,16 @@ class PubSubManager {
|
|
|
203
254
|
|
|
204
255
|
COMMIT;
|
|
205
256
|
`).catch(e => {
|
|
206
|
-
console.error("prepareTriggers failed: ", e);
|
|
207
|
-
throw e;
|
|
208
|
-
});
|
|
209
|
-
return true;
|
|
210
|
-
}
|
|
211
|
-
catch (e) {
|
|
212
257
|
console.error("prepareTriggers failed: ", e);
|
|
213
258
|
throw e;
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
/* Relay relevant data to relevant subscriptions */
|
|
217
|
-
this.notifListener = async (data) => {
|
|
218
|
-
const str = data.payload;
|
|
219
|
-
if (!str) {
|
|
220
|
-
console.error("Empty notif?");
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
const dataArr = str.split(PubSubManager.DELIMITER), notifType = dataArr[0];
|
|
224
|
-
(0, exports.log)(str);
|
|
225
|
-
if (notifType === this.NOTIF_TYPE.schema) {
|
|
226
|
-
if (this.onSchemaChange) {
|
|
227
|
-
const command = dataArr[1], event_type = dataArr[2], query = dataArr[3];
|
|
228
|
-
if (query) {
|
|
229
|
-
this.onSchemaChange({ command, query });
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
if (notifType !== this.NOTIF_TYPE.data) {
|
|
235
|
-
console.error("Unexpected notif type: ", notifType);
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
const table_name = dataArr[1], op_name = dataArr[2], condition_ids_str = dataArr[3];
|
|
239
|
-
// const triggers = await this.db.any("SELECT * FROM prostgles.triggers WHERE table_name = $1 AND id IN ($2:csv)", [table_name, condition_ids_str.split(",").map(v => +v)]);
|
|
240
|
-
// const conditions: string[] = triggers.map(t => t.condition);
|
|
241
|
-
(0, exports.log)("PG Trigger ->", dataArr.join("__"));
|
|
242
|
-
if (condition_ids_str && condition_ids_str.startsWith("error") &&
|
|
243
|
-
this._triggers && this._triggers[table_name] && this._triggers[table_name].length) {
|
|
244
|
-
const pref = "INTERNAL ERROR. Schema might have changed";
|
|
245
|
-
console.error(`${pref}: ${condition_ids_str}`);
|
|
246
|
-
this._triggers[table_name].map(c => {
|
|
247
|
-
const subs = this.getSubs(table_name, c);
|
|
248
|
-
subs.map(s => {
|
|
249
|
-
this.pushSubData(s, pref + ". Check server logs");
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
else if (condition_ids_str?.split(",").length &&
|
|
254
|
-
condition_ids_str?.split(",").every((c) => Number.isInteger(+c)) &&
|
|
255
|
-
this._triggers?.[table_name]?.length) {
|
|
256
|
-
const idxs = condition_ids_str.split(",").map(v => +v);
|
|
257
|
-
const conditions = this._triggers[table_name].filter((c, i) => idxs.includes(i));
|
|
258
|
-
(0, exports.log)("PG Trigger -> ", { table_name, op_name, condition_ids_str, conditions }, this._triggers[table_name]);
|
|
259
|
-
conditions.map(condition => {
|
|
260
|
-
const subs = this.getSubs(table_name, condition);
|
|
261
|
-
const syncs = this.getSyncs(table_name, condition);
|
|
262
|
-
syncs.map((s) => {
|
|
263
|
-
this.syncData(s, undefined, "trigger");
|
|
264
|
-
});
|
|
265
|
-
if (!subs) {
|
|
266
|
-
// console.error(`sub missing for ${table_name} ${condition}`, this.triggers);
|
|
267
|
-
// console.log(this.subs)
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
/* Throttle the subscriptions */
|
|
271
|
-
for (var i = 0; i < subs.length; i++) {
|
|
272
|
-
var sub = subs[i];
|
|
273
|
-
if (this.dbo[sub.table_name] &&
|
|
274
|
-
sub.is_ready &&
|
|
275
|
-
(sub.socket_id && this.sockets[sub.socket_id]) || sub.func) {
|
|
276
|
-
const throttle = sub.throttle || 0;
|
|
277
|
-
if (sub.last_throttled <= Date.now() - throttle) {
|
|
278
|
-
/* It is assumed the policy was checked before this point */
|
|
279
|
-
this.pushSubData(sub);
|
|
280
|
-
// sub.last_throttled = Date.now();
|
|
281
|
-
}
|
|
282
|
-
else if (!sub.is_throttling) {
|
|
283
|
-
(0, exports.log)("throttling sub");
|
|
284
|
-
sub.is_throttling = setTimeout(() => {
|
|
285
|
-
(0, exports.log)("throttling finished. pushSubData...");
|
|
286
|
-
sub.is_throttling = null;
|
|
287
|
-
this.pushSubData(sub);
|
|
288
|
-
}, throttle); // sub.throttle);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
// if(!this._triggers || !this._triggers[table_name] || !this._triggers[table_name].length){
|
|
296
|
-
// console.warn(190, "Trigger sub not found. DROPPING TRIGGER", table_name, condition_ids_str, this._triggers);
|
|
297
|
-
// this.dropTrigger(table_name);
|
|
298
|
-
// } else {
|
|
299
|
-
// }
|
|
300
|
-
console.warn(190, "Trigger sub issue: ", table_name, condition_ids_str, this._triggers);
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
this.getActiveListeners = () => {
|
|
304
|
-
let result = [];
|
|
305
|
-
const upsert = (t, c) => {
|
|
306
|
-
if (!result.find(r => r.table_name === t && r.condition === c)) {
|
|
307
|
-
result.push({ table_name: t, condition: c });
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
|
-
(this.syncs || []).map(s => {
|
|
311
|
-
upsert(s.table_name, s.condition);
|
|
312
|
-
});
|
|
313
|
-
Object.keys(this.subs || {}).map(table_name => {
|
|
314
|
-
Object.keys(this.subs[table_name] || {}).map(condition => {
|
|
315
|
-
if (this.subs[table_name][condition].subs.length) {
|
|
316
|
-
upsert(table_name, condition);
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
259
|
});
|
|
320
|
-
return result;
|
|
321
|
-
};
|
|
322
|
-
this.checkIfTimescaleBug = async (table_name) => {
|
|
323
|
-
const schema = "_timescaledb_catalog", res = await this.db.oneOrNone("SELECT EXISTS( \
|
|
324
|
-
SELECT * \
|
|
325
|
-
FROM information_schema.tables \
|
|
326
|
-
WHERE 1 = 1 \
|
|
327
|
-
AND table_schema = ${schema} \
|
|
328
|
-
AND table_name = 'hypertable' \
|
|
329
|
-
);", { schema });
|
|
330
|
-
if (res.exists) {
|
|
331
|
-
let isHyperTable = await this.db.any("SELECT * FROM " + (0, prostgles_types_1.asName)(schema) + ".hypertable WHERE table_name = ${table_name};", { table_name, schema });
|
|
332
|
-
if (isHyperTable && isHyperTable.length) {
|
|
333
|
-
throw "Triggers do not work on timescaledb hypertables due to bug:\nhttps://github.com/timescale/timescaledb/issues/1084";
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
260
|
return true;
|
|
337
|
-
};
|
|
338
|
-
/*
|
|
339
|
-
A table will only have a trigger with all conditions (for different subs)
|
|
340
|
-
conditions = ["user_id = 1"]
|
|
341
|
-
fields = ["user_id"]
|
|
342
|
-
*/
|
|
343
|
-
this.getMyTriggerQuery = async () => {
|
|
344
|
-
return pgp.as.format(`
|
|
345
|
-
SELECT * --, ROW_NUMBER() OVER(PARTITION BY table_name ORDER BY table_name, condition ) - 1 as id
|
|
346
|
-
FROM prostgles.v_triggers
|
|
347
|
-
WHERE app_id = $1
|
|
348
|
-
ORDER BY table_name, condition
|
|
349
|
-
`, [this.appID]);
|
|
350
|
-
};
|
|
351
|
-
this.addTriggerPool = undefined;
|
|
352
|
-
const { wsChannelNamePrefix, pgChannelName, onSchemaChange, dboBuilder } = options;
|
|
353
|
-
if (!dboBuilder.db || !dboBuilder.dbo) {
|
|
354
|
-
throw 'MISSING: db_pg, db';
|
|
355
261
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
this.socketChannelPreffix = wsChannelNamePrefix || "_psqlWS_";
|
|
362
|
-
(0, exports.log)("Created PubSubManager");
|
|
363
|
-
}
|
|
364
|
-
get db() {
|
|
365
|
-
return this.dboBuilder.db;
|
|
366
|
-
}
|
|
367
|
-
get dbo() {
|
|
368
|
-
return this.dboBuilder.dbo;
|
|
369
|
-
}
|
|
262
|
+
catch (e) {
|
|
263
|
+
console.error("prepareTriggers failed: ", e);
|
|
264
|
+
throw e;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
370
267
|
isReady() {
|
|
371
268
|
if (!this.postgresNotifListenManager)
|
|
372
269
|
throw "this.postgresNotifListenManager missing";
|
|
@@ -379,6 +276,93 @@ class PubSubManager {
|
|
|
379
276
|
return (this.syncs || [])
|
|
380
277
|
.filter((s) => s.table_name === table_name && s.condition === condition);
|
|
381
278
|
}
|
|
279
|
+
/* Relay relevant data to relevant subscriptions */
|
|
280
|
+
notifListener = async (data) => {
|
|
281
|
+
const str = data.payload;
|
|
282
|
+
if (!str) {
|
|
283
|
+
console.error("Empty notif?");
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const dataArr = str.split(PubSubManager.DELIMITER), notifType = dataArr[0];
|
|
287
|
+
(0, exports.log)(str);
|
|
288
|
+
if (notifType === this.NOTIF_TYPE.schema) {
|
|
289
|
+
if (this.onSchemaChange) {
|
|
290
|
+
const command = dataArr[1], event_type = dataArr[2], query = dataArr[3];
|
|
291
|
+
if (query) {
|
|
292
|
+
this.onSchemaChange({ command, query });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (notifType !== this.NOTIF_TYPE.data) {
|
|
298
|
+
console.error("Unexpected notif type: ", notifType);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const table_name = dataArr[1], op_name = dataArr[2], condition_ids_str = dataArr[3];
|
|
302
|
+
// const triggers = await this.db.any("SELECT * FROM prostgles.triggers WHERE table_name = $1 AND id IN ($2:csv)", [table_name, condition_ids_str.split(",").map(v => +v)]);
|
|
303
|
+
// const conditions: string[] = triggers.map(t => t.condition);
|
|
304
|
+
(0, exports.log)("PG Trigger ->", dataArr.join("__"));
|
|
305
|
+
if (condition_ids_str && condition_ids_str.startsWith("error") &&
|
|
306
|
+
this._triggers && this._triggers[table_name] && this._triggers[table_name].length) {
|
|
307
|
+
const pref = "INTERNAL ERROR. Schema might have changed";
|
|
308
|
+
console.error(`${pref}: ${condition_ids_str}`);
|
|
309
|
+
this._triggers[table_name].map(c => {
|
|
310
|
+
const subs = this.getSubs(table_name, c);
|
|
311
|
+
subs.map(s => {
|
|
312
|
+
this.pushSubData(s, pref + ". Check server logs");
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
else if (condition_ids_str?.split(",").length &&
|
|
317
|
+
condition_ids_str?.split(",").every((c) => Number.isInteger(+c)) &&
|
|
318
|
+
this._triggers?.[table_name]?.length) {
|
|
319
|
+
const idxs = condition_ids_str.split(",").map(v => +v);
|
|
320
|
+
const conditions = this._triggers[table_name].filter((c, i) => idxs.includes(i));
|
|
321
|
+
(0, exports.log)("PG Trigger -> ", { table_name, op_name, condition_ids_str, conditions }, this._triggers[table_name]);
|
|
322
|
+
conditions.map(condition => {
|
|
323
|
+
const subs = this.getSubs(table_name, condition);
|
|
324
|
+
const syncs = this.getSyncs(table_name, condition);
|
|
325
|
+
syncs.map((s) => {
|
|
326
|
+
this.syncData(s, undefined, "trigger");
|
|
327
|
+
});
|
|
328
|
+
if (!subs) {
|
|
329
|
+
// console.error(`sub missing for ${table_name} ${condition}`, this.triggers);
|
|
330
|
+
// console.log(this.subs)
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
/* Throttle the subscriptions */
|
|
334
|
+
for (var i = 0; i < subs.length; i++) {
|
|
335
|
+
var sub = subs[i];
|
|
336
|
+
if (this.dbo[sub.table_name] &&
|
|
337
|
+
sub.is_ready &&
|
|
338
|
+
(sub.socket_id && this.sockets[sub.socket_id]) || sub.func) {
|
|
339
|
+
const throttle = sub.throttle || 0;
|
|
340
|
+
if (sub.last_throttled <= Date.now() - throttle) {
|
|
341
|
+
/* It is assumed the policy was checked before this point */
|
|
342
|
+
this.pushSubData(sub);
|
|
343
|
+
// sub.last_throttled = Date.now();
|
|
344
|
+
}
|
|
345
|
+
else if (!sub.is_throttling) {
|
|
346
|
+
(0, exports.log)("throttling sub");
|
|
347
|
+
sub.is_throttling = setTimeout(() => {
|
|
348
|
+
(0, exports.log)("throttling finished. pushSubData...");
|
|
349
|
+
sub.is_throttling = null;
|
|
350
|
+
this.pushSubData(sub);
|
|
351
|
+
}, throttle); // sub.throttle);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
// if(!this._triggers || !this._triggers[table_name] || !this._triggers[table_name].length){
|
|
359
|
+
// console.warn(190, "Trigger sub not found. DROPPING TRIGGER", table_name, condition_ids_str, this._triggers);
|
|
360
|
+
// this.dropTrigger(table_name);
|
|
361
|
+
// } else {
|
|
362
|
+
// }
|
|
363
|
+
console.warn(190, "Trigger sub issue: ", table_name, condition_ids_str, this._triggers);
|
|
364
|
+
}
|
|
365
|
+
};
|
|
382
366
|
pushSubData(sub, err) {
|
|
383
367
|
if (!sub)
|
|
384
368
|
throw "pushSubData: invalid sub";
|
|
@@ -430,6 +414,7 @@ class PubSubManager {
|
|
|
430
414
|
socket.on("disconnect", () => this.onSocketDisconnected(socket));
|
|
431
415
|
}
|
|
432
416
|
}
|
|
417
|
+
syncTimeout;
|
|
433
418
|
async syncData(sync, clientData, source) {
|
|
434
419
|
return await (0, SyncReplication_1.syncData)(this, sync, clientData, source);
|
|
435
420
|
}
|
|
@@ -649,6 +634,25 @@ class PubSubManager {
|
|
|
649
634
|
console.error("Could not unsubscribe. Subscription might not have initialised yet");
|
|
650
635
|
}
|
|
651
636
|
}
|
|
637
|
+
getActiveListeners = () => {
|
|
638
|
+
let result = [];
|
|
639
|
+
const upsert = (t, c) => {
|
|
640
|
+
if (!result.find(r => r.table_name === t && r.condition === c)) {
|
|
641
|
+
result.push({ table_name: t, condition: c });
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
(this.syncs || []).map(s => {
|
|
645
|
+
upsert(s.table_name, s.condition);
|
|
646
|
+
});
|
|
647
|
+
Object.keys(this.subs || {}).map(table_name => {
|
|
648
|
+
Object.keys(this.subs[table_name] || {}).map(condition => {
|
|
649
|
+
if (this.subs[table_name][condition].subs.length) {
|
|
650
|
+
upsert(table_name, condition);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
return result;
|
|
655
|
+
};
|
|
652
656
|
onSocketDisconnected(socket, channel_name) {
|
|
653
657
|
// process.on('warning', e => {
|
|
654
658
|
// console.warn(e.stack)
|
|
@@ -696,6 +700,38 @@ class PubSubManager {
|
|
|
696
700
|
}
|
|
697
701
|
return "ok";
|
|
698
702
|
}
|
|
703
|
+
checkIfTimescaleBug = async (table_name) => {
|
|
704
|
+
const schema = "_timescaledb_catalog", res = await this.db.oneOrNone("SELECT EXISTS( \
|
|
705
|
+
SELECT * \
|
|
706
|
+
FROM information_schema.tables \
|
|
707
|
+
WHERE 1 = 1 \
|
|
708
|
+
AND table_schema = ${schema} \
|
|
709
|
+
AND table_name = 'hypertable' \
|
|
710
|
+
);", { schema });
|
|
711
|
+
if (res.exists) {
|
|
712
|
+
let isHyperTable = await this.db.any("SELECT * FROM " + (0, prostgles_types_1.asName)(schema) + ".hypertable WHERE table_name = ${table_name};", { table_name, schema });
|
|
713
|
+
if (isHyperTable && isHyperTable.length) {
|
|
714
|
+
throw "Triggers do not work on timescaledb hypertables due to bug:\nhttps://github.com/timescale/timescaledb/issues/1084";
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
return true;
|
|
718
|
+
};
|
|
719
|
+
/*
|
|
720
|
+
A table will only have a trigger with all conditions (for different subs)
|
|
721
|
+
conditions = ["user_id = 1"]
|
|
722
|
+
fields = ["user_id"]
|
|
723
|
+
*/
|
|
724
|
+
getMyTriggerQuery = async () => {
|
|
725
|
+
return pgp.as.format(`
|
|
726
|
+
SELECT * --, ROW_NUMBER() OVER(PARTITION BY table_name ORDER BY table_name, condition ) - 1 as id
|
|
727
|
+
FROM prostgles.v_triggers
|
|
728
|
+
WHERE app_id = $1
|
|
729
|
+
ORDER BY table_name, condition
|
|
730
|
+
`, [this.appID]);
|
|
731
|
+
};
|
|
732
|
+
// waitingTriggers: { [key: string]: string[] } = undefined;
|
|
733
|
+
addingTrigger;
|
|
734
|
+
addTriggerPool = undefined;
|
|
699
735
|
async addTrigger(params, viewOptions) {
|
|
700
736
|
try {
|
|
701
737
|
let { table_name, condition } = { ...params };
|
|
@@ -744,32 +780,6 @@ class PubSubManager {
|
|
|
744
780
|
}
|
|
745
781
|
}
|
|
746
782
|
exports.PubSubManager = PubSubManager;
|
|
747
|
-
_a = PubSubManager;
|
|
748
|
-
PubSubManager.DELIMITER = '|$prstgls$|';
|
|
749
|
-
// ,datname
|
|
750
|
-
// ,usename
|
|
751
|
-
// ,client_hostname
|
|
752
|
-
// ,client_port
|
|
753
|
-
// ,backend_start
|
|
754
|
-
// ,query_start
|
|
755
|
-
// ,query
|
|
756
|
-
// ,state
|
|
757
|
-
// console.log(await _db.any(`
|
|
758
|
-
// SELECT pid, application_name, state
|
|
759
|
-
// FROM pg_stat_activity
|
|
760
|
-
// WHERE application_name IS NOT NULL AND application_name != '' -- state = 'active';
|
|
761
|
-
// `))
|
|
762
|
-
PubSubManager.canCreate = async (db) => {
|
|
763
|
-
const canExecute = await (0, DboBuilder_1.canEXECUTE)(db);
|
|
764
|
-
const isSuperUs = await (0, Prostgles_1.isSuperUser)(db);
|
|
765
|
-
return { canExecute, isSuperUs, yes: canExecute && isSuperUs };
|
|
766
|
-
};
|
|
767
|
-
PubSubManager.create = async (options) => {
|
|
768
|
-
const res = new PubSubManager(options);
|
|
769
|
-
return await res.init();
|
|
770
|
-
};
|
|
771
|
-
PubSubManager.SCHEMA_ALTERING_QUERIES = ['CREATE TABLE', 'ALTER TABLE', 'DROP TABLE', 'CREATE VIEW', 'DROP VIEW', 'ALTER VIEW', 'CREATE TABLE AS', 'SELECT INTO'];
|
|
772
|
-
PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID = "prostgles internal query that should be excluded from ";
|
|
773
783
|
const parseCondition = (condition) => Boolean(condition && condition.trim().length) ? condition : "TRUE";
|
|
774
784
|
var prostgles_types_2 = require("prostgles-types");
|
|
775
785
|
Object.defineProperty(exports, "pickKeys", { enumerable: true, get: function () { return prostgles_types_2.pickKeys; } });
|
|
@@ -230,7 +230,7 @@ export class PubSubManager {
|
|
|
230
230
|
data_watch_func: "prostgles.prostgles_trigger_function",
|
|
231
231
|
schema_watch_func: "prostgles.schema_watch_func",
|
|
232
232
|
schema_watch_trigger: "prostgles_schema_watch_trigger_new"
|
|
233
|
-
}
|
|
233
|
+
} as const;
|
|
234
234
|
|
|
235
235
|
static SCHEMA_ALTERING_QUERIES = ['CREATE TABLE', 'ALTER TABLE', 'DROP TABLE', 'CREATE VIEW', 'DROP VIEW', 'ALTER VIEW', 'CREATE TABLE AS', 'SELECT INTO'];
|
|
236
236
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initPubSubManager.d.ts","sourceRoot":"","sources":["initPubSubManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG9D,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"initPubSubManager.d.ts","sourceRoot":"","sources":["initPubSubManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG9D,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAioB/F"}
|