prostgles-server 4.1.128 → 4.1.130
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/QueryStreamer.d.ts +2 -3
- package/dist/DboBuilder/QueryStreamer.d.ts.map +1 -1
- package/dist/DboBuilder/QueryStreamer.js +89 -105
- package/dist/DboBuilder/QueryStreamer.js.map +1 -1
- package/lib/DboBuilder/QueryStreamer.ts +87 -101
- package/package.json +2 -2
- package/tests/client/package-lock.json +15 -15
- package/tests/client/package.json +1 -1
- package/tests/client_only_queries.ts +54 -54
- package/tests/server/package-lock.json +3 -3
|
@@ -12,16 +12,15 @@ type ClientStreamedRequest = {
|
|
|
12
12
|
};
|
|
13
13
|
type StreamedQuery = ClientStreamedRequest & {
|
|
14
14
|
stream: QueryStreamType | undefined;
|
|
15
|
-
|
|
15
|
+
client: pg.Client | undefined;
|
|
16
16
|
onError: ((error: any) => void);
|
|
17
17
|
};
|
|
18
18
|
export declare class QueryStreamer {
|
|
19
19
|
db: DB;
|
|
20
20
|
dboBuilder: DboBuilder;
|
|
21
21
|
socketQueries: Record<string, Record<string, StreamedQuery>>;
|
|
22
|
-
pool: pg.Pool;
|
|
23
|
-
adminPool: pg.Pool;
|
|
24
22
|
constructor(dboBuilder: DboBuilder);
|
|
23
|
+
getConnection: (onError: ((err: any) => void) | undefined) => pg.Client;
|
|
25
24
|
create: (query: ClientStreamedRequest) => Promise<SocketSQLStreamServer>;
|
|
26
25
|
}
|
|
27
26
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryStreamer.d.ts","sourceRoot":"","sources":["../../lib/DboBuilder/QueryStreamer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAY,UAAU,EAAyB,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,eAAe,MAAM,iBAAiB,CAAC;AAK9C,KAAK,qBAAqB,GAAG;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,UAAU,GAAG,SAAS,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAE7B,CAAA;AACD,KAAK,aAAa,GAAG,qBAAqB,GAAG;IAC3C,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,
|
|
1
|
+
{"version":3,"file":"QueryStreamer.d.ts","sourceRoot":"","sources":["../../lib/DboBuilder/QueryStreamer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAY,UAAU,EAAyB,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,eAAe,MAAM,iBAAiB,CAAC;AAK9C,KAAK,qBAAqB,GAAG;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,UAAU,GAAG,SAAS,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAE7B,CAAA;AACD,KAAK,aAAa,GAAG,qBAAqB,GAAG;IAC3C,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,MAAM,EAAE,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC;CACjC,CAAA;AAWD,qBAAa,aAAa;IACxB,EAAE,EAAE,EAAE,CAAC;IACP,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAM;gBACtD,UAAU,EAAE,UAAU;IAKlC,aAAa,mBAAoB,GAAG,KAAK,IAAI,4BAO5C;IAED,MAAM,UAAiB,qBAAqB,KAAG,QAAQ,qBAAqB,CAAC,CAkJ5E;CACF"}
|
|
@@ -18,26 +18,18 @@ class QueryStreamer {
|
|
|
18
18
|
db;
|
|
19
19
|
dboBuilder;
|
|
20
20
|
socketQueries = {};
|
|
21
|
-
pool;
|
|
22
|
-
adminPool;
|
|
23
21
|
constructor(dboBuilder) {
|
|
24
22
|
this.dboBuilder = dboBuilder;
|
|
25
23
|
this.db = dboBuilder.db;
|
|
24
|
+
}
|
|
25
|
+
getConnection = (onError) => {
|
|
26
26
|
const connectionInfo = typeof this.db.$cn === "string" ? { connectionString: this.db.$cn } : this.db.$cn;
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this.pool = new pg.Pool({ ...connectionInfo, max: 50 }).on("error", (error) => {
|
|
31
|
-
// if(error.message !== "Connection terminated") return;
|
|
32
|
-
Object.entries(this.socketQueries).forEach(([socketId, queries]) => {
|
|
33
|
-
Object.entries(queries).forEach(([id, query]) => {
|
|
34
|
-
query.onError?.({ message: error.message });
|
|
35
|
-
delete this.socketQueries[socketId]?.[id];
|
|
36
|
-
});
|
|
37
|
-
});
|
|
27
|
+
const client = new pg.Client(connectionInfo);
|
|
28
|
+
client.on("error", (err) => {
|
|
29
|
+
onError?.(err);
|
|
38
30
|
});
|
|
39
|
-
|
|
40
|
-
}
|
|
31
|
+
return client;
|
|
32
|
+
};
|
|
41
33
|
create = async (query) => {
|
|
42
34
|
const { socket, persistConnection } = query;
|
|
43
35
|
const socketId = socket.id;
|
|
@@ -51,7 +43,7 @@ class QueryStreamer {
|
|
|
51
43
|
let errored = false;
|
|
52
44
|
const socketQuery = {
|
|
53
45
|
...query,
|
|
54
|
-
|
|
46
|
+
client: undefined,
|
|
55
47
|
stream: undefined,
|
|
56
48
|
onError: (rawError) => {
|
|
57
49
|
if (errored)
|
|
@@ -71,108 +63,100 @@ class QueryStreamer {
|
|
|
71
63
|
if (!socketQuery) {
|
|
72
64
|
throw "socket query not found";
|
|
73
65
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
66
|
+
let batchRows = [];
|
|
67
|
+
let finished = false;
|
|
68
|
+
const batchSize = 10000;
|
|
69
|
+
let stream;
|
|
70
|
+
let poolClient;
|
|
71
|
+
const emit = (type, stream) => {
|
|
72
|
+
const result = stream?._result;
|
|
73
|
+
const ended = type === "ended";
|
|
74
|
+
if (finished)
|
|
75
|
+
return;
|
|
76
|
+
finished = finished || ended;
|
|
77
|
+
if (!result?.fields)
|
|
78
|
+
throw "No fields";
|
|
79
|
+
const fields = runSQL_1.getDetailedFieldInfo.bind(this.dboBuilder)(result.fields);
|
|
80
|
+
const packet = { type: "data", rows: batchRows, fields, ended, processId: processID };
|
|
81
|
+
socket.emit(channel, packet);
|
|
82
|
+
if (ended) {
|
|
83
|
+
if (!result)
|
|
84
|
+
throw "No result info";
|
|
85
|
+
runSQL_1.watchSchemaFallback.bind(this.dboBuilder)({ queryWithoutRLS: query.query, command: result.command });
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const client = this.getConnection(err => {
|
|
89
|
+
socketQuery.onError(err);
|
|
90
|
+
client.end();
|
|
91
|
+
});
|
|
92
|
+
try {
|
|
93
|
+
await client.connect();
|
|
94
|
+
poolClient = client;
|
|
95
|
+
processID = client.processID;
|
|
96
|
+
const queryStream = new QueryStream(query.query, [], { batchSize: 1e6, highWaterMark: 1e6, rowMode: "array" });
|
|
97
|
+
stream = client.query(queryStream);
|
|
98
|
+
this.socketQueries[socketId][id].client = poolClient;
|
|
99
|
+
this.socketQueries[socketId][id].stream = stream;
|
|
100
|
+
stream.on('data', async (data) => {
|
|
101
|
+
batchRows.push(data);
|
|
102
|
+
if (options?.streamLimit) {
|
|
103
|
+
if (batchRows.length >= options.streamLimit) {
|
|
104
|
+
emit("ended", stream);
|
|
105
|
+
}
|
|
93
106
|
}
|
|
94
|
-
|
|
95
|
-
|
|
107
|
+
if (batchRows.length >= batchSize) {
|
|
108
|
+
emit("rows", stream);
|
|
109
|
+
batchRows = [];
|
|
96
110
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
111
|
+
});
|
|
112
|
+
stream.on('error', error => {
|
|
113
|
+
socketQuery.onError(error);
|
|
114
|
+
});
|
|
115
|
+
stream.on('end', () => {
|
|
116
|
+
emit("ended", stream);
|
|
117
|
+
// release the client when the stream is finished AND connection is not persisted
|
|
118
|
+
if (!options?.persistStreamConnection) {
|
|
119
|
+
delete this.socketQueries[socketId]?.[id];
|
|
120
|
+
client.end();
|
|
102
121
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (!client)
|
|
110
|
-
throw "No client";
|
|
111
|
-
poolClient = client;
|
|
112
|
-
processID = client.processID;
|
|
113
|
-
const queryStream = new QueryStream(query.query, [], { batchSize, rowMode: "array" });
|
|
114
|
-
stream = client.query(queryStream);
|
|
115
|
-
this.socketQueries[socketId][id].poolClient = poolClient;
|
|
116
|
-
this.socketQueries[socketId][id].stream = stream;
|
|
117
|
-
stream.on('data', async (data) => {
|
|
118
|
-
batchRows.push(data);
|
|
119
|
-
if (options?.streamLimit) {
|
|
120
|
-
if (batchRows.length >= options.streamLimit) {
|
|
121
|
-
emit("ended", stream);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (batchRows.length >= batchSize) {
|
|
125
|
-
emit("rows", stream);
|
|
126
|
-
batchRows = [];
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
stream.on('error', error => {
|
|
130
|
-
socketQuery.onError(error);
|
|
131
|
-
});
|
|
132
|
-
stream.on('end', () => {
|
|
133
|
-
emit("ended", stream);
|
|
134
|
-
// release the client when the stream is finished
|
|
135
|
-
if (!options?.persistStreamConnection) {
|
|
136
|
-
delete this.socketQueries[socketId]?.[id];
|
|
137
|
-
done();
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
catch (err) {
|
|
143
|
-
socketQuery.onError(err);
|
|
144
|
-
}
|
|
145
|
-
})();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
socketQuery.onError(err);
|
|
126
|
+
await client.end();
|
|
127
|
+
}
|
|
146
128
|
};
|
|
147
|
-
const stop = (opts, cb) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (!stream || !poolClient)
|
|
129
|
+
const stop = async (opts, cb) => {
|
|
130
|
+
const { stream, client: queryClient } = this.socketQueries[socketId]?.[id] ?? {};
|
|
131
|
+
if (!stream || !queryClient)
|
|
151
132
|
return;
|
|
152
|
-
this.
|
|
153
|
-
|
|
154
|
-
|
|
133
|
+
const client = this.getConnection(undefined);
|
|
134
|
+
try {
|
|
135
|
+
await client.connect();
|
|
155
136
|
if (!client)
|
|
156
137
|
return cb(null, "No client");
|
|
157
138
|
const stopFunction = opts?.terminate ? "pg_terminate_backend" : "pg_cancel_backend";
|
|
158
|
-
client.query(`SELECT ${stopFunction}(pid) FROM pg_stat_activity WHERE pid = $1`, [processID
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
});
|
|
139
|
+
const rows = await client.query(`SELECT ${stopFunction}(pid), pid, state, query FROM pg_stat_activity WHERE pid = $1 AND query = $2`, [processID, query.query]);
|
|
140
|
+
socket.removeAllListeners(unsubChannel);
|
|
141
|
+
socket.removeAllListeners(channel);
|
|
142
|
+
cb({ processID, info: rows.rows[0] });
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
cb(null, error);
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
await client.end();
|
|
149
|
+
}
|
|
170
150
|
};
|
|
171
151
|
socket.removeAllListeners(unsubChannel);
|
|
172
152
|
socket.once(unsubChannel, stop);
|
|
173
153
|
let started = false;
|
|
174
154
|
socket.removeAllListeners(channel);
|
|
175
|
-
socket.
|
|
155
|
+
socket.on(channel, async (_data, cb) => {
|
|
156
|
+
if (started) {
|
|
157
|
+
// TODO
|
|
158
|
+
return cb(null, "Already started");
|
|
159
|
+
}
|
|
176
160
|
started = true;
|
|
177
161
|
try {
|
|
178
162
|
await startStream();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryStreamer.js","sourceRoot":"","sources":["../../lib/DboBuilder/QueryStreamer.ts"],"names":[],"mappings":";;;AACA,yBAAyB;AACzB,qDAAqG;AAErG,uDAAwE;AACxE,qCAAqE;AAIrE,MAAM,WAAW,GAA2B,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAgBvE,MAAM,cAAc,GAA2B,EAAE,CAAC;AAClD,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAE,EAAE;IAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;IACzB,cAAc,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAa,aAAa;IACxB,EAAE,CAAK;IACP,UAAU,CAAa;IACvB,aAAa,GAAkD,EAAE,CAAC;IAClE,
|
|
1
|
+
{"version":3,"file":"QueryStreamer.js","sourceRoot":"","sources":["../../lib/DboBuilder/QueryStreamer.ts"],"names":[],"mappings":";;;AACA,yBAAyB;AACzB,qDAAqG;AAErG,uDAAwE;AACxE,qCAAqE;AAIrE,MAAM,WAAW,GAA2B,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAgBvE,MAAM,cAAc,GAA2B,EAAE,CAAC;AAClD,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAE,EAAE;IAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;IACzB,cAAc,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAa,aAAa;IACxB,EAAE,CAAK;IACP,UAAU,CAAa;IACvB,aAAa,GAAkD,EAAE,CAAC;IAClE,YAAY,UAAsB;QAChC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC;IAC1B,CAAC;IAED,aAAa,GAAG,CAAC,OAAyC,EAAE,EAAE;QAC5D,MAAM,cAAc,GAAG,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAA,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAU,CAAC;QAC/G,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAA;IAED,MAAM,GAAG,KAAK,EAAE,KAA4B,EAAkC,EAAE;QAC9E,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,GAAG,0BAAQ,CAAC,UAAU,KAAK,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC5D,MAAM,YAAY,GAAG,GAAG,OAAO,cAAc,CAAC;QAC9C,IAAG,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAC;YAC9C,MAAM,4BAA4B,EAAE,QAAQ,CAAC;SAC9C;QAED,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,WAAW,GAAG;YAClB,GAAG,KAAK;YACR,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,CAAC,QAAa,EAAE,EAAE;gBACzB,IAAG,OAAO;oBAAE,OAAO;gBACnB,OAAO,GAAG,IAAI,CAAC;gBAEf,MAAM,iBAAiB,GAAG,IAAA,qDAAmC,EAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACzF,gFAAgF;gBAChF,MAAM,KAAK,GAAG,EAAE,GAAG,iBAAiB,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC3D,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAkC,CAAC,CAAC;YACjF,CAAC;SACF,CAAC;QACF,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAE,CAAC,EAAE,CAAC,KAAK,WAAW,CAAC;QAClD,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;QACzB,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;QAEnB,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;YAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACvD,IAAG,CAAC,WAAW,EAAC;gBACd,MAAM,wBAAwB,CAAC;aAChC;YACD,IAAI,SAAS,GAAU,EAAE,CAAC;YAC1B,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,MAAM,SAAS,GAAG,KAAK,CAAC;YACxB,IAAI,MAAuB,CAAC;YAC5B,IAAI,UAAqB,CAAC;YAC1B,MAAM,IAAI,GAAG,CAAC,IAAsB,EAAE,MAAmC,EAAE,EAAE;gBAC3E,MAAM,MAAM,GAAG,MAAM,EAAE,OAAyD,CAAC;gBACjF,MAAM,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC;gBAC/B,IAAG,QAAQ;oBAAE,OAAO;gBACpB,QAAQ,GAAG,QAAQ,IAAI,KAAK,CAAC;gBAC7B,IAAG,CAAC,MAAM,EAAE,MAAM;oBAAE,MAAM,WAAW,CAAC;gBACtC,MAAM,MAAM,GAAG,6BAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,MAAa,CAAC,CAAC;gBAChF,MAAM,MAAM,GAA0B,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;gBAC7G,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC7B,IAAG,KAAK,EAAC;oBACP,IAAG,CAAC,MAAM;wBAAE,MAAM,gBAAgB,CAAC;oBACnC,4BAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;iBACtG;YACH,CAAC,CAAA;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE;gBACtC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACzB,MAAM,CAAC,GAAG,EAAE,CAAC;YACf,CAAC,CAAC,CAAC;YACH,IAAI;gBACF,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;gBACvB,UAAU,GAAG,MAAM,CAAC;gBACpB,SAAS,GAAI,MAAc,CAAC,SAAS,CAAA;gBACrC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC/G,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBACnC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAE,CAAC,EAAE,CAAE,CAAC,MAAM,GAAG,UAAU,CAAC;gBACvD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAE,CAAC,EAAE,CAAE,CAAC,MAAM,GAAG,MAAM,CAAC;gBACnD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBAC/B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACrB,IAAG,OAAO,EAAE,WAAW,EAAE;wBACvB,IAAG,SAAS,CAAC,MAAM,IAAI,OAAO,CAAC,WAAW,EAAC;4BACzC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;yBACvB;qBACF;oBACD,IAAI,SAAS,CAAC,MAAM,IAAI,SAAS,EAAE;wBACjC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;wBACrB,SAAS,GAAG,EAAE,CAAC;qBAChB;gBACH,CAAC,CAAC,CAAC;gBACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;oBACzB,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC7B,CAAC,CAAC,CAAC;gBAEH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACpB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBACtB,iFAAiF;oBACjF,IAAG,CAAC,OAAO,EAAE,uBAAuB,EAAC;wBACnC,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;wBAC1C,MAAM,CAAC,GAAG,EAAE,CAAC;qBACd;gBACH,CAAC,CAAC,CAAC;aACJ;YAAC,OAAM,GAAG,EAAC;gBACV,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACzB,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;aACpB;QACH,CAAC,CAAA;QAED,MAAM,IAAI,GAAG,KAAK,EAAE,IAA0C,EAAE,EAAiB,EAAE,EAAE;YACnF,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YACjF,IAAG,CAAC,MAAM,IAAI,CAAC,WAAW;gBAAE,OAAO;YACnC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI;gBACF,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;gBACvB,IAAI,CAAC,MAAM;oBAAE,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;gBAC1C,MAAM,YAAY,GAAG,IAAI,EAAE,SAAS,CAAA,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,mBAAmB,CAAC;gBACnF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,YAAY,8EAA8E,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;gBAChK,MAAM,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;gBACxC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBACnC,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aACvC;YAAC,OAAO,KAAK,EAAC;gBACb,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;aACjB;oBAAS;gBACR,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;aACpB;QACH,CAAC,CAAA;QAED,MAAM,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAEhC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAiD,EAAE,EAAiB,EAAE,EAAE;YAChG,IAAG,OAAO,EAAC;gBACT,OAAO;gBACP,OAAO,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;aACpC;YACD,OAAO,GAAG,IAAI,CAAC;YACf,IAAI;gBACF,MAAM,WAAW,EAAE,CAAC;gBACpB,EAAE,EAAE,CAAC;aACN;YAAC,OAAM,GAAG,EAAC;gBACV,EAAE,CAAC,IAAI,EAAE,GAAG,IAAI,sBAAsB,CAAC,CAAC;aACzC;QACH,CAAC,CAAC,CAAC;QAEH,qEAAqE;QACrE,UAAU,CAAC,GAAG,EAAE;YACd,IAAG,OAAO;gBAAE,OAAO;YACnB,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE;gBACZ,SAAS;YACX,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,GAAG,CAAC,CAAC;QAER,OAAO;YACL,OAAO;YACP,YAAY;SACb,CAAA;IACH,CAAC,CAAA;CACF;AArKD,sCAqKC"}
|
|
@@ -19,7 +19,7 @@ type ClientStreamedRequest = {
|
|
|
19
19
|
}
|
|
20
20
|
type StreamedQuery = ClientStreamedRequest & {
|
|
21
21
|
stream: QueryStreamType | undefined;
|
|
22
|
-
|
|
22
|
+
client: pg.Client | undefined;
|
|
23
23
|
onError: ((error: any) => void);
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -36,25 +36,18 @@ export class QueryStreamer {
|
|
|
36
36
|
db: DB;
|
|
37
37
|
dboBuilder: DboBuilder;
|
|
38
38
|
socketQueries: Record<string, Record<string, StreamedQuery>> = {};
|
|
39
|
-
pool: pg.Pool;
|
|
40
|
-
adminPool: pg.Pool;
|
|
41
39
|
constructor(dboBuilder: DboBuilder) {
|
|
42
40
|
this.dboBuilder = dboBuilder;
|
|
43
41
|
this.db = dboBuilder.db;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getConnection = (onError: ((err: any) => void) | undefined) => {
|
|
44
45
|
const connectionInfo = typeof this.db.$cn === "string"? { connectionString: this.db.$cn } : this.db.$cn as any;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.pool = new pg.Pool({ ...connectionInfo, max: 50 }).on("error", (error) => {
|
|
49
|
-
// if(error.message !== "Connection terminated") return;
|
|
50
|
-
Object.entries(this.socketQueries).forEach(([socketId, queries]) => {
|
|
51
|
-
Object.entries(queries).forEach(([id, query]) => {
|
|
52
|
-
query.onError?.({ message: error.message });
|
|
53
|
-
delete this.socketQueries[socketId]?.[id];
|
|
54
|
-
});
|
|
55
|
-
});
|
|
46
|
+
const client = new pg.Client(connectionInfo);
|
|
47
|
+
client.on("error", (err) => {
|
|
48
|
+
onError?.(err);
|
|
56
49
|
});
|
|
57
|
-
|
|
50
|
+
return client;
|
|
58
51
|
}
|
|
59
52
|
|
|
60
53
|
create = async (query: ClientStreamedRequest): Promise<SocketSQLStreamServer> => {
|
|
@@ -71,7 +64,7 @@ export class QueryStreamer {
|
|
|
71
64
|
let errored = false;
|
|
72
65
|
const socketQuery = {
|
|
73
66
|
...query,
|
|
74
|
-
|
|
67
|
+
client: undefined,
|
|
75
68
|
stream: undefined,
|
|
76
69
|
onError: (rawError: any) => {
|
|
77
70
|
if(errored) return;
|
|
@@ -86,101 +79,90 @@ export class QueryStreamer {
|
|
|
86
79
|
this.socketQueries[socketId]![id] ??= socketQuery;
|
|
87
80
|
const { options } = query
|
|
88
81
|
let processID = -1;
|
|
82
|
+
|
|
89
83
|
const startStream = async () => {
|
|
90
84
|
const socketQuery = this.socketQueries[socketId]?.[id];
|
|
91
85
|
if(!socketQuery){
|
|
92
86
|
throw "socket query not found";
|
|
87
|
+
}
|
|
88
|
+
let batchRows: any[] = [];
|
|
89
|
+
let finished = false;
|
|
90
|
+
const batchSize = 10000;
|
|
91
|
+
let stream: QueryStreamType;
|
|
92
|
+
let poolClient: pg.Client;
|
|
93
|
+
const emit = (type: "rows" | "ended", stream: QueryStreamType | undefined) => {
|
|
94
|
+
const result = stream?._result as { command: string; fields: any[] } | undefined;
|
|
95
|
+
const ended = type === "ended";
|
|
96
|
+
if(finished) return;
|
|
97
|
+
finished = finished || ended;
|
|
98
|
+
if(!result?.fields) throw "No fields";
|
|
99
|
+
const fields = getDetailedFieldInfo.bind(this.dboBuilder)(result.fields as any);
|
|
100
|
+
const packet: SocketSQLStreamPacket = { type: "data", rows: batchRows, fields, ended, processId: processID };
|
|
101
|
+
socket.emit(channel, packet);
|
|
102
|
+
if(ended){
|
|
103
|
+
if(!result) throw "No result info";
|
|
104
|
+
watchSchemaFallback.bind(this.dboBuilder)({ queryWithoutRLS: query.query, command: result.command });
|
|
105
|
+
}
|
|
93
106
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
packet = { type: "rows", rows: batchRows, ended };
|
|
107
|
+
const client = this.getConnection(err => {
|
|
108
|
+
socketQuery.onError(err);
|
|
109
|
+
client.end();
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
await client.connect();
|
|
113
|
+
poolClient = client;
|
|
114
|
+
processID = (client as any).processID
|
|
115
|
+
const queryStream = new QueryStream(query.query, [], { batchSize: 1e6, highWaterMark: 1e6, rowMode: "array" });
|
|
116
|
+
stream = client.query(queryStream);
|
|
117
|
+
this.socketQueries[socketId]![id]!.client = poolClient;
|
|
118
|
+
this.socketQueries[socketId]![id]!.stream = stream;
|
|
119
|
+
stream.on('data', async (data) => {
|
|
120
|
+
batchRows.push(data);
|
|
121
|
+
if(options?.streamLimit) {
|
|
122
|
+
if(batchRows.length >= options.streamLimit){
|
|
123
|
+
emit("ended", stream);
|
|
124
|
+
}
|
|
113
125
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
watchSchemaFallback.bind(this.dboBuilder)({ queryWithoutRLS: query.query, command: result.command });
|
|
126
|
+
if (batchRows.length >= batchSize) {
|
|
127
|
+
emit("rows", stream);
|
|
128
|
+
batchRows = [];
|
|
118
129
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if(batchRows.length >= options.streamLimit){
|
|
137
|
-
emit("ended", stream);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (batchRows.length >= batchSize) {
|
|
141
|
-
emit("rows", stream);
|
|
142
|
-
batchRows = [];
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
stream.on('error', error => {
|
|
146
|
-
socketQuery.onError(error);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
stream.on('end', () => {
|
|
150
|
-
emit("ended", stream);
|
|
151
|
-
// release the client when the stream is finished
|
|
152
|
-
if(!options?.persistStreamConnection){
|
|
153
|
-
delete this.socketQueries[socketId]?.[id];
|
|
154
|
-
done();
|
|
155
|
-
}
|
|
156
|
-
})
|
|
157
|
-
});
|
|
158
|
-
} catch(err){
|
|
159
|
-
socketQuery.onError(err);
|
|
160
|
-
}
|
|
161
|
-
})();
|
|
130
|
+
});
|
|
131
|
+
stream.on('error', error => {
|
|
132
|
+
socketQuery.onError(error);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
stream.on('end', () => {
|
|
136
|
+
emit("ended", stream);
|
|
137
|
+
// release the client when the stream is finished AND connection is not persisted
|
|
138
|
+
if(!options?.persistStreamConnection){
|
|
139
|
+
delete this.socketQueries[socketId]?.[id];
|
|
140
|
+
client.end();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
} catch(err){
|
|
144
|
+
socketQuery.onError(err);
|
|
145
|
+
await client.end();
|
|
146
|
+
}
|
|
162
147
|
}
|
|
163
148
|
|
|
164
|
-
const stop = (opts: { terminate?: boolean; } | undefined, cb: BasicCallback) => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
149
|
+
const stop = async (opts: { terminate?: boolean; } | undefined, cb: BasicCallback) => {
|
|
150
|
+
const { stream, client: queryClient } = this.socketQueries[socketId]?.[id] ?? {};
|
|
151
|
+
if(!stream || !queryClient) return;
|
|
152
|
+
const client = this.getConnection(undefined);
|
|
153
|
+
try {
|
|
154
|
+
await client.connect();
|
|
170
155
|
if (!client) return cb(null, "No client");
|
|
171
156
|
const stopFunction = opts?.terminate? "pg_terminate_backend" : "pg_cancel_backend";
|
|
172
|
-
client.query(`SELECT ${stopFunction}(pid) FROM pg_stat_activity WHERE pid = $1`, [processID
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
done();
|
|
182
|
-
});
|
|
183
|
-
});
|
|
157
|
+
const rows = await client.query(`SELECT ${stopFunction}(pid), pid, state, query FROM pg_stat_activity WHERE pid = $1 AND query = $2`, [processID, query.query]);
|
|
158
|
+
socket.removeAllListeners(unsubChannel);
|
|
159
|
+
socket.removeAllListeners(channel);
|
|
160
|
+
cb({ processID, info: rows.rows[0] });
|
|
161
|
+
} catch (error){
|
|
162
|
+
cb(null, error);
|
|
163
|
+
} finally {
|
|
164
|
+
await client.end();
|
|
165
|
+
}
|
|
184
166
|
}
|
|
185
167
|
|
|
186
168
|
socket.removeAllListeners(unsubChannel);
|
|
@@ -188,7 +170,11 @@ export class QueryStreamer {
|
|
|
188
170
|
|
|
189
171
|
let started = false;
|
|
190
172
|
socket.removeAllListeners(channel);
|
|
191
|
-
socket.
|
|
173
|
+
socket.on(channel, async (_data: { query: string; params: any } | undefined, cb: BasicCallback) => {
|
|
174
|
+
if(started){
|
|
175
|
+
// TODO
|
|
176
|
+
return cb(null, "Already started");
|
|
177
|
+
}
|
|
192
178
|
started = true;
|
|
193
179
|
try {
|
|
194
180
|
await startStream();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prostgles-server",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.130",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"pg-promise": "^11.5.4",
|
|
47
47
|
"pg-query-stream": "^4.5.3",
|
|
48
48
|
"prostgles-client": "^4.0.53",
|
|
49
|
-
"prostgles-types": "^4.0.
|
|
49
|
+
"prostgles-types": "^4.0.67"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/bluebird": "^3.5.36",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@types/node": "^14.14.16",
|
|
13
|
-
"prostgles-client": "^4.0.
|
|
13
|
+
"prostgles-client": "^4.0.62",
|
|
14
14
|
"prostgles-types": "^4.0.51",
|
|
15
15
|
"socket.io-client": "^4.7.1"
|
|
16
16
|
},
|
|
@@ -75,11 +75,11 @@
|
|
|
75
75
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
76
76
|
},
|
|
77
77
|
"node_modules/prostgles-client": {
|
|
78
|
-
"version": "4.0.
|
|
79
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.
|
|
80
|
-
"integrity": "sha512-
|
|
78
|
+
"version": "4.0.62",
|
|
79
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.62.tgz",
|
|
80
|
+
"integrity": "sha512-0tSymKQWkf5hShxyw3kbBzs0wVqwzFYYRqWWTV8zCJGuCLfoKCqhUU6BY257ZAuhRBmMClTa430JR1PccXVYvw==",
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"prostgles-types": "^4.0.
|
|
82
|
+
"prostgles-types": "^4.0.67"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
85
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
@@ -91,9 +91,9 @@
|
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
93
|
"node_modules/prostgles-types": {
|
|
94
|
-
"version": "4.0.
|
|
95
|
-
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.
|
|
96
|
-
"integrity": "sha512-
|
|
94
|
+
"version": "4.0.67",
|
|
95
|
+
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.67.tgz",
|
|
96
|
+
"integrity": "sha512-KOZ+q3apiwmn+97PAGYpdH6EZwOSpA4OmzZX6fzbzGLG2spE1ghrakQIBGa7HqwuuIoejQInKWbRCs4Arm1n6A==",
|
|
97
97
|
"dependencies": {
|
|
98
98
|
"json-schema": "^0.4.0"
|
|
99
99
|
}
|
|
@@ -213,17 +213,17 @@
|
|
|
213
213
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
214
214
|
},
|
|
215
215
|
"prostgles-client": {
|
|
216
|
-
"version": "4.0.
|
|
217
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.
|
|
218
|
-
"integrity": "sha512-
|
|
216
|
+
"version": "4.0.62",
|
|
217
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.62.tgz",
|
|
218
|
+
"integrity": "sha512-0tSymKQWkf5hShxyw3kbBzs0wVqwzFYYRqWWTV8zCJGuCLfoKCqhUU6BY257ZAuhRBmMClTa430JR1PccXVYvw==",
|
|
219
219
|
"requires": {
|
|
220
|
-
"prostgles-types": "^4.0.
|
|
220
|
+
"prostgles-types": "^4.0.67"
|
|
221
221
|
}
|
|
222
222
|
},
|
|
223
223
|
"prostgles-types": {
|
|
224
|
-
"version": "4.0.
|
|
225
|
-
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.
|
|
226
|
-
"integrity": "sha512-
|
|
224
|
+
"version": "4.0.67",
|
|
225
|
+
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.67.tgz",
|
|
226
|
+
"integrity": "sha512-KOZ+q3apiwmn+97PAGYpdH6EZwOSpA4OmzZX6fzbzGLG2spE1ghrakQIBGa7HqwuuIoejQInKWbRCs4Arm1n6A==",
|
|
227
227
|
"requires": {
|
|
228
228
|
"json-schema": "^0.4.0"
|
|
229
229
|
}
|
|
@@ -5,6 +5,57 @@ import { tryRun, tryRunP } from './isomorphic_queries';
|
|
|
5
5
|
import { reject } from 'bluebird';
|
|
6
6
|
|
|
7
7
|
export default async function client_only(db: DBHandlerClient, auth: Auth, log: (...args: any[]) => any, methods, tableSchema: DBSchemaTable[], token: string){
|
|
8
|
+
|
|
9
|
+
await tryRunP("SQL Stream stop kills the query", async (resolve, reject) => {
|
|
10
|
+
const query = "SELECT * FROM pg_sleep(5)"
|
|
11
|
+
const res = await db.sql!(query, {}, { returnType: "stream" });
|
|
12
|
+
const listener = async (packet: SocketSQLStreamPacket) => {
|
|
13
|
+
if(packet.type === "error"){
|
|
14
|
+
const queryState = await db.sql!("SELECT * FROM pg_stat_activity WHERE query = $1", [query], { returnType: "rows" });
|
|
15
|
+
assert.equal(queryState.length, 1);
|
|
16
|
+
assert.equal(queryState[0].state, "idle");
|
|
17
|
+
assert.equal(packet.error.message, "canceling statement due to user request");
|
|
18
|
+
resolve("ok");
|
|
19
|
+
} else {
|
|
20
|
+
assert.equal(packet.type, "data");
|
|
21
|
+
assert.equal(packet.ended, true);
|
|
22
|
+
assert.deepStrictEqual(packet.rows, []);
|
|
23
|
+
reject("ok");
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const startHandler = await res.start(listener);
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
startHandler.stop().catch(reject);
|
|
29
|
+
}, 1000);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
await tryRunP("SQL Stream stop with terminate kills the query", async (resolve, reject) => {
|
|
33
|
+
const totalRows = 5e6;
|
|
34
|
+
const query = `SELECT * FROM generate_series(1, ${totalRows})`;
|
|
35
|
+
const res = await db.sql!(query, {}, { returnType: "stream" });
|
|
36
|
+
const rowsReceived: any[] = [];
|
|
37
|
+
const listener = async (packet: SocketSQLStreamPacket) => {
|
|
38
|
+
if(packet.type === "error"){
|
|
39
|
+
const queryState = await db.sql!("SELECT * FROM pg_stat_activity WHERE query = $1", [query], { returnType: "rows" });
|
|
40
|
+
assert.equal(queryState.length, 0);
|
|
41
|
+
resolve("ok");
|
|
42
|
+
} else {
|
|
43
|
+
try {
|
|
44
|
+
rowsReceived.push(...packet.rows);
|
|
45
|
+
console.log(rowsReceived.length)
|
|
46
|
+
assert.equal(packet.ended, false);
|
|
47
|
+
assert.equal(rowsReceived.length < totalRows, true);
|
|
48
|
+
} catch(error){
|
|
49
|
+
reject(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const startHandler = await res.start(listener);
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
startHandler.stop(true).catch(reject);
|
|
56
|
+
}, 22);
|
|
57
|
+
});
|
|
58
|
+
|
|
8
59
|
await Promise.all([1e3, 1e2].map(async (numberOfRows) => {
|
|
9
60
|
await tryRunP("SQL Stream", async (resolve) => {
|
|
10
61
|
const res = await db.sql!(`SELECT v.* FROM generate_series(1, ${numberOfRows}) v`, {}, { returnType: "stream" });
|
|
@@ -28,7 +79,7 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
28
79
|
const res = await db.sql!("SELECT ${val} as val", { val }, { returnType: "stream" });
|
|
29
80
|
const listener = async (packet: SocketSQLStreamPacket) => {
|
|
30
81
|
try {
|
|
31
|
-
assert.equal(packet.type, "
|
|
82
|
+
assert.equal(packet.type, "data");
|
|
32
83
|
assert.equal(packet.ended, true);
|
|
33
84
|
assert.deepStrictEqual(packet.rows, [[val]]);
|
|
34
85
|
resolve(1);
|
|
@@ -72,7 +123,7 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
72
123
|
if(packet.type === "error"){
|
|
73
124
|
reject(packet.error);
|
|
74
125
|
} else {
|
|
75
|
-
assert.equal(packet.type, "
|
|
126
|
+
assert.equal(packet.type, "data");
|
|
76
127
|
assert.equal(packet.ended, true);
|
|
77
128
|
assert.equal(packet.rows.length, 10);
|
|
78
129
|
|
|
@@ -99,7 +150,7 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
99
150
|
if(packet.type === "error"){
|
|
100
151
|
reject(packet.error);
|
|
101
152
|
} else {
|
|
102
|
-
assert.equal(packet.type, "
|
|
153
|
+
assert.equal(packet.type, "data");
|
|
103
154
|
assert.equal(packet.ended, true);
|
|
104
155
|
assert.equal(packet.rows.length, 1);
|
|
105
156
|
const normalSql = await db.sql!("SELECT * FROM planes LIMIT 1", {});
|
|
@@ -112,57 +163,6 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
112
163
|
await res.start(listener);
|
|
113
164
|
});
|
|
114
165
|
|
|
115
|
-
await tryRunP("SQL Stream stop kills the query", async (resolve, reject) => {
|
|
116
|
-
const query = "SELECT * FROM pg_sleep(5)"
|
|
117
|
-
const res = await db.sql!(query, {}, { returnType: "stream" });
|
|
118
|
-
const listener = async (packet: SocketSQLStreamPacket) => {
|
|
119
|
-
if(packet.type === "error"){
|
|
120
|
-
const queryState = await db.sql!("SELECT * FROM pg_stat_activity WHERE query = $1", [query], { returnType: "rows" });
|
|
121
|
-
assert.equal(queryState.length, 1);
|
|
122
|
-
assert.equal(queryState[0].state, "idle");
|
|
123
|
-
assert.equal(packet.error.message, "canceling statement due to user request");
|
|
124
|
-
resolve("ok");
|
|
125
|
-
} else {
|
|
126
|
-
assert.equal(packet.type, "start");
|
|
127
|
-
assert.equal(packet.ended, true);
|
|
128
|
-
assert.deepStrictEqual(packet.rows, []);
|
|
129
|
-
reject("ok");
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
const startHandler = await res.start(listener);
|
|
133
|
-
setTimeout(() => {
|
|
134
|
-
startHandler.stop().catch(reject);
|
|
135
|
-
}, 1000);
|
|
136
|
-
});
|
|
137
|
-
// await tryRunP("SQL Stream stop with terminate kills the query", async (resolve, reject) => {
|
|
138
|
-
// const totalRows = 5e6;
|
|
139
|
-
// const query = `SELECT * FROM generate_series(1, ${totalRows})`;
|
|
140
|
-
// const res = await db.sql!(query, {}, { returnType: "stream" });
|
|
141
|
-
// const rowsReceived: any[] = [];
|
|
142
|
-
// const listener = async (packet: SocketSQLStreamPacket) => {
|
|
143
|
-
// if(packet.type === "error"){
|
|
144
|
-
// const queryState = await db.sql!("SELECT * FROM pg_stat_activity WHERE query = $1", [query], { returnType: "rows" });
|
|
145
|
-
// assert.equal(queryState.length, 1);
|
|
146
|
-
// assert.equal(queryState[0].state, "idle");
|
|
147
|
-
// assert.equal(packet.error.message, "canceling statement due to user request");
|
|
148
|
-
// resolve("ok");
|
|
149
|
-
// } else {
|
|
150
|
-
// try {
|
|
151
|
-
// rowsReceived.push(...packet.rows);
|
|
152
|
-
// console.log(rowsReceived.length)
|
|
153
|
-
// assert.equal(packet.ended, false);
|
|
154
|
-
// assert.equal(rowsReceived.length < totalRows, true);
|
|
155
|
-
// } catch(error){
|
|
156
|
-
// reject(error);
|
|
157
|
-
// }
|
|
158
|
-
// }
|
|
159
|
-
// };
|
|
160
|
-
// const startHandler = await res.start(listener);
|
|
161
|
-
// setTimeout(() => {
|
|
162
|
-
// startHandler.stop(true).catch(reject);
|
|
163
|
-
// }, 22);
|
|
164
|
-
// });
|
|
165
|
-
|
|
166
166
|
// await tryRunP("SQL Stream ensure the connection is never released (same pg_backend_pid is the same for subsequent) queries when using persistConnectionId", async (resolve, reject) => {
|
|
167
167
|
// const res = await db.sql!("SELECT pg_backend_pid()", {}, { returnType: "stream", persistConnectionId: true });
|
|
168
168
|
// const listener = async (packet: SocketSQLStreamPacket) => {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"../..": {
|
|
23
23
|
"name": "prostgles-server",
|
|
24
|
-
"version": "4.1.
|
|
24
|
+
"version": "4.1.129",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@types/express": "^4.17.13",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"pg-promise": "^11.5.4",
|
|
36
36
|
"pg-query-stream": "^4.5.3",
|
|
37
37
|
"prostgles-client": "^4.0.53",
|
|
38
|
-
"prostgles-types": "^4.0.
|
|
38
|
+
"prostgles-types": "^4.0.67"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/bluebird": "^3.5.36",
|
|
@@ -1546,7 +1546,7 @@
|
|
|
1546
1546
|
"pg-promise": "^11.5.4",
|
|
1547
1547
|
"pg-query-stream": "^4.5.3",
|
|
1548
1548
|
"prostgles-client": "^4.0.53",
|
|
1549
|
-
"prostgles-types": "^4.0.
|
|
1549
|
+
"prostgles-types": "^4.0.67",
|
|
1550
1550
|
"typescript": "^5.2.2"
|
|
1551
1551
|
}
|
|
1552
1552
|
},
|