prostgles-server 2.0.157 → 2.0.158
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/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +8 -6
- package/dist/DboBuilder.js.map +1 -1
- package/dist/PubSubManager.d.ts +3 -2
- package/dist/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager.js +13 -13
- package/dist/PubSubManager.js.map +1 -1
- package/dist/SyncReplication.d.ts +1 -1
- package/dist/SyncReplication.d.ts.map +1 -1
- package/dist/SyncReplication.js +21 -19
- package/dist/SyncReplication.js.map +1 -1
- package/lib/DboBuilder.ts +8 -7
- package/lib/PubSubManager.ts +13 -13
- package/lib/SyncReplication.ts +24 -24
- package/package.json +2 -2
- package/tests/client/PID.txt +1 -1
- package/tests/client/package-lock.json +15 -15
- package/tests/client/package.json +1 -1
- package/tests/client_only_queries.js +26 -20
- package/tests/client_only_queries.ts +27 -18
- package/tests/isomorphic_queries.js +178 -231
- package/tests/isomorphic_queries.ts +2 -61
- package/tests/server/package-lock.json +186 -50
- package/tests/server/package.json +2 -2
package/lib/SyncReplication.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { PubSubManager, SyncParams,
|
|
2
|
+
import { PubSubManager, SyncParams, pickKeys, omitKeys, log } from "./PubSubManager";
|
|
3
3
|
import { OrderBy, WAL, AnyObject, SyncBatchParams } from "prostgles-types";
|
|
4
4
|
import { TableHandler } from "./DboBuilder";
|
|
5
5
|
|
|
@@ -42,8 +42,8 @@ function getNumbers(numberArr: (null | undefined | string | number)[]): number[]
|
|
|
42
42
|
return numberArr.filter(v => v !== null && v !== undefined && Number.isFinite(+v)) as any;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export const syncData = async (_this: PubSubManager, sync: SyncParams, clientData
|
|
46
|
-
|
|
45
|
+
export const syncData = async (_this: PubSubManager, sync: SyncParams, clientData: ClientExpressData | undefined, source: "trigger" | "client") => {
|
|
46
|
+
log("syncData", { clientData, sync: pickKeys(sync, ["filter", "last_synced", "lr", "is_syncing"]) , source })
|
|
47
47
|
const {
|
|
48
48
|
socket_id, channel_name, table_name, filter,
|
|
49
49
|
table_rules, allow_delete = false, params,
|
|
@@ -162,7 +162,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
162
162
|
// console.log("deleteData deleteData deleteData " + deleted.length);
|
|
163
163
|
if(allow_delete){
|
|
164
164
|
return Promise.all(deleted.map(async d => {
|
|
165
|
-
const id_filter =
|
|
165
|
+
const id_filter = pickKeys(d, id_fields);
|
|
166
166
|
try {
|
|
167
167
|
await (_this.dbo[table_name] as TableHandler).delete(id_filter, undefined, undefined, table_rules);
|
|
168
168
|
return 1;
|
|
@@ -181,16 +181,13 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
181
181
|
* Upserts the given client data where synced_field is higher than on server
|
|
182
182
|
*/
|
|
183
183
|
upsertData = (data: AnyObject[], isExpress = false) => {
|
|
184
|
-
let inserted = 0,
|
|
185
|
-
updated = 0,
|
|
186
|
-
total = data.length;
|
|
187
184
|
|
|
188
185
|
// console.log("isExpress", isExpress, data);
|
|
189
186
|
|
|
190
|
-
return _this.dboBuilder.getTX(async dbTX => {
|
|
187
|
+
return _this.dboBuilder.getTX(async (dbTX) => {
|
|
191
188
|
const tbl = dbTX[table_name] as TableHandler;
|
|
192
189
|
const existingData = await tbl.find(
|
|
193
|
-
{ $or: data.map(d =>
|
|
190
|
+
{ $or: data.map(d => pickKeys(d, id_fields)) },
|
|
194
191
|
{
|
|
195
192
|
select: [synced_field, ...id_fields] ,
|
|
196
193
|
orderBy: (orderByAsc as OrderBy),
|
|
@@ -198,37 +195,40 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
198
195
|
undefined,
|
|
199
196
|
table_rules
|
|
200
197
|
);
|
|
201
|
-
|
|
202
|
-
|
|
198
|
+
let inserts = data.filter(d => !existingData.find(ed => rowsIdsMatch(ed, d)));
|
|
199
|
+
let updates = data.filter(d => existingData.find(ed => rowsIdsMatch(ed, d) && +ed[synced_field] < +d[synced_field]) );
|
|
203
200
|
try {
|
|
204
201
|
if(!table_rules) throw "table_rules missing"
|
|
205
202
|
if(table_rules.update && updates.length){
|
|
206
203
|
let updateData: [any, any][] = [];
|
|
207
204
|
await Promise.all(updates.map(upd => {
|
|
208
|
-
const id_filter =
|
|
205
|
+
const id_filter = pickKeys(upd, id_fields);
|
|
209
206
|
const syncSafeFilter = { $and: [id_filter, { [synced_field]: { "<": upd[synced_field] } } ] }
|
|
210
|
-
|
|
211
|
-
updateData.push([syncSafeFilter,
|
|
207
|
+
|
|
208
|
+
updateData.push([syncSafeFilter, omitKeys(upd, id_fields)])
|
|
212
209
|
}));
|
|
213
|
-
await tbl.updateBatch(updateData, { fixIssues: true }, table_rules)
|
|
214
|
-
|
|
210
|
+
await tbl.updateBatch(updateData, { fixIssues: true }, table_rules);
|
|
211
|
+
} else {
|
|
212
|
+
updates = [];
|
|
215
213
|
}
|
|
214
|
+
|
|
216
215
|
if(table_rules.insert && inserts.length){
|
|
217
216
|
// const qs = await tbl.insert(inserts, { fixIssues: true }, null, table_rules, { returnQuery: true });
|
|
218
217
|
// console.log("inserts", qs)
|
|
219
218
|
await tbl.insert(inserts, { fixIssues: true }, undefined, table_rules);
|
|
220
|
-
|
|
219
|
+
} else {
|
|
220
|
+
inserts = [];
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
return
|
|
223
|
+
return { inserts, updates };
|
|
224
224
|
} catch(e) {
|
|
225
225
|
console.trace(e);
|
|
226
226
|
throw e;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
}).then(
|
|
230
|
-
log(`upsertData: inserted( ${
|
|
231
|
-
return { inserted , updated , total };
|
|
229
|
+
}).then(({ inserts, updates }) => {
|
|
230
|
+
log(`upsertData: inserted( ${inserts.length} ) updated( ${updates.length} ) total( ${data.length} ) \n last insert ${JSON.stringify(inserts.at(-1))} \n last update ${JSON.stringify(updates.at(-1))}`);
|
|
231
|
+
return { inserted: inserts.length , updated: updates.length , total: data.length };
|
|
232
232
|
})
|
|
233
233
|
.catch(err => {
|
|
234
234
|
console.trace("Something went wrong with syncing to server: \n ->", err, data.length, id_fields);
|
|
@@ -381,7 +381,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
381
381
|
});
|
|
382
382
|
await Promise.all(to_delete.map(d => {
|
|
383
383
|
deleted++;
|
|
384
|
-
return (_this.dbo[table_name] as TableHandler).delete(
|
|
384
|
+
return (_this.dbo[table_name] as TableHandler).delete(pickKeys(d, id_fields), { }, undefined, table_rules);
|
|
385
385
|
}));
|
|
386
386
|
sData = await getServerData(min_synced, offset);
|
|
387
387
|
}
|
|
@@ -447,7 +447,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
447
447
|
/**
|
|
448
448
|
* After all data was inserted request SyncInfo from client and sync again if necessary
|
|
449
449
|
*/
|
|
450
|
-
_this.syncData(sync, undefined);
|
|
450
|
+
_this.syncData(sync, undefined, source);
|
|
451
451
|
},
|
|
452
452
|
})
|
|
453
453
|
}
|
|
@@ -459,7 +459,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
459
459
|
_this.syncTimeout = setTimeout(() => {
|
|
460
460
|
_this.syncTimeout = undefined;
|
|
461
461
|
// console.log("SYNC FROM TIMEOUT")
|
|
462
|
-
_this.syncData(sync, undefined);
|
|
462
|
+
_this.syncData(sync, undefined, source);
|
|
463
463
|
}, throttle)
|
|
464
464
|
}
|
|
465
465
|
// console.log("SYNC THROTTLE")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prostgles-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.158",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"bluebird": "^3.7.2",
|
|
30
30
|
"file-type": "^16.5.3",
|
|
31
31
|
"pg-promise": "^10.11.1",
|
|
32
|
-
"prostgles-types": "^1.5.
|
|
32
|
+
"prostgles-types": "^1.5.131",
|
|
33
33
|
"sharp": "^0.30.5"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
package/tests/client/PID.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
23125
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@types/node": "^14.14.16",
|
|
13
13
|
"@types/socket.io-client": "^1.4.35",
|
|
14
|
-
"prostgles-client": "^1.5.
|
|
14
|
+
"prostgles-client": "^1.5.144",
|
|
15
15
|
"prostgles-types": "^1.5.68",
|
|
16
16
|
"socket.io-client": "^4.5.1"
|
|
17
17
|
}
|
|
@@ -73,17 +73,17 @@
|
|
|
73
73
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
74
74
|
},
|
|
75
75
|
"node_modules/prostgles-client": {
|
|
76
|
-
"version": "1.5.
|
|
77
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.
|
|
78
|
-
"integrity": "sha512-
|
|
76
|
+
"version": "1.5.144",
|
|
77
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.144.tgz",
|
|
78
|
+
"integrity": "sha512-IbLQ6PC3bUgRUHiWQs0p3PXdyAQWprPbRM7VZ4OCAuPzAnOdjyriB+psa04li1AMs9EtKpMkAil+Hks6tgyHpA==",
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"prostgles-types": "^1.5.
|
|
80
|
+
"prostgles-types": "^1.5.131"
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
"node_modules/prostgles-types": {
|
|
84
|
-
"version": "1.5.
|
|
85
|
-
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.
|
|
86
|
-
"integrity": "sha512-
|
|
84
|
+
"version": "1.5.131",
|
|
85
|
+
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.131.tgz",
|
|
86
|
+
"integrity": "sha512-gJUrlG2JcDFglKMLAf7flMHOQ5+rPSkBct4zhMTJU35wDEU4c9QWuoLaSMj3zhvw4q/wCb4tz4l3nCrNbdPCGw=="
|
|
87
87
|
},
|
|
88
88
|
"node_modules/socket.io-client": {
|
|
89
89
|
"version": "4.5.1",
|
|
@@ -187,17 +187,17 @@
|
|
|
187
187
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
188
188
|
},
|
|
189
189
|
"prostgles-client": {
|
|
190
|
-
"version": "1.5.
|
|
191
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.
|
|
192
|
-
"integrity": "sha512-
|
|
190
|
+
"version": "1.5.144",
|
|
191
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.144.tgz",
|
|
192
|
+
"integrity": "sha512-IbLQ6PC3bUgRUHiWQs0p3PXdyAQWprPbRM7VZ4OCAuPzAnOdjyriB+psa04li1AMs9EtKpMkAil+Hks6tgyHpA==",
|
|
193
193
|
"requires": {
|
|
194
|
-
"prostgles-types": "^1.5.
|
|
194
|
+
"prostgles-types": "^1.5.131"
|
|
195
195
|
}
|
|
196
196
|
},
|
|
197
197
|
"prostgles-types": {
|
|
198
|
-
"version": "1.5.
|
|
199
|
-
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.
|
|
200
|
-
"integrity": "sha512-
|
|
198
|
+
"version": "1.5.131",
|
|
199
|
+
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.131.tgz",
|
|
200
|
+
"integrity": "sha512-gJUrlG2JcDFglKMLAf7flMHOQ5+rPSkBct4zhMTJU35wDEU4c9QWuoLaSMj3zhvw4q/wCb4tz4l3nCrNbdPCGw=="
|
|
201
201
|
},
|
|
202
202
|
"socket.io-client": {
|
|
203
203
|
"version": "4.5.1",
|
|
@@ -4,14 +4,13 @@ const assert_1 = require("assert");
|
|
|
4
4
|
const isomorphic_queries_1 = require("./isomorphic_queries");
|
|
5
5
|
async function client_only(db, auth, log, methods) {
|
|
6
6
|
const testRealtime = () => {
|
|
7
|
-
log("Started testRealtime");
|
|
8
7
|
return new Promise(async (resolve, reject) => {
|
|
9
8
|
try {
|
|
10
9
|
/* METHODS */
|
|
11
10
|
const t222 = await methods.get();
|
|
12
11
|
assert_1.strict.equal(t222, 222, "methods.get() failed");
|
|
13
12
|
/* RAWSQL */
|
|
14
|
-
await (0, isomorphic_queries_1.
|
|
13
|
+
await (0, isomorphic_queries_1.tryRun)("SQL Full result", async () => {
|
|
15
14
|
const sqlStatement = await db.sql("SELECT $1", [1], { returnType: "statement" });
|
|
16
15
|
assert_1.strict.equal(sqlStatement, "SELECT 1", "db.sql statement query failed");
|
|
17
16
|
const arrayMode = await db.sql("SELECT 1 as a, 2 as a", undefined, { returnType: "arrayMode" });
|
|
@@ -34,29 +33,35 @@ async function client_only(db, auth, log, methods) {
|
|
|
34
33
|
udt_name: 'int4',
|
|
35
34
|
tsDataType: "number"
|
|
36
35
|
}], "db.sql query failed");
|
|
37
|
-
|
|
38
|
-
}, log);
|
|
36
|
+
});
|
|
39
37
|
await (0, isomorphic_queries_1.tryRunP)("sql LISTEN NOTIFY events", async (resolve, reject) => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
38
|
+
try {
|
|
39
|
+
const sub = await db.sql("LISTEN chnl ", {}, { returnType: "allowListen" });
|
|
40
|
+
if (!("addListener" in sub)) {
|
|
41
|
+
reject("addListener missing");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
sub.addListener(notif => {
|
|
45
|
+
const expected = "hello";
|
|
46
|
+
if (notif === expected)
|
|
47
|
+
resolve(true);
|
|
48
|
+
else
|
|
49
|
+
reject(`Notif value is not what we expect: ${JSON.stringify(notif)} is not ${JSON.stringify(expected)} (expected) `);
|
|
50
|
+
});
|
|
51
|
+
db.sql("NOTIFY chnl , 'hello'; ");
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
reject(e);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
51
57
|
await (0, isomorphic_queries_1.tryRunP)("sql NOTICE events", async (resolve, reject) => {
|
|
52
58
|
const sub = await db.sql("", {}, { returnType: "noticeSubscription" });
|
|
53
|
-
// console.log({ sub })
|
|
54
59
|
sub.addListener(notice => {
|
|
55
|
-
|
|
56
|
-
if (notice.message ===
|
|
60
|
+
const expected = "hello2";
|
|
61
|
+
if (notice.message === expected)
|
|
57
62
|
resolve(true);
|
|
58
63
|
else
|
|
59
|
-
reject(
|
|
64
|
+
reject(`Notice value is not what we expect: ${JSON.stringify(notice)} is not ${JSON.stringify(expected)} (expected) `);
|
|
60
65
|
});
|
|
61
66
|
db.sql(`
|
|
62
67
|
DO $$
|
|
@@ -68,7 +73,8 @@ async function client_only(db, auth, log, methods) {
|
|
|
68
73
|
`);
|
|
69
74
|
}, log);
|
|
70
75
|
/* REPLICATION */
|
|
71
|
-
|
|
76
|
+
log("Started testRealtime");
|
|
77
|
+
const start = Date.now();
|
|
72
78
|
await db.planes.delete();
|
|
73
79
|
let inserts = new Array(100).fill(null).map((d, i) => ({ id: i, flight_number: `FN${i}`, x: Math.random(), y: i }));
|
|
74
80
|
await db.planes.insert(inserts);
|
|
@@ -7,7 +7,7 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
const testRealtime = () => {
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
return new Promise(async (resolve, reject) => {
|
|
12
12
|
try {
|
|
13
13
|
|
|
@@ -16,7 +16,7 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
16
16
|
assert.equal(t222, 222, "methods.get() failed");
|
|
17
17
|
|
|
18
18
|
/* RAWSQL */
|
|
19
|
-
await
|
|
19
|
+
await tryRun("SQL Full result", async () => {
|
|
20
20
|
const sqlStatement = await db.sql("SELECT $1", [1], { returnType: "statement" });
|
|
21
21
|
assert.equal(sqlStatement, "SELECT 1", "db.sql statement query failed");
|
|
22
22
|
|
|
@@ -42,29 +42,37 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
42
42
|
udt_name: 'int4',
|
|
43
43
|
tsDataType: "number"
|
|
44
44
|
}] , "db.sql query failed");
|
|
45
|
-
|
|
46
|
-
}, log);
|
|
45
|
+
});
|
|
47
46
|
|
|
48
47
|
await tryRunP("sql LISTEN NOTIFY events", async (resolve, reject) => {
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
try {
|
|
50
|
+
|
|
51
|
+
const sub = await db.sql("LISTEN chnl ", {}, { returnType: "allowListen" });
|
|
52
|
+
if(!("addListener" in sub)) {
|
|
53
|
+
reject("addListener missing");
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
sub.addListener(notif => {
|
|
58
|
+
const expected = "hello"
|
|
59
|
+
if(notif === expected) resolve(true);
|
|
60
|
+
else reject(`Notif value is not what we expect: ${JSON.stringify(notif)} is not ${JSON.stringify(expected)} (expected) `)
|
|
61
|
+
});
|
|
62
|
+
db.sql("NOTIFY chnl , 'hello'; ");
|
|
63
|
+
} catch(e){
|
|
64
|
+
reject(e);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
59
67
|
|
|
60
68
|
await tryRunP("sql NOTICE events", async (resolve, reject) => {
|
|
61
69
|
|
|
62
70
|
const sub = await db.sql("", {}, { returnType: "noticeSubscription" });
|
|
63
|
-
|
|
71
|
+
|
|
64
72
|
sub.addListener(notice => {
|
|
65
|
-
|
|
66
|
-
if(notice.message ===
|
|
67
|
-
else reject(
|
|
73
|
+
const expected = "hello2"
|
|
74
|
+
if(notice.message === expected) resolve(true);
|
|
75
|
+
else reject(`Notice value is not what we expect: ${JSON.stringify(notice)} is not ${JSON.stringify(expected)} (expected) `)
|
|
68
76
|
});
|
|
69
77
|
db.sql(`
|
|
70
78
|
DO $$
|
|
@@ -78,7 +86,8 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
78
86
|
|
|
79
87
|
|
|
80
88
|
/* REPLICATION */
|
|
81
|
-
|
|
89
|
+
log("Started testRealtime")
|
|
90
|
+
const start = Date.now();
|
|
82
91
|
|
|
83
92
|
await db.planes.delete();
|
|
84
93
|
let inserts = new Array(100).fill(null).map((d, i) => ({ id: i, flight_number: `FN${i}`, x: Math.random(), y: i }));
|