badmfck-api-server 2.9.4 → 2.9.5
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/apiServer/DBService.d.ts +13 -0
- package/dist/apiServer/DBService.js +26 -2
- package/dist/apiServer/MysqlService.js +4 -1
- package/dist/apiServer/db/IDBAdapter.d.ts +2 -1
- package/dist/apiServer/db/MysqlAdapter.d.ts +5 -2
- package/dist/apiServer/db/MysqlAdapter.js +100 -69
- package/package.json +1 -1
@@ -21,6 +21,18 @@ export interface IDBQuery {
|
|
21
21
|
calculateCount?: boolean;
|
22
22
|
parseQueryOnly?: boolean;
|
23
23
|
}
|
24
|
+
export interface IDBBulkQuery {
|
25
|
+
dbid?: string;
|
26
|
+
bulk: {
|
27
|
+
query: string;
|
28
|
+
fields: {
|
29
|
+
[key: string]: IDBQueryField | null | string | number | boolean;
|
30
|
+
};
|
31
|
+
throwable?: boolean;
|
32
|
+
calculateCount?: boolean;
|
33
|
+
}[];
|
34
|
+
queued?: boolean;
|
35
|
+
}
|
24
36
|
export interface IDBError {
|
25
37
|
code: string;
|
26
38
|
errno: number;
|
@@ -52,6 +64,7 @@ export interface DBAdapterOptions {
|
|
52
64
|
debug?: boolean;
|
53
65
|
}
|
54
66
|
export declare const REQ_DB: Req<IDBQuery, IDBResult>;
|
67
|
+
export declare const REQ_DBX: Req<IDBBulkQuery, IDBResult[]>;
|
55
68
|
export declare class DBService extends BaseService {
|
56
69
|
static allInstances: DBService[];
|
57
70
|
options: IDBSericeOptions;
|
@@ -1,10 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.DBService = exports.REQ_DB = void 0;
|
3
|
+
exports.DBService = exports.REQ_DBX = exports.REQ_DB = void 0;
|
4
4
|
const badmfck_signal_1 = require("badmfck-signal");
|
5
5
|
const BaseService_1 = require("./BaseService");
|
6
6
|
const MysqlAdapter_1 = require("./db/MysqlAdapter");
|
7
|
-
exports.REQ_DB = new badmfck_signal_1.Req(undefined, "
|
7
|
+
exports.REQ_DB = new badmfck_signal_1.Req(undefined, "REQ_DB");
|
8
|
+
exports.REQ_DBX = new badmfck_signal_1.Req(undefined, "REQ_DBX");
|
8
9
|
class DBService extends BaseService_1.BaseService {
|
9
10
|
static allInstances = [];
|
10
11
|
options;
|
@@ -25,6 +26,29 @@ class DBService extends BaseService_1.BaseService {
|
|
25
26
|
if (this.options.type === "mysql") {
|
26
27
|
await this.createMysqlDatabase();
|
27
28
|
}
|
29
|
+
exports.REQ_DBX.listener = async (req) => {
|
30
|
+
if (!req.dbid && DBService.allInstances.length === 1 && DBService.allInstances[0].adapter)
|
31
|
+
return DBService.allInstances[0].adapter.bulk(req);
|
32
|
+
for (let i of DBService.allInstances) {
|
33
|
+
if (i.options.id === req.dbid && i.adapter)
|
34
|
+
return i.adapter.bulk(req);
|
35
|
+
}
|
36
|
+
const error = {
|
37
|
+
code: "DB_NOT_FOUND",
|
38
|
+
errno: -1,
|
39
|
+
fatal: true,
|
40
|
+
sql: "",
|
41
|
+
name: "DB_NOT_FOUND",
|
42
|
+
message: "DB not found: " + req.dbid
|
43
|
+
};
|
44
|
+
let result = [];
|
45
|
+
for (let i of req.bulk) {
|
46
|
+
result.push({ error: error });
|
47
|
+
if (i.throwable)
|
48
|
+
throw error;
|
49
|
+
}
|
50
|
+
return result;
|
51
|
+
};
|
28
52
|
exports.REQ_DB.listener = async (req) => {
|
29
53
|
if (!req.dbid && DBService.allInstances.length === 1 && DBService.allInstances[0].adapter)
|
30
54
|
return DBService.allInstances[0].adapter.query(req);
|
@@ -151,8 +151,11 @@ class MysqlService extends BaseService_1.BaseService {
|
|
151
151
|
const query = MysqlService.prepareQuery(i.query, i.fields);
|
152
152
|
promises.push(this.execute(query, i.rollbackQuery ?? null, i.transactionID ?? 0, i.throwable ?? false, i.calculateCount ?? false));
|
153
153
|
}
|
154
|
-
if (this.debug)
|
154
|
+
if (this.debug) {
|
155
155
|
console.log("Execute queries: ", data.length);
|
156
|
+
for (let i of data)
|
157
|
+
console.log(i);
|
158
|
+
}
|
156
159
|
const result = await Promise.all(promises);
|
157
160
|
for (let i of result) {
|
158
161
|
if (i.error && i.error.code === "CONN_ERR") {
|
@@ -1,7 +1,8 @@
|
|
1
|
-
import { IDBQuery, IDBResult } from "../DBService";
|
1
|
+
import { IDBBulkQuery, IDBQuery, IDBResult } from "../DBService";
|
2
2
|
export interface IDBAdapter {
|
3
3
|
init(): Promise<void>;
|
4
4
|
finish(): Promise<void>;
|
5
5
|
prepareQuery(request: IDBQuery): string;
|
6
6
|
query(request: IDBQuery): Promise<IDBResult>;
|
7
|
+
bulk(request: IDBBulkQuery): Promise<IDBResult[]>;
|
7
8
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/// <reference types="node" />
|
2
|
-
import { DBAdapterOptions, IDBError, IDBQuery, IDBQueryField, IDBResult } from "../DBService";
|
2
|
+
import { DBAdapterOptions, IDBBulkQuery, IDBError, IDBQuery, IDBQueryField, IDBResult } from "../DBService";
|
3
3
|
import { IDBAdapter } from "./IDBAdapter";
|
4
4
|
import mysql from 'mysql2/promise';
|
5
5
|
import fs from 'fs';
|
@@ -34,7 +34,9 @@ export declare class MysqlAdapter implements IDBAdapter {
|
|
34
34
|
init(): Promise<void>;
|
35
35
|
setupTimers(): void;
|
36
36
|
recreatePool(): Promise<boolean>;
|
37
|
-
|
37
|
+
bulk(request: IDBBulkQuery): Promise<IDBResult[]>;
|
38
|
+
getConnection(transactionId?: number): Promise<mysql.PoolConnection | IDBError>;
|
39
|
+
query(request: IDBQuery, conn?: mysql.PoolConnection): Promise<IDBResult>;
|
38
40
|
finalizeConnection(conn: mysql.PoolConnection): void;
|
39
41
|
prepareQuery(request: IDBQuery): string;
|
40
42
|
static prepareQueryFieldValue(field: IDBQueryField): string | number | boolean | null | undefined;
|
@@ -44,5 +46,6 @@ export declare class MysqlAdapter implements IDBAdapter {
|
|
44
46
|
finish(): Promise<void>;
|
45
47
|
createMysqlQueryError(err: any, throwable?: boolean): IDBError;
|
46
48
|
storeTransactionAsProblem(trx: ITransaction, message: string): Promise<void>;
|
49
|
+
isError(obj: any): obj is IDBError;
|
47
50
|
}
|
48
51
|
export {};
|
@@ -154,104 +154,132 @@ class MysqlAdapter {
|
|
154
154
|
}
|
155
155
|
return true;
|
156
156
|
}
|
157
|
-
async
|
158
|
-
const
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
157
|
+
async bulk(request) {
|
158
|
+
const results = [];
|
159
|
+
let queries = [];
|
160
|
+
let conn = null;
|
161
|
+
if (request.queued) {
|
162
|
+
conn = await this.getConnection();
|
163
|
+
if (this.isError(conn)) {
|
164
|
+
for (let i of request.bulk)
|
165
|
+
results.push({ data: null, error: conn });
|
166
|
+
return results;
|
167
|
+
}
|
164
168
|
}
|
169
|
+
for (let i of request.bulk) {
|
170
|
+
if (request.queued && conn) {
|
171
|
+
const response = await this.query({
|
172
|
+
query: i.query,
|
173
|
+
fields: i.fields,
|
174
|
+
throwable: i.throwable,
|
175
|
+
}, conn);
|
176
|
+
results.push(response);
|
177
|
+
continue;
|
178
|
+
}
|
179
|
+
queries.push(this.query({
|
180
|
+
query: i.query,
|
181
|
+
fields: i.fields,
|
182
|
+
throwable: i.throwable,
|
183
|
+
}));
|
184
|
+
}
|
185
|
+
if (conn) {
|
186
|
+
this.finalizeConnection(conn);
|
187
|
+
conn = null;
|
188
|
+
}
|
189
|
+
if (queries && queries.length > 0) {
|
190
|
+
const responses = await Promise.all(queries);
|
191
|
+
for (let i of responses)
|
192
|
+
results.push(i);
|
193
|
+
}
|
194
|
+
return results;
|
195
|
+
}
|
196
|
+
async getConnection(transactionId) {
|
165
197
|
if (!this.pool) {
|
166
198
|
(0, LogService_1.logError)("${MysqlAdapter.js}", "No pool created, can't execute query");
|
167
|
-
|
199
|
+
return {
|
168
200
|
code: "NO_POOL",
|
169
201
|
errno: 100000,
|
170
202
|
fatal: true,
|
171
|
-
sql:
|
203
|
+
sql: "",
|
172
204
|
name: "NO_POOL",
|
173
205
|
message: "Mysql pool not created",
|
174
206
|
};
|
175
|
-
if (request.throwable)
|
176
|
-
throw { ...DefaultErrors_1.default.DB_ERROR, details: error.message, stack: error };
|
177
|
-
return {
|
178
|
-
data: null,
|
179
|
-
error: error,
|
180
|
-
};
|
181
207
|
}
|
182
208
|
try {
|
183
209
|
let conn = null;
|
184
|
-
if (
|
185
|
-
conn = this.transactions.find(i => i.id ===
|
210
|
+
if (transactionId && transactionId > 0) {
|
211
|
+
conn = this.transactions.find(i => i.id === transactionId)?.conn ?? null;
|
186
212
|
if (this.options.debug)
|
187
213
|
console.log("Execute query on transaction: ", conn?.threadId);
|
188
214
|
}
|
189
215
|
else
|
190
216
|
conn = await this.pool.getConnection();
|
217
|
+
if (this.options.debug) {
|
218
|
+
console.log("Pool status: ", this.poolConnections, this.acquiredPoolConnections);
|
219
|
+
}
|
191
220
|
if (this.options.debug)
|
192
221
|
console.log("Execute query", conn?.threadId);
|
193
|
-
if (
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
if (!request.transactionID)
|
224
|
-
this.finalizeConnection(conn);
|
225
|
-
else if (request.transactionID && request.throwable) {
|
226
|
-
this.rollbackTransaction(this.transactions.find(i => i.id === request.transactionID));
|
227
|
-
this.finalizeConnection(conn);
|
228
|
-
}
|
229
|
-
const error = this.createMysqlQueryError(e);
|
230
|
-
if (`${e}`.indexOf('ECONNREFUSED') !== -1)
|
231
|
-
this.recreatePool();
|
232
|
-
if (request.throwable)
|
233
|
-
throw { ...DefaultErrors_1.default.DB_ERROR, details: error.message, stack: error };
|
222
|
+
if (conn)
|
223
|
+
return conn;
|
224
|
+
}
|
225
|
+
catch (e) {
|
226
|
+
if (`${e}`.indexOf('ECONNREFUSED') !== -1)
|
227
|
+
this.recreatePool();
|
228
|
+
}
|
229
|
+
(0, LogService_1.logCrit)("${MysqlAdapter.js}", `No connection created!`);
|
230
|
+
return {
|
231
|
+
code: "NO_CONN",
|
232
|
+
errno: 100001,
|
233
|
+
fatal: true,
|
234
|
+
sql: "",
|
235
|
+
name: "NO_CONN",
|
236
|
+
message: "Mysql pool cant get connection",
|
237
|
+
};
|
238
|
+
}
|
239
|
+
async query(request, conn) {
|
240
|
+
const query = this.prepareQuery(request);
|
241
|
+
if (request.parseQueryOnly) {
|
242
|
+
return {
|
243
|
+
data: [{ query }],
|
244
|
+
error: null,
|
245
|
+
};
|
246
|
+
}
|
247
|
+
let doCloseConnection = false;
|
248
|
+
if (!conn) {
|
249
|
+
doCloseConnection = true;
|
250
|
+
conn = await this.getConnection(request.transactionID ?? -1);
|
251
|
+
if (this.isError(conn)) {
|
234
252
|
return {
|
235
253
|
data: null,
|
236
|
-
error:
|
254
|
+
error: conn,
|
237
255
|
};
|
238
256
|
}
|
239
257
|
}
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
message: e + "",
|
258
|
+
try {
|
259
|
+
const result = await conn.query(query);
|
260
|
+
this.lastSuccessQueryTime = +new Date();
|
261
|
+
if (!request.transactionID && doCloseConnection)
|
262
|
+
this.finalizeConnection(conn);
|
263
|
+
return {
|
264
|
+
data: result[0],
|
265
|
+
error: null
|
249
266
|
};
|
267
|
+
}
|
268
|
+
catch (e) {
|
269
|
+
if (!request.transactionID && doCloseConnection)
|
270
|
+
this.finalizeConnection(conn);
|
271
|
+
else if (request.transactionID && request.throwable) {
|
272
|
+
this.rollbackTransaction(this.transactions.find(i => i.id === request.transactionID));
|
273
|
+
this.finalizeConnection(conn);
|
274
|
+
}
|
275
|
+
const error = this.createMysqlQueryError(e);
|
276
|
+
if (`${e}`.indexOf('ECONNREFUSED') !== -1)
|
277
|
+
this.recreatePool();
|
250
278
|
if (request.throwable)
|
251
279
|
throw { ...DefaultErrors_1.default.DB_ERROR, details: error.message, stack: error };
|
252
280
|
return {
|
253
281
|
data: null,
|
254
|
-
error:
|
282
|
+
error: this.createMysqlQueryError(e),
|
255
283
|
};
|
256
284
|
}
|
257
285
|
}
|
@@ -464,6 +492,9 @@ class MysqlAdapter {
|
|
464
492
|
if (this.options.transactionFailReport)
|
465
493
|
this.options.transactionFailReport(trx, message);
|
466
494
|
}
|
495
|
+
isError(obj) {
|
496
|
+
return obj && "code" in obj && "errno" in obj && "name" in obj && "message" in obj;
|
497
|
+
}
|
467
498
|
}
|
468
499
|
exports.MysqlAdapter = MysqlAdapter;
|
469
500
|
const secret_key = "AKLWkajw%^&dgwqhw#98453i23bfk23rn2knknglrgjeit";
|