prostgles-server 4.2.559 → 4.2.560
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/DboBuilder.d.ts +3 -3
- package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder/DboBuilder.js +18 -29
- package/dist/DboBuilder/DboBuilder.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +17 -4
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.js +16 -2
- package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.d.ts +2 -1
- package/dist/DboBuilder/ViewHandler/count.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.js +5 -2
- package/dist/DboBuilder/ViewHandler/count.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.d.ts +4 -1
- package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.js +9 -5
- package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.d.ts +9 -0
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.d.ts.map +1 -0
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.js +73 -0
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.js.map +1 -0
- package/dist/DboBuilder/ViewHandler/size.d.ts +2 -1
- package/dist/DboBuilder/ViewHandler/size.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/size.js +7 -5
- package/dist/DboBuilder/ViewHandler/size.js.map +1 -1
- package/dist/DboBuilder/dboBuilderUtils.d.ts +1 -0
- package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
- package/dist/DboBuilder/dboBuilderUtils.js +4 -2
- package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
- package/dist/DboBuilder/{QueryStreamer.d.ts → runSql/QueryStreamer.d.ts} +4 -6
- package/dist/DboBuilder/runSql/QueryStreamer.d.ts.map +1 -0
- package/dist/DboBuilder/{QueryStreamer.js → runSql/QueryStreamer.js} +5 -22
- package/dist/DboBuilder/runSql/QueryStreamer.js.map +1 -0
- package/dist/DboBuilder/runSql/getAdminClient.d.ts +26 -0
- package/dist/DboBuilder/runSql/getAdminClient.d.ts.map +1 -0
- package/dist/DboBuilder/runSql/getAdminClient.js +32 -0
- package/dist/DboBuilder/runSql/getAdminClient.js.map +1 -0
- package/dist/Prostgles.d.ts +2 -0
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +3 -1
- package/dist/Prostgles.js.map +1 -1
- package/dist/PublishParser/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser/PublishParser.js +2 -1
- package/dist/PublishParser/PublishParser.js.map +1 -1
- package/dist/WebsocketAPI/onSocketConnected.d.ts.map +1 -1
- package/dist/WebsocketAPI/onSocketConnected.js +14 -6
- package/dist/WebsocketAPI/onSocketConnected.js.map +1 -1
- package/dist/initProstgles.d.ts.map +1 -1
- package/dist/initProstgles.js +2 -0
- package/dist/initProstgles.js.map +1 -1
- package/dist/runClientRequest.d.ts +1 -1
- package/dist/runClientRequest.d.ts.map +1 -1
- package/dist/runClientRequest.js +28 -6
- package/dist/runClientRequest.js.map +1 -1
- package/lib/DboBuilder/DboBuilder.ts +20 -31
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +27 -3
- package/lib/DboBuilder/ViewHandler/count.ts +6 -2
- package/lib/DboBuilder/ViewHandler/find.ts +16 -7
- package/lib/DboBuilder/ViewHandler/getDbHandlerWithAbort.ts +98 -0
- package/lib/DboBuilder/ViewHandler/size.ts +8 -5
- package/lib/DboBuilder/dboBuilderUtils.ts +4 -1
- package/lib/DboBuilder/{QueryStreamer.ts → runSql/QueryStreamer.ts} +10 -32
- package/lib/DboBuilder/runSql/getAdminClient.ts +31 -0
- package/lib/Prostgles.ts +4 -1
- package/lib/PublishParser/PublishParser.ts +3 -1
- package/lib/WebsocketAPI/onSocketConnected.ts +15 -7
- package/lib/initProstgles.ts +3 -0
- package/lib/runClientRequest.ts +49 -10
- package/package.json +2 -2
- package/dist/DboBuilder/QueryStreamer.d.ts.map +0 -1
- package/dist/DboBuilder/QueryStreamer.js.map +0 -1
package/dist/runClientRequest.js
CHANGED
|
@@ -20,12 +20,14 @@ const TABLE_METHODS = {
|
|
|
20
20
|
getInfo: 1,
|
|
21
21
|
sync: 1,
|
|
22
22
|
insertMany: 1,
|
|
23
|
+
abort: 1,
|
|
23
24
|
};
|
|
24
25
|
const TABLE_METHODS_KEYS = (0, prostgles_types_1.getKeys)(TABLE_METHODS);
|
|
25
26
|
const SOCKET_ONLY_COMMANDS = [
|
|
26
27
|
"subscribe",
|
|
27
28
|
"subscribeOne",
|
|
28
29
|
"sync",
|
|
30
|
+
"abort",
|
|
29
31
|
];
|
|
30
32
|
const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
|
|
31
33
|
/* Channel name will only include client-sent params so we ignore table_rules enforced params */
|
|
@@ -37,7 +39,15 @@ const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
|
|
|
37
39
|
command: { enum: TABLE_METHODS_KEYS },
|
|
38
40
|
param1: { type: "any", optional: true },
|
|
39
41
|
param2: { type: "any", optional: true },
|
|
40
|
-
param3: {
|
|
42
|
+
param3: {
|
|
43
|
+
type: {
|
|
44
|
+
abortSignalId: { type: "string", optional: true },
|
|
45
|
+
returning: { type: "any", optional: true },
|
|
46
|
+
returnQuery: { type: "boolean", optional: true },
|
|
47
|
+
returnType: { type: "string", optional: true },
|
|
48
|
+
},
|
|
49
|
+
optional: true,
|
|
50
|
+
},
|
|
41
51
|
}, nonValidatedArgs, "tableName");
|
|
42
52
|
if (validation.error !== undefined) {
|
|
43
53
|
throw validation.error;
|
|
@@ -56,11 +66,6 @@ const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
|
|
|
56
66
|
throw clientInfo;
|
|
57
67
|
}
|
|
58
68
|
const parsedTableRule = await this.publishParser.getParsedTableRule({ tableName, clientReq }, clientInfo, scope);
|
|
59
|
-
this.publishParser.validateRequestRule({ tableName, command, clientReq }, parsedTableRule, scope);
|
|
60
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
61
|
-
if (!parsedTableRule) {
|
|
62
|
-
throw `Invalid OR disallowed request: ${tableName}.${command} `;
|
|
63
|
-
}
|
|
64
69
|
const sessionUser = !clientInfo.user ? undefined : ({
|
|
65
70
|
...(0, parseFieldFilter_1.parseFieldFilter)(
|
|
66
71
|
//@ts-ignore
|
|
@@ -72,6 +77,23 @@ const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
|
|
|
72
77
|
isRemoteRequest: { user: sessionUser },
|
|
73
78
|
scope,
|
|
74
79
|
};
|
|
80
|
+
if (command === "abort") {
|
|
81
|
+
const validation = (0, prostgles_types_1.getJSONBObjectSchemaValidationError)({
|
|
82
|
+
tableName: { type: "string" },
|
|
83
|
+
command: { enum: ["abort"] },
|
|
84
|
+
param1: {
|
|
85
|
+
type: { command: { enum: prostgles_types_1.ABORTABLE_METHODS }, abortSignalId: "string" },
|
|
86
|
+
},
|
|
87
|
+
}, nonValidatedArgs, "tableName", undefined, { allowExtraProperties: true });
|
|
88
|
+
if (validation.error !== undefined) {
|
|
89
|
+
throw validation.error;
|
|
90
|
+
}
|
|
91
|
+
this.publishParser.validateRequestRule({ tableName, command: validation.data.param1.command, clientReq }, parsedTableRule, scope);
|
|
92
|
+
return tableHandler.abortRemoteQuery(validation.data.param1.abortSignalId, localParams);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.publishParser.validateRequestRule({ tableName, command, clientReq }, parsedTableRule, scope);
|
|
96
|
+
}
|
|
75
97
|
if (param3 && param3.returnQuery) {
|
|
76
98
|
const isAllowed = await (0, runSQL_1.canRunSQL)(this, clientReq);
|
|
77
99
|
if (isAllowed) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runClientRequest.js","sourceRoot":"","sources":["../lib/runClientRequest.ts"],"names":[],"mappings":";;;AACA,
|
|
1
|
+
{"version":3,"file":"runClientRequest.js","sourceRoot":"","sources":["../lib/runClientRequest.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@ import type {
|
|
|
20
20
|
TableSchema,
|
|
21
21
|
TxCB,
|
|
22
22
|
} from "./DboBuilderTypes";
|
|
23
|
-
import { QueryStreamer } from "./QueryStreamer";
|
|
23
|
+
import { QueryStreamer } from "./runSql/QueryStreamer";
|
|
24
24
|
import { TableHandler } from "./TableHandler/TableHandler";
|
|
25
25
|
import type { JoinPaths } from "./ViewHandler/ViewHandler";
|
|
26
26
|
import { parseJoinPath } from "./ViewHandler/parseJoinPath";
|
|
@@ -69,18 +69,27 @@ export class DboBuilder {
|
|
|
69
69
|
|
|
70
70
|
queryStreamer: QueryStreamer;
|
|
71
71
|
|
|
72
|
+
private constructor(prostgles: Prostgles) {
|
|
73
|
+
this.prostgles = prostgles;
|
|
74
|
+
if (!this.prostgles.db) throw "db missing";
|
|
75
|
+
this.db = this.prostgles.db;
|
|
76
|
+
this.dbo = {};
|
|
77
|
+
this.dboMap = new Map();
|
|
78
|
+
this.queryStreamer = new QueryStreamer(this);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private init = async () => {
|
|
82
|
+
await this.build();
|
|
83
|
+
/* If watchSchema is enabled then PubSubManager must be created (if possible) because it creates the event trigger */
|
|
84
|
+
if (this.prostgles.schemaWatch?.type.watchType === "DDL_trigger") {
|
|
85
|
+
await this.getPubSubManager();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return this;
|
|
89
|
+
};
|
|
90
|
+
|
|
72
91
|
get tables(): TableSchema[] {
|
|
73
92
|
return this.tablesOrViews ?? [];
|
|
74
|
-
// .map(({ name, columns }) => {
|
|
75
|
-
// const info = this.dboMap.get(name)?.tableOrViewInfo;
|
|
76
|
-
// if (!info) return undefined;
|
|
77
|
-
// return {
|
|
78
|
-
// name,
|
|
79
|
-
// info,
|
|
80
|
-
// columns,
|
|
81
|
-
// } satisfies DbTableInfo;
|
|
82
|
-
// })
|
|
83
|
-
// .filter(isDefined);
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
getDetailedFieldInfo = async (fields: pg.IColumn[]) => {
|
|
@@ -130,32 +139,12 @@ export class DboBuilder {
|
|
|
130
139
|
|
|
131
140
|
onSchemaChange?: (event: { command: string; query: string }) => void;
|
|
132
141
|
|
|
133
|
-
private constructor(prostgles: Prostgles) {
|
|
134
|
-
this.prostgles = prostgles;
|
|
135
|
-
if (!this.prostgles.db) throw "db missing";
|
|
136
|
-
this.db = this.prostgles.db;
|
|
137
|
-
this.dbo = {};
|
|
138
|
-
this.dboMap = new Map();
|
|
139
|
-
this.queryStreamer = new QueryStreamer(this);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
private init = async () => {
|
|
143
|
-
await this.build();
|
|
144
|
-
/* If watchSchema is enabled then PubSubManager must be created (if possible) because it creates the event trigger */
|
|
145
|
-
if (this.prostgles.schemaWatch?.type.watchType === "DDL_trigger") {
|
|
146
|
-
await this.getPubSubManager();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return this;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
142
|
public static create = async (prostgles: Prostgles): Promise<DboBuilder> => {
|
|
153
143
|
const res = new DboBuilder(prostgles);
|
|
154
144
|
return await res.init();
|
|
155
145
|
};
|
|
156
146
|
|
|
157
147
|
destroy = async () => {
|
|
158
|
-
await this.queryStreamer.destroy().catch(console.error);
|
|
159
148
|
return this._pubSubManager?.destroy();
|
|
160
149
|
};
|
|
161
150
|
|
|
@@ -20,7 +20,7 @@ import type { TableSchema } from "../DboBuilderTypes";
|
|
|
20
20
|
import { getValidatedTableRules } from "../TableRules/getValidatedTableRules";
|
|
21
21
|
import { getColumns } from "../getColumns";
|
|
22
22
|
import { count } from "./count";
|
|
23
|
-
import { find } from "./find";
|
|
23
|
+
import { find, type Param3 } from "./find";
|
|
24
24
|
import { getInfo } from "./getInfo";
|
|
25
25
|
import { parseFieldFilter } from "./parseFieldFilter";
|
|
26
26
|
import { prepareWhere } from "./prepareWhere";
|
|
@@ -30,6 +30,8 @@ import { subscribe } from "./subscribe";
|
|
|
30
30
|
import { validateViewRules } from "./validateViewRules";
|
|
31
31
|
import { escapeTSNames } from "../../utils/utils";
|
|
32
32
|
import type { TableDefinition } from "../../TableConfig/TableConfig";
|
|
33
|
+
import { getDbHandlerWithAbort } from "./getDbHandlerWithAbort";
|
|
34
|
+
import type { VoidFunction } from "../../SchemaWatch/SchemaWatch";
|
|
33
35
|
|
|
34
36
|
export type JoinPaths = {
|
|
35
37
|
t1: string;
|
|
@@ -112,6 +114,28 @@ export class ViewHandler {
|
|
|
112
114
|
return localParams?.tx || this.tx;
|
|
113
115
|
};
|
|
114
116
|
|
|
117
|
+
abortRemoteQuery = (abortSignalId: string, localParams: LocalParams) => {
|
|
118
|
+
const sid = this.dboBuilder.prostgles.authHandler.getSIDNoError(localParams.clientReq);
|
|
119
|
+
if (!sid) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
"Cannot get SID from client request. Ensure that the client is authenticated before using abortable queries.",
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
const abortableQuery = this.activeQueries.get(abortSignalId);
|
|
125
|
+
if (!abortableQuery || abortableQuery.sid !== sid) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
`No active query found with abortSignalId ${abortSignalId}. Ensure that the query was initiated with the correct abortSignalId.`,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
abortableQuery.abort();
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
activeQueries = new Map<
|
|
134
|
+
string,
|
|
135
|
+
{ abort: VoidFunction; query: string; start: number; sid: string | undefined }
|
|
136
|
+
>();
|
|
137
|
+
getDbHandlerWithAbort = getDbHandlerWithAbort.bind(this);
|
|
138
|
+
|
|
115
139
|
_log = ({
|
|
116
140
|
command,
|
|
117
141
|
data,
|
|
@@ -178,7 +202,7 @@ export class ViewHandler {
|
|
|
178
202
|
async findOne(
|
|
179
203
|
filter?: Filter,
|
|
180
204
|
selectParams?: SelectParams,
|
|
181
|
-
|
|
205
|
+
param3?: Param3,
|
|
182
206
|
table_rules?: ParsedTableRule,
|
|
183
207
|
localParams?: LocalParams,
|
|
184
208
|
): Promise<any> {
|
|
@@ -191,7 +215,7 @@ export class ViewHandler {
|
|
|
191
215
|
const result = await this.find(
|
|
192
216
|
filter,
|
|
193
217
|
{ ...params, limit: 1, returnType: "row" },
|
|
194
|
-
|
|
218
|
+
param3,
|
|
195
219
|
table_rules,
|
|
196
220
|
localParams,
|
|
197
221
|
);
|
|
@@ -8,12 +8,13 @@ import {
|
|
|
8
8
|
} from "../dboBuilderUtils";
|
|
9
9
|
import type { ViewHandler } from "./ViewHandler";
|
|
10
10
|
import { getReturnTypeQuery } from "./getReturnTypeQuery";
|
|
11
|
+
import type { Param3 } from "./find";
|
|
11
12
|
|
|
12
13
|
export async function count(
|
|
13
14
|
this: ViewHandler,
|
|
14
15
|
_filter?: Filter,
|
|
15
16
|
selectParams?: SelectParams,
|
|
16
|
-
|
|
17
|
+
param3?: Param3,
|
|
17
18
|
table_rules?: ParsedTableRule,
|
|
18
19
|
localParams?: LocalParams,
|
|
19
20
|
): Promise<number> {
|
|
@@ -54,7 +55,10 @@ export async function count(
|
|
|
54
55
|
return queryToReturn as unknown[];
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
const handler = this.
|
|
58
|
+
const handler = this.getDbHandlerWithAbort(localParams, {
|
|
59
|
+
abortSignal: selectParams?.abortSignal,
|
|
60
|
+
abortSignalId: param3?.abortSignalId,
|
|
61
|
+
});
|
|
58
62
|
return handler.one(queryWithRLS).then(({ count }) => +count);
|
|
59
63
|
});
|
|
60
64
|
|
|
@@ -13,19 +13,23 @@ import { getSelectQuery } from "../QueryBuilder/getSelectQuery";
|
|
|
13
13
|
import { getReturnTypeQuery } from "./getReturnTypeQuery";
|
|
14
14
|
import type { ViewHandler } from "./ViewHandler";
|
|
15
15
|
|
|
16
|
+
export type Param3 = {
|
|
17
|
+
abortSignalId?: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
16
20
|
export const find = async function (
|
|
17
21
|
this: ViewHandler,
|
|
18
|
-
filter
|
|
22
|
+
filter: Filter = {},
|
|
19
23
|
selectParams?: SelectParams,
|
|
20
|
-
|
|
24
|
+
param3?: Param3,
|
|
21
25
|
tableRules?: ParsedTableRule,
|
|
22
26
|
localParams?: LocalParams,
|
|
23
27
|
): Promise<any[]> {
|
|
24
28
|
const start = Date.now();
|
|
25
|
-
const
|
|
26
|
-
|
|
29
|
+
const { limit, returnType, abortSignal } = selectParams ?? {};
|
|
30
|
+
|
|
31
|
+
const command = limit === 1 && returnType === "row" ? "findOne" : "find";
|
|
27
32
|
try {
|
|
28
|
-
filter = filter || {};
|
|
29
33
|
const allowedReturnTypes = Object.keys({
|
|
30
34
|
row: 1,
|
|
31
35
|
statement: 1,
|
|
@@ -52,6 +56,7 @@ export const find = async function (
|
|
|
52
56
|
returnType: 1,
|
|
53
57
|
groupBy: 1,
|
|
54
58
|
having: 1,
|
|
59
|
+
abortSignal: 1,
|
|
55
60
|
} satisfies Record<keyof SelectParams, 1>);
|
|
56
61
|
|
|
57
62
|
const invalidParams = Object.keys(selectParams).filter((k) => !validParamNames.includes(k));
|
|
@@ -96,7 +101,7 @@ export const find = async function (
|
|
|
96
101
|
this,
|
|
97
102
|
filter,
|
|
98
103
|
selectParamsLimitCheck,
|
|
99
|
-
|
|
104
|
+
undefined,
|
|
100
105
|
tableRules,
|
|
101
106
|
localParams,
|
|
102
107
|
);
|
|
@@ -109,6 +114,7 @@ export const find = async function (
|
|
|
109
114
|
);
|
|
110
115
|
|
|
111
116
|
const queryWithRLS = withUserRLS(localParams, queryWithoutRLS);
|
|
117
|
+
|
|
112
118
|
const queryToReturn = await getReturnTypeQuery({
|
|
113
119
|
handler: this,
|
|
114
120
|
localParams,
|
|
@@ -123,7 +129,10 @@ export const find = async function (
|
|
|
123
129
|
|
|
124
130
|
const query = queryWithRLS;
|
|
125
131
|
const isOneOrNone = returnType === "row" || returnType === "value";
|
|
126
|
-
const dbHandler = this.
|
|
132
|
+
const dbHandler = this.getDbHandlerWithAbort(localParams, {
|
|
133
|
+
abortSignal,
|
|
134
|
+
abortSignalId: param3?.abortSignalId,
|
|
135
|
+
});
|
|
127
136
|
const queryPromise =
|
|
128
137
|
isOneOrNone ?
|
|
129
138
|
dbHandler.oneOrNone<AnyObject>(query).then((data) => (data ? [data] : []))
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { DB } from "../../initProstgles";
|
|
2
|
+
import { QUERY_ID_PREFIX, type LocalParams } from "../DboBuilder";
|
|
3
|
+
import type { ViewHandler } from "./ViewHandler";
|
|
4
|
+
import type * as pgPromise from "pg-promise";
|
|
5
|
+
|
|
6
|
+
export function getDbHandlerWithAbort(
|
|
7
|
+
this: ViewHandler,
|
|
8
|
+
localParams: LocalParams | undefined,
|
|
9
|
+
params: { abortSignal: AbortSignal | undefined; abortSignalId: string | undefined },
|
|
10
|
+
): Pick<DB | pgPromise.ITask<{}>, "any" | "one" | "many" | "manyOrNone" | "none" | "oneOrNone"> {
|
|
11
|
+
if (params.abortSignal && params.abortSignalId) {
|
|
12
|
+
throw new Error("Cannot provide both abortSignal and abortSignalId");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (params.abortSignal?.aborted) {
|
|
16
|
+
throw new Error("Query aborted before execution");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const abortSignal =
|
|
20
|
+
params.abortSignal ?? AbortSignal.timeout(localParams?.clientReq ? 7_000 : 120_000);
|
|
21
|
+
const abortSignalId = params.abortSignalId ?? crypto.randomUUID();
|
|
22
|
+
|
|
23
|
+
if (this.activeQueries.has(abortSignalId)) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`A query with abortSignalId ${params.abortSignalId} is already active. Ensure that each query has a unique abortSignalId.`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
const handler = this.getTransaction(localParams)?.t ?? this.db;
|
|
29
|
+
const { adminClient } = this.dboBuilder.prostgles;
|
|
30
|
+
if (!adminClient) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
"adminClient not available. Ensure prostgles.adminClient is initialized before using abortable queries.",
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const sid = this.dboBuilder.prostgles.authHandler.getSIDNoError(localParams?.clientReq);
|
|
36
|
+
if (!sid && localParams?.clientReq) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"Cannot get SID from client request. Ensure that the client is authenticated before using abortable queries.",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const withAbortQuery = <Args extends unknown[], R extends Promise<any>>(
|
|
42
|
+
func: (query: string, ...args: Args) => R,
|
|
43
|
+
) => {
|
|
44
|
+
return (query: string, ...args: Args) => {
|
|
45
|
+
const queryIdPrefix = query.split("\n", 1)[0];
|
|
46
|
+
|
|
47
|
+
const queryHasIdPrefix = queryIdPrefix?.startsWith(QUERY_ID_PREFIX);
|
|
48
|
+
if (!queryIdPrefix || !queryHasIdPrefix) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
"Query does not have a prostgles query id prefix. Ensure that the query is generated using prostgles methods that include the query id.",
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const abort = () => {
|
|
55
|
+
/** Only terminate if there is exactly one matching query with a query id prefix */
|
|
56
|
+
|
|
57
|
+
void adminClient
|
|
58
|
+
.query(
|
|
59
|
+
`
|
|
60
|
+
SELECT pg_terminate_backend(pid), *
|
|
61
|
+
FROM pg_stat_activity
|
|
62
|
+
WHERE query LIKE $1 AND pid <> pg_backend_pid()
|
|
63
|
+
`,
|
|
64
|
+
[`${queryIdPrefix}%`],
|
|
65
|
+
)
|
|
66
|
+
.then((res) => {
|
|
67
|
+
// if (params.abortSignalId) {
|
|
68
|
+
// console.log(JSON.stringify(res.rows));
|
|
69
|
+
// process.exit(1);
|
|
70
|
+
// }
|
|
71
|
+
})
|
|
72
|
+
.catch((err) => {
|
|
73
|
+
// ignore error
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
this.activeQueries.set(abortSignalId, {
|
|
77
|
+
query,
|
|
78
|
+
start: Date.now(),
|
|
79
|
+
sid,
|
|
80
|
+
abort,
|
|
81
|
+
});
|
|
82
|
+
abortSignal.addEventListener("abort", abort);
|
|
83
|
+
return func(query, ...args).finally(() => {
|
|
84
|
+
abortSignal.removeEventListener("abort", abort);
|
|
85
|
+
this.activeQueries.delete(abortSignalId);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
manyOrNone: withAbortQuery(handler.manyOrNone.bind(handler)),
|
|
92
|
+
one: withAbortQuery(handler.one.bind(handler)),
|
|
93
|
+
oneOrNone: withAbortQuery(handler.oneOrNone.bind(handler)),
|
|
94
|
+
any: withAbortQuery(handler.any.bind(handler)),
|
|
95
|
+
none: withAbortQuery(handler.none.bind(handler)),
|
|
96
|
+
many: withAbortQuery(handler.many.bind(handler)),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -8,11 +8,12 @@ import {
|
|
|
8
8
|
} from "../dboBuilderUtils";
|
|
9
9
|
import type { ViewHandler } from "./ViewHandler";
|
|
10
10
|
import { getReturnTypeQuery } from "./getReturnTypeQuery";
|
|
11
|
+
import type { Param3 } from "./find";
|
|
11
12
|
export async function size(
|
|
12
13
|
this: ViewHandler,
|
|
13
14
|
_filter?: Filter,
|
|
14
15
|
selectParams?: SelectParams,
|
|
15
|
-
|
|
16
|
+
param3?: Param3,
|
|
16
17
|
table_rules?: ParsedTableRule,
|
|
17
18
|
localParams?: LocalParams,
|
|
18
19
|
): Promise<string> {
|
|
@@ -22,7 +23,7 @@ export async function size(
|
|
|
22
23
|
const result = await this.find(
|
|
23
24
|
filter,
|
|
24
25
|
{ ...selectParams, limit: 2 },
|
|
25
|
-
|
|
26
|
+
param3,
|
|
26
27
|
table_rules,
|
|
27
28
|
localParams,
|
|
28
29
|
).then(async (_allowed) => {
|
|
@@ -57,9 +58,11 @@ export async function size(
|
|
|
57
58
|
return queryToReturn as unknown[];
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
const handler = this.getDbHandlerWithAbort(localParams, {
|
|
62
|
+
abortSignal: selectParams?.abortSignal,
|
|
63
|
+
abortSignalId: param3?.abortSignalId,
|
|
64
|
+
});
|
|
65
|
+
return handler.one<{ size: string | null }>(queryWithRLS).then(({ size }) => size || "0");
|
|
63
66
|
});
|
|
64
67
|
await this._log({
|
|
65
68
|
command: "size",
|
|
@@ -176,6 +176,8 @@ export const getCanExecute = async (db: DB) => {
|
|
|
176
176
|
return false;
|
|
177
177
|
};
|
|
178
178
|
|
|
179
|
+
export const QUERY_ID_PREFIX = "-- prostgles query id: ";
|
|
180
|
+
|
|
179
181
|
export const withUserRLS = (localParams: LocalParams | undefined, query: string) => {
|
|
180
182
|
const user = localParams?.isRemoteRequest?.user;
|
|
181
183
|
const queryPrefix = `SET SESSION "prostgles.user" \nTO`;
|
|
@@ -184,5 +186,6 @@ export const withUserRLS = (localParams: LocalParams | undefined, query: string)
|
|
|
184
186
|
firstQuery = pgp.as.format(`${queryPrefix} \${user};`, { user });
|
|
185
187
|
}
|
|
186
188
|
|
|
187
|
-
|
|
189
|
+
const queryId = crypto.randomUUID();
|
|
190
|
+
return [QUERY_ID_PREFIX + queryId, firstQuery, query].filter(Boolean).join("\n");
|
|
188
191
|
};
|
|
@@ -2,13 +2,14 @@ import * as pg from "pg";
|
|
|
2
2
|
import type CursorType from "pg-cursor";
|
|
3
3
|
import type { SQLOptions, SocketSQLStreamPacket, SocketSQLStreamServer } from "prostgles-types";
|
|
4
4
|
import { CHANNELS, omitKeys, pickKeys } from "prostgles-types";
|
|
5
|
-
import type { BasicCallback } from "
|
|
6
|
-
import type { VoidFunction } from "
|
|
7
|
-
import type { DB } from "
|
|
8
|
-
import type { DboBuilder } from "
|
|
9
|
-
import type { PRGLIOSocket } from "
|
|
10
|
-
import { getErrorAsObject, getSerializedClientErrorFromPGError } from "
|
|
11
|
-
import { getDetailedFieldInfo } from "./
|
|
5
|
+
import type { BasicCallback } from "../../PubSubManager/PubSubManager";
|
|
6
|
+
import type { VoidFunction } from "../../SchemaWatch/SchemaWatch";
|
|
7
|
+
import type { DB } from "../../initProstgles";
|
|
8
|
+
import type { DboBuilder } from "../DboBuilder";
|
|
9
|
+
import type { PRGLIOSocket } from "../DboBuilderTypes";
|
|
10
|
+
import { getErrorAsObject, getSerializedClientErrorFromPGError } from "../dboBuilderUtils";
|
|
11
|
+
import { getDetailedFieldInfo } from "./runSqlUtils";
|
|
12
|
+
import { getConnectionDetails } from "./getAdminClient";
|
|
12
13
|
const Cursor = require("pg-cursor") as typeof CursorType;
|
|
13
14
|
|
|
14
15
|
type ClientStreamedRequest = {
|
|
@@ -44,36 +45,13 @@ export class QueryStreamer {
|
|
|
44
45
|
db: DB;
|
|
45
46
|
dboBuilder: DboBuilder;
|
|
46
47
|
socketQueries: Map<string, Map<number, StreamedQuery>> = new Map();
|
|
47
|
-
adminClient: pg.Client;
|
|
48
48
|
constructor(dboBuilder: DboBuilder) {
|
|
49
49
|
this.dboBuilder = dboBuilder;
|
|
50
50
|
this.db = dboBuilder.db;
|
|
51
|
-
const setAdminClient = () => {
|
|
52
|
-
this.adminClient = this.getConnection(undefined, { keepAlive: true });
|
|
53
|
-
return this.adminClient.connect();
|
|
54
|
-
};
|
|
55
|
-
this.adminClient = this.getConnection(
|
|
56
|
-
(error) => {
|
|
57
|
-
if (error.message?.includes("database") && error.message?.includes("does not exist"))
|
|
58
|
-
return;
|
|
59
|
-
console.log("Admin client error. Reconnecting...", error);
|
|
60
|
-
void setAdminClient();
|
|
61
|
-
},
|
|
62
|
-
{ keepAlive: true },
|
|
63
|
-
);
|
|
64
|
-
void this.adminClient.connect();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
destroy() {
|
|
68
|
-
return this.adminClient.end().catch((err) => {
|
|
69
|
-
console.error("Error ending admin client connection", err);
|
|
70
|
-
});
|
|
71
51
|
}
|
|
72
52
|
|
|
73
53
|
getConnection = (onError: ((err: any) => void) | undefined, extraOptions?: pg.ClientConfig) => {
|
|
74
|
-
const
|
|
75
|
-
typeof this.db.$cn === "string" ? { connectionString: this.db.$cn } : (this.db.$cn as any);
|
|
76
|
-
const client = new pg.Client({ ...connectionInfo, ...extraOptions });
|
|
54
|
+
const client = new pg.Client({ ...getConnectionDetails(this.db), ...extraOptions });
|
|
77
55
|
client.on("error", (err) => {
|
|
78
56
|
onError?.(err);
|
|
79
57
|
});
|
|
@@ -272,7 +250,7 @@ export class QueryStreamer {
|
|
|
272
250
|
}
|
|
273
251
|
try {
|
|
274
252
|
const stopFunction = opts?.terminate ? "pg_terminate_backend" : "pg_cancel_backend";
|
|
275
|
-
const rows = await this.adminClient
|
|
253
|
+
const rows = await this.dboBuilder.prostgles.adminClient!.query(
|
|
276
254
|
`SELECT ${stopFunction}(pid), pid, state, query FROM pg_stat_activity WHERE pid = $1`,
|
|
277
255
|
[processID],
|
|
278
256
|
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as pg from "pg";
|
|
2
|
+
import type { DB } from "../../initProstgles";
|
|
3
|
+
|
|
4
|
+
export const getAdminClient = async (db: DB, onDbDropped?: () => void): Promise<pg.Client> => {
|
|
5
|
+
const adminClient = new pg.Client({
|
|
6
|
+
...getConnectionDetails(db),
|
|
7
|
+
application_name: "prostgles-admin-client",
|
|
8
|
+
keepAlive: true,
|
|
9
|
+
});
|
|
10
|
+
if (onDbDropped) {
|
|
11
|
+
adminClient.on("error", (err) => {
|
|
12
|
+
if (
|
|
13
|
+
err.message.includes("terminating connection due to administrator command") ||
|
|
14
|
+
(err.message.includes("database") && err.message.includes("does not exist"))
|
|
15
|
+
) {
|
|
16
|
+
onDbDropped();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
await adminClient.connect();
|
|
21
|
+
return adminClient;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const getConnectionDetails = (db: DB) => {
|
|
25
|
+
const opts = db.$pool.options as pg.ClientConfig;
|
|
26
|
+
return {
|
|
27
|
+
...opts,
|
|
28
|
+
password: opts.password,
|
|
29
|
+
keepAlive: true,
|
|
30
|
+
} satisfies pg.ClientConfig;
|
|
31
|
+
};
|
package/lib/Prostgles.ts
CHANGED
|
@@ -60,6 +60,7 @@ const DEFAULT_KEYWORDS = {
|
|
|
60
60
|
import { randomUUID } from "crypto";
|
|
61
61
|
import * as fs from "fs";
|
|
62
62
|
import type { TableHandler } from "./DboBuilder/TableHandler/TableHandler";
|
|
63
|
+
import type { getAdminClient } from "./DboBuilder/runSql/getAdminClient";
|
|
63
64
|
|
|
64
65
|
export class Prostgles {
|
|
65
66
|
/**
|
|
@@ -81,6 +82,7 @@ export class Prostgles {
|
|
|
81
82
|
};
|
|
82
83
|
|
|
83
84
|
db?: DB;
|
|
85
|
+
adminClient?: Awaited<ReturnType<typeof getAdminClient>>;
|
|
84
86
|
pgp?: PGP;
|
|
85
87
|
dbo?: DBHandlerServer;
|
|
86
88
|
_dboBuilder?: DboBuilder;
|
|
@@ -173,8 +175,9 @@ export class Prostgles {
|
|
|
173
175
|
!this.db ||
|
|
174
176
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
175
177
|
!this.db.connect
|
|
176
|
-
)
|
|
178
|
+
) {
|
|
177
179
|
throw "something went wrong getting a db connection";
|
|
180
|
+
}
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
getTSFileName() {
|
|
@@ -160,7 +160,9 @@ export class PublishParser {
|
|
|
160
160
|
tableRule: ParsedTableRule,
|
|
161
161
|
scope: PermissionScope | undefined,
|
|
162
162
|
) {
|
|
163
|
-
if (!command || !tableName)
|
|
163
|
+
if (!command || !tableName) {
|
|
164
|
+
throw "command OR tableName are missing";
|
|
165
|
+
}
|
|
164
166
|
|
|
165
167
|
const [rule] =
|
|
166
168
|
getObjectEntries(SQL_COMMAND_TABLE_METHODS).find(([_, methods]) =>
|
|
@@ -32,20 +32,28 @@ export async function onSocketConnected(this: Prostgles, socket: PRGLIOSocket) {
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
socket.on("disconnect", () => {
|
|
35
|
-
this.dbEventsManager?.removeNotice(socket);
|
|
36
|
-
this.dbEventsManager?.removeNotify(undefined, socket);
|
|
37
|
-
this.connectedSockets = this.connectedSockets.filter((s) => s.id !== socket.id);
|
|
38
|
-
this.dboBuilder.queryStreamer.onDisconnect(socket.id);
|
|
39
35
|
void this.opts.onLog?.({
|
|
40
36
|
type: "disconnect",
|
|
41
37
|
sid: this.authHandler.getValidatedSid({ socket }),
|
|
42
38
|
socketId: socket.id,
|
|
43
39
|
connectedSocketIds: this.connectedSockets.map((s) => s.id),
|
|
44
40
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
this.dbEventsManager?.removeNotice(socket);
|
|
42
|
+
this.dbEventsManager?.removeNotify(undefined, socket);
|
|
43
|
+
this.connectedSockets = this.connectedSockets.filter((s) => s.id !== socket.id);
|
|
44
|
+
this.dboBuilder.queryStreamer.onDisconnect(socket.id);
|
|
45
|
+
const sid = this.authHandler.getSIDNoError({ socket });
|
|
46
|
+
if (sid) {
|
|
47
|
+
this.dboBuilder.dboMap.forEach((tableHandler) => {
|
|
48
|
+
tableHandler.activeQueries.forEach((activeQuery) => {
|
|
49
|
+
if (activeQuery.sid === sid) {
|
|
50
|
+
activeQuery.abort();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
48
54
|
}
|
|
55
|
+
|
|
56
|
+
void this.opts.onSocketDisconnect?.({ socket, dbo: dbo as DBOFullyTyped, db, getUser });
|
|
49
57
|
});
|
|
50
58
|
|
|
51
59
|
await this.opts.onLog?.({
|