@dbcube/core 3.0.21 → 3.0.23
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/index.cjs +196 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +197 -194
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -53,8 +53,6 @@ declare class QueryEngine {
|
|
|
53
53
|
private createPersistentConnection;
|
|
54
54
|
private createProcess;
|
|
55
55
|
disconnect(): Promise<ResponseEngine>;
|
|
56
|
-
static getStats(): any;
|
|
57
|
-
static clearAll(): void;
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
interface SystemInfo {
|
|
@@ -124,11 +122,19 @@ interface RunResult {
|
|
|
124
122
|
declare class SqliteExecutor {
|
|
125
123
|
private binaryPath;
|
|
126
124
|
private dbPath;
|
|
125
|
+
private connectionId;
|
|
126
|
+
private tcpPort;
|
|
127
|
+
private useTcp;
|
|
127
128
|
constructor(dbPath: string);
|
|
128
129
|
private getBinaryPath;
|
|
129
130
|
private executeBinary;
|
|
130
131
|
connect(): Promise<boolean>;
|
|
131
132
|
exists(): Promise<boolean>;
|
|
133
|
+
private findAvailablePort;
|
|
134
|
+
private isPortAvailable;
|
|
135
|
+
private startTcpServer;
|
|
136
|
+
private sendTcpQuery;
|
|
137
|
+
private sleep;
|
|
132
138
|
query(sql: string, params?: any[]): Promise<SqliteResult>;
|
|
133
139
|
queryMultiple(sql: string): Promise<SqliteResult>;
|
|
134
140
|
prepare(sql: string): {
|
package/dist/index.d.ts
CHANGED
|
@@ -53,8 +53,6 @@ declare class QueryEngine {
|
|
|
53
53
|
private createPersistentConnection;
|
|
54
54
|
private createProcess;
|
|
55
55
|
disconnect(): Promise<ResponseEngine>;
|
|
56
|
-
static getStats(): any;
|
|
57
|
-
static clearAll(): void;
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
interface SystemInfo {
|
|
@@ -124,11 +122,19 @@ interface RunResult {
|
|
|
124
122
|
declare class SqliteExecutor {
|
|
125
123
|
private binaryPath;
|
|
126
124
|
private dbPath;
|
|
125
|
+
private connectionId;
|
|
126
|
+
private tcpPort;
|
|
127
|
+
private useTcp;
|
|
127
128
|
constructor(dbPath: string);
|
|
128
129
|
private getBinaryPath;
|
|
129
130
|
private executeBinary;
|
|
130
131
|
connect(): Promise<boolean>;
|
|
131
132
|
exists(): Promise<boolean>;
|
|
133
|
+
private findAvailablePort;
|
|
134
|
+
private isPortAvailable;
|
|
135
|
+
private startTcpServer;
|
|
136
|
+
private sendTcpQuery;
|
|
137
|
+
private sleep;
|
|
132
138
|
query(sql: string, params?: any[]): Promise<SqliteResult>;
|
|
133
139
|
queryMultiple(sql: string): Promise<SqliteResult>;
|
|
134
140
|
prepare(sql: string): {
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/lib/Engine.ts
|
|
9
2
|
import path3 from "path";
|
|
10
3
|
|
|
@@ -728,166 +721,11 @@ import path4 from "path";
|
|
|
728
721
|
import { createRequire as createRequire2 } from "module";
|
|
729
722
|
import * as net from "net";
|
|
730
723
|
import { spawn as spawn2 } from "child_process";
|
|
731
|
-
var MAX_CONNECTIONS_PER_DB = 10;
|
|
732
|
-
var MAX_CACHE_ENTRIES = 1e3;
|
|
733
|
-
var CACHE_CLEANUP_THRESHOLD = 0.9;
|
|
734
|
-
var CONNECTION_IDLE_TIMEOUT = 3e5;
|
|
735
|
-
var CONNECTION_MAX_AGE = 36e5;
|
|
736
|
-
var LRUCache = class {
|
|
737
|
-
cache;
|
|
738
|
-
maxSize;
|
|
739
|
-
cleanupThreshold;
|
|
740
|
-
constructor(maxSize, cleanupThreshold = 0.9) {
|
|
741
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
742
|
-
this.maxSize = maxSize;
|
|
743
|
-
this.cleanupThreshold = cleanupThreshold;
|
|
744
|
-
}
|
|
745
|
-
get(key) {
|
|
746
|
-
const entry = this.cache.get(key);
|
|
747
|
-
if (!entry) return void 0;
|
|
748
|
-
entry.lastAccessed = Date.now();
|
|
749
|
-
entry.accessCount++;
|
|
750
|
-
return entry.value;
|
|
751
|
-
}
|
|
752
|
-
set(key, value) {
|
|
753
|
-
if (this.cache.size >= this.maxSize * this.cleanupThreshold) {
|
|
754
|
-
this.evictLRU();
|
|
755
|
-
}
|
|
756
|
-
this.cache.set(key, {
|
|
757
|
-
value,
|
|
758
|
-
lastAccessed: Date.now(),
|
|
759
|
-
accessCount: 1
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
evictLRU() {
|
|
763
|
-
const entries = Array.from(this.cache.entries()).sort((a, b) => {
|
|
764
|
-
const scoreDiff = this.calculateScore(a[1]) - this.calculateScore(b[1]);
|
|
765
|
-
if (scoreDiff !== 0) return scoreDiff;
|
|
766
|
-
return a[1].lastAccessed - b[1].lastAccessed;
|
|
767
|
-
});
|
|
768
|
-
const toRemove = Math.floor(this.maxSize * 0.2);
|
|
769
|
-
for (let i = 0; i < toRemove && i < entries.length; i++) {
|
|
770
|
-
this.cache.delete(entries[i][0]);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
calculateScore(entry) {
|
|
774
|
-
const now = Date.now();
|
|
775
|
-
const age = now - entry.lastAccessed;
|
|
776
|
-
const recencyScore = 1 / (age + 1);
|
|
777
|
-
const frequencyScore = entry.accessCount;
|
|
778
|
-
return recencyScore * 0.3 + frequencyScore * 0.7;
|
|
779
|
-
}
|
|
780
|
-
clear() {
|
|
781
|
-
this.cache.clear();
|
|
782
|
-
}
|
|
783
|
-
size() {
|
|
784
|
-
return this.cache.size;
|
|
785
|
-
}
|
|
786
|
-
};
|
|
787
|
-
var ConnectionPool = class {
|
|
788
|
-
pools;
|
|
789
|
-
maxConnectionsPerDb;
|
|
790
|
-
constructor(maxConnectionsPerDb = MAX_CONNECTIONS_PER_DB) {
|
|
791
|
-
this.pools = /* @__PURE__ */ new Map();
|
|
792
|
-
this.maxConnectionsPerDb = maxConnectionsPerDb;
|
|
793
|
-
setInterval(() => this.cleanupIdleConnections(), 6e4);
|
|
794
|
-
}
|
|
795
|
-
getConnection(connectionId) {
|
|
796
|
-
const pool = this.pools.get(connectionId);
|
|
797
|
-
if (!pool || pool.length === 0) return null;
|
|
798
|
-
for (let i = 0; i < pool.length; i++) {
|
|
799
|
-
const conn = pool[i];
|
|
800
|
-
if (this.isConnectionValid(conn)) {
|
|
801
|
-
conn.lastUsed = Date.now();
|
|
802
|
-
conn.requestCount++;
|
|
803
|
-
return conn.socket;
|
|
804
|
-
} else {
|
|
805
|
-
conn.socket.destroy();
|
|
806
|
-
pool.splice(i, 1);
|
|
807
|
-
i--;
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
return null;
|
|
811
|
-
}
|
|
812
|
-
addConnection(connectionId, socket) {
|
|
813
|
-
if (!this.pools.has(connectionId)) {
|
|
814
|
-
this.pools.set(connectionId, []);
|
|
815
|
-
}
|
|
816
|
-
const pool = this.pools.get(connectionId);
|
|
817
|
-
if (pool.length >= this.maxConnectionsPerDb) {
|
|
818
|
-
const oldest = pool.shift();
|
|
819
|
-
if (oldest) {
|
|
820
|
-
oldest.socket.destroy();
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
pool.push({
|
|
824
|
-
socket,
|
|
825
|
-
lastUsed: Date.now(),
|
|
826
|
-
createdAt: Date.now(),
|
|
827
|
-
requestCount: 0
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
|
-
removeConnection(connectionId, socket) {
|
|
831
|
-
const pool = this.pools.get(connectionId);
|
|
832
|
-
if (!pool) return;
|
|
833
|
-
const index = pool.findIndex((c) => c.socket === socket);
|
|
834
|
-
if (index !== -1) {
|
|
835
|
-
pool[index].socket.destroy();
|
|
836
|
-
pool.splice(index, 1);
|
|
837
|
-
}
|
|
838
|
-
if (pool.length === 0) {
|
|
839
|
-
this.pools.delete(connectionId);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
closeAll(connectionId) {
|
|
843
|
-
if (connectionId) {
|
|
844
|
-
const pool = this.pools.get(connectionId);
|
|
845
|
-
if (pool) {
|
|
846
|
-
pool.forEach((conn) => conn.socket.destroy());
|
|
847
|
-
this.pools.delete(connectionId);
|
|
848
|
-
}
|
|
849
|
-
} else {
|
|
850
|
-
this.pools.forEach((pool) => {
|
|
851
|
-
pool.forEach((conn) => conn.socket.destroy());
|
|
852
|
-
});
|
|
853
|
-
this.pools.clear();
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
isConnectionValid(conn) {
|
|
857
|
-
const now = Date.now();
|
|
858
|
-
const age = now - conn.createdAt;
|
|
859
|
-
return conn.socket.readyState === "open" && age < CONNECTION_MAX_AGE;
|
|
860
|
-
}
|
|
861
|
-
cleanupIdleConnections() {
|
|
862
|
-
const now = Date.now();
|
|
863
|
-
this.pools.forEach((pool, connectionId) => {
|
|
864
|
-
for (let i = pool.length - 1; i >= 0; i--) {
|
|
865
|
-
const conn = pool[i];
|
|
866
|
-
const idleTime = now - conn.lastUsed;
|
|
867
|
-
if (idleTime > CONNECTION_IDLE_TIMEOUT || !this.isConnectionValid(conn)) {
|
|
868
|
-
conn.socket.destroy();
|
|
869
|
-
pool.splice(i, 1);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
if (pool.length === 0) {
|
|
873
|
-
this.pools.delete(connectionId);
|
|
874
|
-
}
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
|
-
getStats() {
|
|
878
|
-
const stats = {};
|
|
879
|
-
this.pools.forEach((pool, id) => {
|
|
880
|
-
stats[id] = {
|
|
881
|
-
activeConnections: pool.length,
|
|
882
|
-
totalRequests: pool.reduce((sum, c) => sum + c.requestCount, 0)
|
|
883
|
-
};
|
|
884
|
-
});
|
|
885
|
-
return stats;
|
|
886
|
-
}
|
|
887
|
-
};
|
|
888
724
|
var globalTcpServers = /* @__PURE__ */ new Map();
|
|
889
|
-
var
|
|
890
|
-
var queryCache = new
|
|
725
|
+
var globalTcpConnections = /* @__PURE__ */ new Map();
|
|
726
|
+
var queryCache = /* @__PURE__ */ new Map();
|
|
727
|
+
var cacheSize = 0;
|
|
728
|
+
var MAX_CACHE_SIZE = 500;
|
|
891
729
|
var QueryEngine = class {
|
|
892
730
|
name;
|
|
893
731
|
config;
|
|
@@ -917,8 +755,7 @@ var QueryEngine = class {
|
|
|
917
755
|
}
|
|
918
756
|
isPortAvailable(port) {
|
|
919
757
|
return new Promise((resolve5) => {
|
|
920
|
-
const
|
|
921
|
-
const tester = net2.createServer();
|
|
758
|
+
const tester = net.createServer();
|
|
922
759
|
tester.once("error", () => resolve5(false));
|
|
923
760
|
tester.once("listening", () => {
|
|
924
761
|
tester.close();
|
|
@@ -1042,12 +879,14 @@ var QueryEngine = class {
|
|
|
1042
879
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1043
880
|
}
|
|
1044
881
|
getCachedDML(dmlJson) {
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
return cached;
|
|
882
|
+
if (queryCache.has(dmlJson)) {
|
|
883
|
+
return queryCache.get(dmlJson);
|
|
1048
884
|
}
|
|
1049
885
|
const parsed = JSON.parse(dmlJson);
|
|
1050
|
-
|
|
886
|
+
if (cacheSize < MAX_CACHE_SIZE) {
|
|
887
|
+
queryCache.set(dmlJson, parsed);
|
|
888
|
+
cacheSize++;
|
|
889
|
+
}
|
|
1051
890
|
return parsed;
|
|
1052
891
|
}
|
|
1053
892
|
async startTcpServer() {
|
|
@@ -1161,12 +1000,13 @@ var QueryEngine = class {
|
|
|
1161
1000
|
});
|
|
1162
1001
|
}
|
|
1163
1002
|
async sendTcpRequestFast(args) {
|
|
1164
|
-
const existingConnection =
|
|
1003
|
+
const existingConnection = globalTcpConnections.get(this.connectionId);
|
|
1165
1004
|
if (existingConnection && existingConnection.readyState === "open") {
|
|
1166
1005
|
try {
|
|
1167
1006
|
return await this.sendOnExistingConnection(existingConnection, args);
|
|
1168
1007
|
} catch (error) {
|
|
1169
|
-
|
|
1008
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1009
|
+
existingConnection.destroy();
|
|
1170
1010
|
}
|
|
1171
1011
|
}
|
|
1172
1012
|
return await this.createPersistentConnection(args);
|
|
@@ -1251,7 +1091,7 @@ var QueryEngine = class {
|
|
|
1251
1091
|
}
|
|
1252
1092
|
return;
|
|
1253
1093
|
}
|
|
1254
|
-
|
|
1094
|
+
globalTcpConnections.set(this.connectionId, client);
|
|
1255
1095
|
const command = {
|
|
1256
1096
|
action: "execute",
|
|
1257
1097
|
dml: dmlJson
|
|
@@ -1278,12 +1118,12 @@ var QueryEngine = class {
|
|
|
1278
1118
|
client.on("error", (error) => {
|
|
1279
1119
|
if (!isResolved) {
|
|
1280
1120
|
isResolved = true;
|
|
1281
|
-
|
|
1121
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1282
1122
|
reject(error);
|
|
1283
1123
|
}
|
|
1284
1124
|
});
|
|
1285
1125
|
client.on("close", () => {
|
|
1286
|
-
|
|
1126
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1287
1127
|
if (!isResolved && !responseBuffer.includes("PROCESS_RESPONSE:")) {
|
|
1288
1128
|
reject(new Error("Connection closed without valid response"));
|
|
1289
1129
|
}
|
|
@@ -1378,7 +1218,12 @@ var QueryEngine = class {
|
|
|
1378
1218
|
});
|
|
1379
1219
|
}
|
|
1380
1220
|
async disconnect() {
|
|
1381
|
-
|
|
1221
|
+
const connection = globalTcpConnections.get(this.connectionId);
|
|
1222
|
+
if (connection && connection.readyState === "open") {
|
|
1223
|
+
connection.write(JSON.stringify({ action: "disconnect" }));
|
|
1224
|
+
connection.destroy();
|
|
1225
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1226
|
+
}
|
|
1382
1227
|
const serverInfo = globalTcpServers.get(this.connectionId);
|
|
1383
1228
|
if (serverInfo && serverInfo.process && !serverInfo.process.killed) {
|
|
1384
1229
|
serverInfo.process.kill();
|
|
@@ -1395,36 +1240,28 @@ var QueryEngine = class {
|
|
|
1395
1240
|
data: null
|
|
1396
1241
|
};
|
|
1397
1242
|
}
|
|
1398
|
-
// Método para obtener estadísticas del pool y cache
|
|
1399
|
-
static getStats() {
|
|
1400
|
-
return {
|
|
1401
|
-
connectionPool: connectionPool.getStats(),
|
|
1402
|
-
cache: {
|
|
1403
|
-
size: queryCache.size(),
|
|
1404
|
-
maxSize: MAX_CACHE_ENTRIES
|
|
1405
|
-
}
|
|
1406
|
-
};
|
|
1407
|
-
}
|
|
1408
|
-
// Método para limpiar todo el cache y conexiones
|
|
1409
|
-
static clearAll() {
|
|
1410
|
-
queryCache.clear();
|
|
1411
|
-
connectionPool.closeAll();
|
|
1412
|
-
}
|
|
1413
1243
|
};
|
|
1414
1244
|
|
|
1415
1245
|
// src/lib/SqliteExecutor.ts
|
|
1416
|
-
import { exec } from "child_process";
|
|
1246
|
+
import { exec, spawn as spawn3 } from "child_process";
|
|
1417
1247
|
import * as path5 from "path";
|
|
1418
1248
|
import * as fs3 from "fs";
|
|
1419
1249
|
import { promisify } from "util";
|
|
1420
1250
|
import { createRequire as createRequire3 } from "module";
|
|
1251
|
+
import * as net2 from "net";
|
|
1421
1252
|
var execAsync = promisify(exec);
|
|
1253
|
+
var globalSqliteServers = /* @__PURE__ */ new Map();
|
|
1254
|
+
var globalSqliteConnections = /* @__PURE__ */ new Map();
|
|
1422
1255
|
var SqliteExecutor = class {
|
|
1423
1256
|
binaryPath;
|
|
1424
1257
|
dbPath;
|
|
1258
|
+
connectionId;
|
|
1259
|
+
tcpPort = 9944;
|
|
1260
|
+
useTcp = true;
|
|
1425
1261
|
constructor(dbPath) {
|
|
1426
1262
|
this.dbPath = dbPath;
|
|
1427
1263
|
this.binaryPath = this.getBinaryPath();
|
|
1264
|
+
this.connectionId = `sqlite_${dbPath.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
1428
1265
|
}
|
|
1429
1266
|
getBinaryPath() {
|
|
1430
1267
|
const possibleDirs = [
|
|
@@ -1507,7 +1344,173 @@ var SqliteExecutor = class {
|
|
|
1507
1344
|
return false;
|
|
1508
1345
|
}
|
|
1509
1346
|
}
|
|
1347
|
+
async findAvailablePort(startPort) {
|
|
1348
|
+
for (let port = startPort; port >= 9900; port--) {
|
|
1349
|
+
if (await this.isPortAvailable(port)) {
|
|
1350
|
+
return port;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
throw new Error("No available ports found in range 9900-9944");
|
|
1354
|
+
}
|
|
1355
|
+
isPortAvailable(port) {
|
|
1356
|
+
return new Promise((resolve5) => {
|
|
1357
|
+
const tester = net2.createServer();
|
|
1358
|
+
tester.once("error", () => resolve5(false));
|
|
1359
|
+
tester.once("listening", () => {
|
|
1360
|
+
tester.close();
|
|
1361
|
+
resolve5(true);
|
|
1362
|
+
});
|
|
1363
|
+
tester.listen(port, "127.0.0.1");
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
async startTcpServer() {
|
|
1367
|
+
this.tcpPort = await this.findAvailablePort(this.tcpPort);
|
|
1368
|
+
return new Promise((resolve5, reject) => {
|
|
1369
|
+
const serverArgs = [
|
|
1370
|
+
"--action",
|
|
1371
|
+
"serve",
|
|
1372
|
+
"--id",
|
|
1373
|
+
this.connectionId,
|
|
1374
|
+
"--database-ref",
|
|
1375
|
+
"config",
|
|
1376
|
+
"--database",
|
|
1377
|
+
this.dbPath
|
|
1378
|
+
];
|
|
1379
|
+
const serverProcess = spawn3(this.binaryPath, serverArgs);
|
|
1380
|
+
let started = false;
|
|
1381
|
+
const timeout = setTimeout(() => {
|
|
1382
|
+
if (!started) {
|
|
1383
|
+
serverProcess.kill();
|
|
1384
|
+
reject(new Error("SQLite TCP server startup timeout"));
|
|
1385
|
+
}
|
|
1386
|
+
}, 1e4);
|
|
1387
|
+
serverProcess.stdout.on("data", (data) => {
|
|
1388
|
+
const output = data.toString();
|
|
1389
|
+
if (output.includes("SQLite TCP Server started") || output.includes("PROCESS_RESPONSE:")) {
|
|
1390
|
+
if (!started) {
|
|
1391
|
+
started = true;
|
|
1392
|
+
clearTimeout(timeout);
|
|
1393
|
+
const match = output.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1394
|
+
if (match) {
|
|
1395
|
+
try {
|
|
1396
|
+
const response = JSON.parse(match[1]);
|
|
1397
|
+
if (response.data && response.data.port) {
|
|
1398
|
+
this.tcpPort = response.data.port;
|
|
1399
|
+
}
|
|
1400
|
+
} catch (e) {
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
globalSqliteServers.set(this.connectionId, {
|
|
1404
|
+
port: this.tcpPort,
|
|
1405
|
+
process: serverProcess
|
|
1406
|
+
});
|
|
1407
|
+
resolve5();
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
});
|
|
1411
|
+
serverProcess.stderr.on("data", (data) => {
|
|
1412
|
+
console.error(`[SQLite Server Error] ${data.toString().trim()}`);
|
|
1413
|
+
});
|
|
1414
|
+
serverProcess.on("close", () => {
|
|
1415
|
+
globalSqliteServers.delete(this.connectionId);
|
|
1416
|
+
globalSqliteConnections.delete(this.connectionId);
|
|
1417
|
+
});
|
|
1418
|
+
serverProcess.on("error", (error) => {
|
|
1419
|
+
if (!started) {
|
|
1420
|
+
clearTimeout(timeout);
|
|
1421
|
+
reject(error);
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
async sendTcpQuery(sql, params) {
|
|
1427
|
+
const serverInfo = globalSqliteServers.get(this.connectionId);
|
|
1428
|
+
if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
|
|
1429
|
+
await this.startTcpServer();
|
|
1430
|
+
await this.sleep(500);
|
|
1431
|
+
}
|
|
1432
|
+
return new Promise((resolve5, reject) => {
|
|
1433
|
+
const client = new net2.Socket();
|
|
1434
|
+
let responseBuffer = "";
|
|
1435
|
+
let isResolved = false;
|
|
1436
|
+
const timeout = setTimeout(() => {
|
|
1437
|
+
if (!isResolved) {
|
|
1438
|
+
isResolved = true;
|
|
1439
|
+
client.destroy();
|
|
1440
|
+
reject(new Error("TCP query timeout"));
|
|
1441
|
+
}
|
|
1442
|
+
}, 1e4);
|
|
1443
|
+
client.connect(this.tcpPort, "127.0.0.1", () => {
|
|
1444
|
+
const command = {
|
|
1445
|
+
action: "query",
|
|
1446
|
+
query: sql,
|
|
1447
|
+
params: params || []
|
|
1448
|
+
};
|
|
1449
|
+
client.write(JSON.stringify(command) + "\n");
|
|
1450
|
+
});
|
|
1451
|
+
client.on("data", (data) => {
|
|
1452
|
+
responseBuffer += data.toString();
|
|
1453
|
+
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1454
|
+
if (match && !isResolved) {
|
|
1455
|
+
isResolved = true;
|
|
1456
|
+
clearTimeout(timeout);
|
|
1457
|
+
client.destroy();
|
|
1458
|
+
try {
|
|
1459
|
+
const response = JSON.parse(match[1]);
|
|
1460
|
+
if (response.code === 200) {
|
|
1461
|
+
resolve5({
|
|
1462
|
+
status: "success",
|
|
1463
|
+
message: response.message,
|
|
1464
|
+
data: response.data
|
|
1465
|
+
});
|
|
1466
|
+
} else {
|
|
1467
|
+
resolve5({
|
|
1468
|
+
status: "error",
|
|
1469
|
+
message: response.message,
|
|
1470
|
+
data: null
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
} catch (error) {
|
|
1474
|
+
reject(new Error("Failed to parse TCP response"));
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
});
|
|
1478
|
+
client.on("error", (error) => {
|
|
1479
|
+
if (!isResolved) {
|
|
1480
|
+
isResolved = true;
|
|
1481
|
+
clearTimeout(timeout);
|
|
1482
|
+
this.useTcp = false;
|
|
1483
|
+
this.executeBinary([
|
|
1484
|
+
"--action",
|
|
1485
|
+
"query",
|
|
1486
|
+
"--database",
|
|
1487
|
+
this.dbPath,
|
|
1488
|
+
"--query",
|
|
1489
|
+
sql,
|
|
1490
|
+
...params && params.length > 0 ? ["--params", JSON.stringify(params)] : []
|
|
1491
|
+
]).then(resolve5).catch(reject);
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
client.on("close", () => {
|
|
1495
|
+
if (!isResolved) {
|
|
1496
|
+
clearTimeout(timeout);
|
|
1497
|
+
reject(new Error("Connection closed without valid response"));
|
|
1498
|
+
}
|
|
1499
|
+
});
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
sleep(ms) {
|
|
1503
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1504
|
+
}
|
|
1510
1505
|
async query(sql, params) {
|
|
1506
|
+
if (this.useTcp) {
|
|
1507
|
+
try {
|
|
1508
|
+
return await this.sendTcpQuery(sql, params);
|
|
1509
|
+
} catch (error) {
|
|
1510
|
+
console.warn("TCP query failed, falling back to direct execution");
|
|
1511
|
+
this.useTcp = false;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1511
1514
|
const args = [
|
|
1512
1515
|
"--action",
|
|
1513
1516
|
"query",
|