prostgles-server 4.1.127 → 4.1.129

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.
@@ -12,15 +12,15 @@ type ClientStreamedRequest = {
12
12
  };
13
13
  type StreamedQuery = ClientStreamedRequest & {
14
14
  stream: QueryStreamType | undefined;
15
- poolClient: pg.PoolClient | undefined;
15
+ client: pg.Client | undefined;
16
+ onError: ((error: any) => void);
16
17
  };
17
18
  export declare class QueryStreamer {
18
19
  db: DB;
19
20
  dboBuilder: DboBuilder;
20
21
  socketQueries: Record<string, Record<string, StreamedQuery>>;
21
- pool: pg.Pool;
22
- adminPool: pg.Pool;
23
22
  constructor(dboBuilder: DboBuilder);
23
+ getConnection: (onError: ((err: any) => void) | undefined) => pg.Client;
24
24
  create: (query: ClientStreamedRequest) => Promise<SocketSQLStreamServer>;
25
25
  }
26
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,EAAuB,UAAU,EAAyB,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAChH,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,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC;CACvC,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;IAClE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC;gBACP,UAAU,EAAE,UAAU;IAOlC,MAAM,UAAiB,qBAAqB,KAAG,QAAQ,qBAAqB,CAAC,CAkJ5E;CACF"}
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,CAqJ5E;CACF"}
@@ -18,14 +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;
26
- this.pool = new pg.Pool(typeof this.db.$cn === "string" ? { connectionString: this.db.$cn } : this.db.$cn);
27
- this.adminPool = new pg.Pool(typeof this.db.$cn === "string" ? { connectionString: this.db.$cn } : this.db.$cn);
28
24
  }
25
+ getConnection = (onError) => {
26
+ const connectionInfo = typeof this.db.$cn === "string" ? { connectionString: this.db.$cn } : this.db.$cn;
27
+ const client = new pg.Client(connectionInfo);
28
+ client.on("error", (err) => {
29
+ onError?.(err);
30
+ });
31
+ return client;
32
+ };
29
33
  create = async (query) => {
30
34
  const { socket, persistConnection } = query;
31
35
  const socketId = socket.id;
@@ -36,11 +40,22 @@ class QueryStreamer {
36
40
  throw `Must stop existing query ${id} first`;
37
41
  }
38
42
  this.socketQueries[socketId] ??= {};
39
- this.socketQueries[socketId][id] ??= {
43
+ let errored = false;
44
+ const socketQuery = {
40
45
  ...query,
41
- poolClient: undefined,
46
+ client: undefined,
42
47
  stream: undefined,
48
+ onError: (rawError) => {
49
+ if (errored)
50
+ return;
51
+ errored = true;
52
+ const errorWithoutQuery = (0, dboBuilderUtils_1.getSerializedClientErrorFromPGError)(rawError, { type: "sql" });
53
+ // For some reason query is not present on the error object from sql stream mode
54
+ const error = { ...errorWithoutQuery, query: query.query };
55
+ socket.emit(channel, { type: "error", error });
56
+ },
43
57
  };
58
+ this.socketQueries[socketId][id] ??= socketQuery;
44
59
  const { options } = query;
45
60
  let processID = -1;
46
61
  const startStream = async () => {
@@ -48,107 +63,98 @@ class QueryStreamer {
48
63
  if (!socketQuery) {
49
64
  throw "socket query not found";
50
65
  }
51
- (async () => {
52
- let emittedPackets = 0;
53
- let batchRows = [];
54
- let finished = false;
55
- const batchSize = 10000;
56
- let stream;
57
- let poolClient;
58
- const emit = (type, rawError, stream) => {
59
- const result = stream?._result;
60
- let packet;
61
- const ended = type === "ended";
62
- if (finished)
63
- return;
64
- finished = finished || ended;
65
- if (type === "error") {
66
- const errorWithoutQuery = (0, dboBuilderUtils_1.getSerializedClientErrorFromPGError)(rawError, { type: "sql" });
67
- // For some reason query is not present on the error object from sql stream mode
68
- const error = { ...errorWithoutQuery, query: query.query };
69
- packet = { type: "error", error };
70
- }
71
- else if (!emittedPackets) {
72
- if (!result?.fields)
73
- throw "No fields";
74
- const fields = runSQL_1.getDetailedFieldInfo.bind(this.dboBuilder)(result.fields);
75
- packet = { type: "start", rows: batchRows, fields, ended, processId: processID };
66
+ let emittedPackets = 0;
67
+ let batchRows = [];
68
+ let finished = false;
69
+ const batchSize = 10000;
70
+ let stream;
71
+ let poolClient;
72
+ const emit = (type, stream) => {
73
+ const result = stream?._result;
74
+ let packet;
75
+ const ended = type === "ended";
76
+ if (finished)
77
+ return;
78
+ finished = finished || ended;
79
+ if (!emittedPackets) {
80
+ if (!result?.fields)
81
+ throw "No fields";
82
+ const fields = runSQL_1.getDetailedFieldInfo.bind(this.dboBuilder)(result.fields);
83
+ packet = { type: "start", rows: batchRows, fields, ended, processId: processID };
84
+ }
85
+ else {
86
+ packet = { type: "rows", rows: batchRows, ended };
87
+ }
88
+ socket.emit(channel, packet);
89
+ if (ended) {
90
+ if (!result)
91
+ throw "No result info";
92
+ runSQL_1.watchSchemaFallback.bind(this.dboBuilder)({ queryWithoutRLS: query.query, command: result.command });
93
+ }
94
+ emittedPackets++;
95
+ };
96
+ const client = this.getConnection(err => {
97
+ socketQuery.onError(err);
98
+ client.end();
99
+ });
100
+ try {
101
+ await client.connect();
102
+ poolClient = client;
103
+ processID = client.processID;
104
+ const queryStream = new QueryStream(query.query, [], { batchSize: 1e6, highWaterMark: 1e6, rowMode: "array" });
105
+ stream = client.query(queryStream);
106
+ this.socketQueries[socketId][id].client = poolClient;
107
+ this.socketQueries[socketId][id].stream = stream;
108
+ stream.on('data', async (data) => {
109
+ batchRows.push(data);
110
+ if (options?.streamLimit) {
111
+ if (batchRows.length >= options.streamLimit) {
112
+ emit("ended", stream);
113
+ }
76
114
  }
77
- else {
78
- packet = { type: "rows", rows: batchRows, ended };
115
+ if (batchRows.length >= batchSize) {
116
+ emit("rows", stream);
117
+ batchRows = [];
79
118
  }
80
- socket.emit(channel, packet);
81
- if (ended) {
82
- if (!result)
83
- throw "No result info";
84
- runSQL_1.watchSchemaFallback.bind(this.dboBuilder)({ queryWithoutRLS: query.query, command: result.command });
119
+ });
120
+ stream.on('error', error => {
121
+ socketQuery.onError(error);
122
+ });
123
+ stream.on('end', () => {
124
+ emit("ended", stream);
125
+ // release the client when the stream is finished AND connection is not persisted
126
+ if (!options?.persistStreamConnection) {
127
+ delete this.socketQueries[socketId]?.[id];
128
+ client.end();
85
129
  }
86
- emittedPackets++;
87
- };
88
- try {
89
- await this.pool.connect((err, client, done) => {
90
- if (err)
91
- throw err;
92
- if (!client)
93
- throw "No client";
94
- poolClient = client;
95
- processID = client.processID;
96
- const queryStream = new QueryStream(query.query, [], { batchSize, rowMode: "array" });
97
- stream = client.query(queryStream);
98
- this.socketQueries[socketId][id].poolClient = 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", undefined, stream);
105
- }
106
- }
107
- if (batchRows.length >= batchSize) {
108
- emit("rows", undefined, stream);
109
- batchRows = [];
110
- }
111
- });
112
- stream.on('error', error => {
113
- emit("error", error, stream);
114
- });
115
- stream.on('end', () => {
116
- emit("ended", undefined, stream);
117
- // release the client when the stream is finished
118
- if (!options?.persistStreamConnection) {
119
- delete this.socketQueries[socketId]?.[id];
120
- done();
121
- }
122
- });
123
- });
124
- }
125
- catch (err) {
126
- emit("error", err, undefined);
127
- }
128
- })();
130
+ });
131
+ }
132
+ catch (err) {
133
+ socketQuery.onError(err);
134
+ await client.end();
135
+ }
129
136
  };
130
- const stop = (_data, cb) => {
131
- // Must kill query if not ended
132
- const { stream, poolClient } = this.socketQueries[socketId]?.[id] ?? {};
137
+ const stop = async (opts, cb) => {
138
+ const { stream, client: poolClient } = this.socketQueries[socketId]?.[id] ?? {};
133
139
  if (!stream || !poolClient)
134
140
  return;
135
- this.adminPool.connect(async (err, client, done) => {
136
- if (err)
137
- return cb(null, err);
141
+ const client = this.getConnection(undefined);
142
+ try {
143
+ await client.connect();
138
144
  if (!client)
139
145
  return cb(null, "No client");
140
- client.query(`SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE pid = $1`, [processID], (err) => {
141
- if (err) {
142
- cb(null, err);
143
- console.error(err);
144
- }
145
- delete this.socketQueries[socketId]?.[id];
146
- poolClient.release();
147
- socket.removeAllListeners(unsubChannel);
148
- socket.removeAllListeners(channel);
149
- done();
150
- });
151
- });
146
+ const stopFunction = opts?.terminate ? "pg_terminate_backend" : "pg_cancel_backend";
147
+ const rows = await client.query(`SELECT ${stopFunction}(pid), pid, state, query FROM pg_stat_activity WHERE pid = $1 AND query = $2`, [processID, query.query]);
148
+ socket.removeAllListeners(unsubChannel);
149
+ socket.removeAllListeners(channel);
150
+ cb({ processID, info: rows.rows[0] });
151
+ }
152
+ catch (error) {
153
+ cb(null, error);
154
+ }
155
+ finally {
156
+ await client.end();
157
+ }
152
158
  };
153
159
  socket.removeAllListeners(unsubChannel);
154
160
  socket.once(unsubChannel, stop);
@@ -168,7 +174,7 @@ class QueryStreamer {
168
174
  setTimeout(() => {
169
175
  if (started)
170
176
  return;
171
- stop(null, () => {
177
+ stop({}, () => {
172
178
  // empty
173
179
  });
174
180
  }, 5e3);
@@ -1 +1 @@
1
- {"version":3,"file":"QueryStreamer.js","sourceRoot":"","sources":["../../lib/DboBuilder/QueryStreamer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QueryStreamer.js","sourceRoot":"","sources":["../../lib/DboBuilder/QueryStreamer.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { DB } from "../initProstgles";
2
2
  import * as pg from "pg";
3
- import { AnyObject, CHANNELS, SQLOptions, SocketSQLStreamPacket, SocketSQLStreamServer } from "prostgles-types";
3
+ import { CHANNELS, SQLOptions, SocketSQLStreamPacket, SocketSQLStreamServer } from "prostgles-types";
4
4
  import { PRGLIOSocket } from "./DboBuilderTypes";
5
5
  import { getSerializedClientErrorFromPGError } from "./dboBuilderUtils";
6
6
  import { getDetailedFieldInfo, watchSchemaFallback } from "./runSQL";
@@ -19,7 +19,8 @@ type ClientStreamedRequest = {
19
19
  }
20
20
  type StreamedQuery = ClientStreamedRequest & {
21
21
  stream: QueryStreamType | undefined;
22
- poolClient: pg.PoolClient | undefined;
22
+ client: pg.Client | undefined;
23
+ onError: ((error: any) => void);
23
24
  }
24
25
 
25
26
  const shortSocketIds: Record<string, number> = {};
@@ -35,13 +36,18 @@ export class QueryStreamer {
35
36
  db: DB;
36
37
  dboBuilder: DboBuilder;
37
38
  socketQueries: Record<string, Record<string, StreamedQuery>> = {};
38
- pool: pg.Pool;
39
- adminPool: pg.Pool;
40
39
  constructor(dboBuilder: DboBuilder) {
41
40
  this.dboBuilder = dboBuilder;
42
41
  this.db = dboBuilder.db;
43
- this.pool = new pg.Pool( typeof this.db.$cn === "string"? { connectionString: this.db.$cn } : this.db.$cn as any);
44
- this.adminPool = new pg.Pool( typeof this.db.$cn === "string"? { connectionString: this.db.$cn } : this.db.$cn as any);
42
+ }
43
+
44
+ getConnection = (onError: ((err: any) => void) | undefined) => {
45
+ const connectionInfo = typeof this.db.$cn === "string"? { connectionString: this.db.$cn } : this.db.$cn as any;
46
+ const client = new pg.Client(connectionInfo);
47
+ client.on("error", (err) => {
48
+ onError?.(err);
49
+ });
50
+ return client;
45
51
  }
46
52
 
47
53
  create = async (query: ClientStreamedRequest): Promise<SocketSQLStreamServer> => {
@@ -54,113 +60,116 @@ export class QueryStreamer {
54
60
  throw `Must stop existing query ${id} first`;
55
61
  }
56
62
 
57
- this.socketQueries[socketId] ??= {}
58
- this.socketQueries[socketId]![id] ??= {
63
+ this.socketQueries[socketId] ??= {};
64
+ let errored = false;
65
+ const socketQuery = {
59
66
  ...query,
60
- poolClient: undefined,
67
+ client: undefined,
61
68
  stream: undefined,
69
+ onError: (rawError: any) => {
70
+ if(errored) return;
71
+ errored = true;
72
+
73
+ const errorWithoutQuery = getSerializedClientErrorFromPGError(rawError, { type: "sql" });
74
+ // For some reason query is not present on the error object from sql stream mode
75
+ const error = { ...errorWithoutQuery, query: query.query };
76
+ socket.emit(channel, { type: "error", error } satisfies SocketSQLStreamPacket);
77
+ },
62
78
  };
79
+ this.socketQueries[socketId]![id] ??= socketQuery;
63
80
  const { options } = query
64
81
  let processID = -1;
82
+
65
83
  const startStream = async () => {
66
84
  const socketQuery = this.socketQueries[socketId]?.[id];
67
85
  if(!socketQuery){
68
86
  throw "socket query not found";
87
+ }
88
+ let emittedPackets = 0;
89
+ let batchRows: any[] = [];
90
+ let finished = false;
91
+ const batchSize = 10000;
92
+ let stream: QueryStreamType;
93
+ let poolClient: pg.Client;
94
+ const emit = (type: "rows" | "ended", stream: QueryStreamType | undefined) => {
95
+ const result = stream?._result as { command: string; fields: any[] } | undefined;
96
+ let packet: SocketSQLStreamPacket | undefined;
97
+ const ended = type === "ended";
98
+ if(finished) return;
99
+ finished = finished || ended;
100
+ if (!emittedPackets) {
101
+ if(!result?.fields) throw "No fields";
102
+ const fields = getDetailedFieldInfo.bind(this.dboBuilder)(result.fields as any);
103
+ packet = { type: "start", rows: batchRows, fields, ended, processId: processID };
104
+ } else {
105
+ packet = { type: "rows", rows: batchRows, ended };
106
+ }
107
+ socket.emit(channel, packet);
108
+ if(ended){
109
+ if(!result) throw "No result info";
110
+ watchSchemaFallback.bind(this.dboBuilder)({ queryWithoutRLS: query.query, command: result.command });
111
+ }
112
+ emittedPackets++;
69
113
  }
70
- (async () => {
71
- let emittedPackets = 0;
72
- let batchRows: any[] = [];
73
- let finished = false;
74
- const batchSize = 10000;
75
- let stream: QueryStreamType;
76
- let poolClient: pg.PoolClient;
77
- const emit = (type: "rows" | "error" | "ended", rawError: any | undefined, stream: QueryStreamType | undefined) => {
78
- const result = stream?._result as { command: string; fields: any[] } | undefined;
79
- let packet: SocketSQLStreamPacket | undefined;
80
- const ended = type === "ended";
81
- if(finished) return;
82
- finished = finished || ended;
83
- if(type === "error"){
84
- const errorWithoutQuery = getSerializedClientErrorFromPGError(rawError, { type: "sql" });
85
- // For some reason query is not present on the error object from sql stream mode
86
- const error = { ...errorWithoutQuery, query: query.query };
87
- packet = { type: "error", error };
88
- } else if (!emittedPackets) {
89
- if(!result?.fields) throw "No fields";
90
- const fields = getDetailedFieldInfo.bind(this.dboBuilder)(result.fields as any);
91
- packet = { type: "start", rows: batchRows, fields, ended, processId: processID };
92
- } else {
93
- packet = { type: "rows", rows: batchRows, ended };
114
+ const client = this.getConnection(err => {
115
+ socketQuery.onError(err);
116
+ client.end();
117
+ });
118
+ try {
119
+ await client.connect();
120
+ poolClient = client;
121
+ processID = (client as any).processID
122
+ const queryStream = new QueryStream(query.query, [], { batchSize: 1e6, highWaterMark: 1e6, rowMode: "array" });
123
+ stream = client.query(queryStream);
124
+ this.socketQueries[socketId]![id]!.client = poolClient;
125
+ this.socketQueries[socketId]![id]!.stream = stream;
126
+ stream.on('data', async (data) => {
127
+ batchRows.push(data);
128
+ if(options?.streamLimit) {
129
+ if(batchRows.length >= options.streamLimit){
130
+ emit("ended", stream);
131
+ }
94
132
  }
95
- socket.emit(channel, packet);
96
- if(ended){
97
- if(!result) throw "No result info";
98
- watchSchemaFallback.bind(this.dboBuilder)({ queryWithoutRLS: query.query, command: result.command });
133
+ if (batchRows.length >= batchSize) {
134
+ emit("rows", stream);
135
+ batchRows = [];
99
136
  }
100
- emittedPackets++;
101
- }
102
-
103
- try {
104
-
105
- await this.pool.connect((err, client, done) => {
106
- if (err) throw err;
107
- if (!client) throw "No client";
108
- poolClient = client;
109
- processID = (client as any).processID
110
- const queryStream = new QueryStream(query.query, [], { batchSize, rowMode: "array" });
111
- stream = client.query(queryStream);
112
- this.socketQueries[socketId]![id]!.poolClient = poolClient;
113
- this.socketQueries[socketId]![id]!.stream = stream;
114
- stream.on('data', async (data) => {
115
- batchRows.push(data);
116
- if(options?.streamLimit) {
117
- if(batchRows.length >= options.streamLimit){
118
- emit("ended", undefined, stream);
119
- }
120
- }
121
- if (batchRows.length >= batchSize) {
122
- emit("rows", undefined, stream);
123
- batchRows = [];
124
- }
125
- });
126
- stream.on('error', error => {
127
- emit("error", error, stream);
128
- });
129
-
130
- stream.on('end', () => {
131
- emit("ended", undefined, stream);
132
- // release the client when the stream is finished
133
- if(!options?.persistStreamConnection){
134
- delete this.socketQueries[socketId]?.[id];
135
- done();
136
- }
137
- })
138
- });
139
- } catch(err){
140
- emit("error", err, undefined);
141
- }
142
- })();
137
+ });
138
+ stream.on('error', error => {
139
+ socketQuery.onError(error);
140
+ });
141
+
142
+ stream.on('end', () => {
143
+ emit("ended", stream);
144
+ // release the client when the stream is finished AND connection is not persisted
145
+ if(!options?.persistStreamConnection){
146
+ delete this.socketQueries[socketId]?.[id];
147
+ client.end();
148
+ }
149
+ });
150
+ } catch(err){
151
+ socketQuery.onError(err);
152
+ await client.end();
153
+ }
143
154
  }
144
155
 
145
- const stop = (_data: any, cb: BasicCallback) => {
146
- // Must kill query if not ended
147
- const { stream, poolClient } = this.socketQueries[socketId]?.[id] ?? {};
156
+ const stop = async (opts: { terminate?: boolean; } | undefined, cb: BasicCallback) => {
157
+ const { stream, client: poolClient } = this.socketQueries[socketId]?.[id] ?? {};
148
158
  if(!stream || !poolClient) return;
149
- this.adminPool.connect(async (err, client, done) => {
150
- if (err) return cb(null, err);
159
+ const client = this.getConnection(undefined);
160
+ try {
161
+ await client.connect();
151
162
  if (!client) return cb(null, "No client");
152
- client.query(`SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE pid = $1`, [processID], (err) => {
153
- if(err) {
154
- cb(null, err);
155
- console.error(err);
156
- }
157
- delete this.socketQueries[socketId]?.[id];
158
- poolClient.release();
159
- socket.removeAllListeners(unsubChannel);
160
- socket.removeAllListeners(channel);
161
- done();
162
- });
163
- });
163
+ const stopFunction = opts?.terminate? "pg_terminate_backend" : "pg_cancel_backend";
164
+ const rows = await client.query(`SELECT ${stopFunction}(pid), pid, state, query FROM pg_stat_activity WHERE pid = $1 AND query = $2`, [processID, query.query]);
165
+ socket.removeAllListeners(unsubChannel);
166
+ socket.removeAllListeners(channel);
167
+ cb({ processID, info: rows.rows[0] });
168
+ } catch (error){
169
+ cb(null, error);
170
+ } finally {
171
+ await client.end();
172
+ }
164
173
  }
165
174
 
166
175
  socket.removeAllListeners(unsubChannel);
@@ -181,7 +190,7 @@ export class QueryStreamer {
181
190
  /** If not started in 5 seconds then assume this will never happen */
182
191
  setTimeout(() => {
183
192
  if(started) return;
184
- stop(null, () => {
193
+ stop({}, () => {
185
194
  // empty
186
195
  });
187
196
  }, 5e3);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.1.127",
3
+ "version": "4.1.129",
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.64"
49
+ "prostgles-types": "^4.0.66"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/bluebird": "^3.5.36",
@@ -92,13 +92,17 @@ try {
92
92
  onReady: async (db, methods, tableSchema, auth, isReconnect) => {
93
93
  log(`TEST_NAME: ${TEST_NAME} Started`)
94
94
  try {
95
- // if(typeof window !== "undefined"){
96
- // window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
97
- // console.error("Error occured: " + errorMsg);
98
- // stopTest({ err: errorMsg });
99
- // return false;
100
- // }
101
- // }
95
+ if(typeof window !== "undefined"){
96
+ const onLog = (...args: any[]) => {
97
+ socket.emit("log", args.map(v => typeof v === "object"? JSON.stringify(v) : v).join(" "));
98
+ }
99
+ window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
100
+ console.error("Error occured: " + errorMsg);
101
+ stopTest({ err: errorMsg });
102
+ return false;
103
+ }
104
+ console.log = onLog;
105
+ }
102
106
  await test.onRun(db, methods, tableSchema, auth, isReconnect);
103
107
 
104
108
  stopTest();
@@ -10,7 +10,7 @@
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "@types/node": "^14.14.16",
13
- "prostgles-client": "^4.0.60",
13
+ "prostgles-client": "^4.0.61",
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.60",
79
- "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.60.tgz",
80
- "integrity": "sha512-dkdlNRbfWOKlqO6hbWJ2m0GJA+9MxXTDOI52WTDqELHImN8bHU3LGGjH6d76BSLvgZF6W6wDTdlTVlMEvy0VGQ==",
78
+ "version": "4.0.61",
79
+ "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.61.tgz",
80
+ "integrity": "sha512-AEgiO5erJnDde0o5hSd1ztKGRWPK2OVCKeVYCbEDGHYIcZzvBA1jRwxpreGaqENZDrWix5LJHyTTTZuLr+LhCw==",
81
81
  "dependencies": {
82
- "prostgles-types": "^4.0.65"
82
+ "prostgles-types": "^4.0.66"
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.65",
95
- "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.65.tgz",
96
- "integrity": "sha512-JdpXQDlx63RZSWAd99N78HugLMJfNy2MC1kCH5ZZjMrDwRPunJ72ByK0rCwybKxMsMiPVcFD0CUlMiqetqpYaA==",
94
+ "version": "4.0.66",
95
+ "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.66.tgz",
96
+ "integrity": "sha512-nDMoWmXmHPBFRK1KJaf7ttfy1VTiB072CtxZoY6LExPPKVCjnJ5PBafIEG1N6opa1WFaU0ez4WTm9Ykc4AOmAQ==",
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.60",
217
- "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.60.tgz",
218
- "integrity": "sha512-dkdlNRbfWOKlqO6hbWJ2m0GJA+9MxXTDOI52WTDqELHImN8bHU3LGGjH6d76BSLvgZF6W6wDTdlTVlMEvy0VGQ==",
216
+ "version": "4.0.61",
217
+ "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.61.tgz",
218
+ "integrity": "sha512-AEgiO5erJnDde0o5hSd1ztKGRWPK2OVCKeVYCbEDGHYIcZzvBA1jRwxpreGaqENZDrWix5LJHyTTTZuLr+LhCw==",
219
219
  "requires": {
220
- "prostgles-types": "^4.0.65"
220
+ "prostgles-types": "^4.0.66"
221
221
  }
222
222
  },
223
223
  "prostgles-types": {
224
- "version": "4.0.65",
225
- "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.65.tgz",
226
- "integrity": "sha512-JdpXQDlx63RZSWAd99N78HugLMJfNy2MC1kCH5ZZjMrDwRPunJ72ByK0rCwybKxMsMiPVcFD0CUlMiqetqpYaA==",
224
+ "version": "4.0.66",
225
+ "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.66.tgz",
226
+ "integrity": "sha512-nDMoWmXmHPBFRK1KJaf7ttfy1VTiB072CtxZoY6LExPPKVCjnJ5PBafIEG1N6opa1WFaU0ez4WTm9Ykc4AOmAQ==",
227
227
  "requires": {
228
228
  "json-schema": "^0.4.0"
229
229
  }
@@ -7,13 +7,13 @@
7
7
  "start": "tsc-watch --onSuccess \"node dist/client/index.js\"",
8
8
  "dev": "NOSTOP=true npm start",
9
9
  "build": "rm -rf ./node_modules/* && rm -rf ./dist/* && npm i && tsc",
10
- "test": "node dist/client/index.js"
10
+ "test": "node dist/client/index.js"
11
11
  },
12
12
  "author": "",
13
13
  "license": "ISC",
14
14
  "dependencies": {
15
15
  "@types/node": "^14.14.16",
16
- "prostgles-client": "^4.0.60",
16
+ "prostgles-client": "^4.0.61",
17
17
  "prostgles-types": "^4.0.51",
18
18
  "socket.io-client": "^4.7.1"
19
19
  },
@@ -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, "start");
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" });
@@ -112,29 +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
-
138
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) => {
139
167
  // const res = await db.sql!("SELECT pg_backend_pid()", {}, { returnType: "stream", persistConnectionId: true });
140
168
  // const listener = async (packet: SocketSQLStreamPacket) => {
@@ -115,6 +115,9 @@ prostgles<DBSchemaGenerated>({
115
115
  if(clientTest){
116
116
  log("Client connected -> console does not work. use log function. socket.id:", socket.id);
117
117
  socket.emit("start-test", { server_id: Math.random() });
118
+ socket.on("log", async (data, cb) => {
119
+ console.log("Client log ", data);
120
+ });
118
121
  socket.on("stop-test", async (err, cb) => {
119
122
  cb();
120
123
  console.log("Client test " + (!err? "successful" : "failed"));
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "../..": {
23
23
  "name": "prostgles-server",
24
- "version": "4.1.126",
24
+ "version": "4.1.128",
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.64"
38
+ "prostgles-types": "^4.0.66"
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.64",
1549
+ "prostgles-types": "^4.0.66",
1550
1550
  "typescript": "^5.2.2"
1551
1551
  }
1552
1552
  },