@dbcube/core 3.0.10 → 3.0.14
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 +159 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +159 -27
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -768,9 +768,39 @@ var net = __toESM(require("net"));
|
|
|
768
768
|
var import_child_process2 = require("child_process");
|
|
769
769
|
var globalTcpServers = /* @__PURE__ */ new Map();
|
|
770
770
|
var globalTcpConnections = /* @__PURE__ */ new Map();
|
|
771
|
-
var
|
|
772
|
-
var
|
|
773
|
-
var
|
|
771
|
+
var connectionPools = /* @__PURE__ */ new Map();
|
|
772
|
+
var MAX_POOL_SIZE = 3;
|
|
773
|
+
var LRUCache = class {
|
|
774
|
+
cache = /* @__PURE__ */ new Map();
|
|
775
|
+
maxSize;
|
|
776
|
+
constructor(maxSize) {
|
|
777
|
+
this.maxSize = maxSize;
|
|
778
|
+
}
|
|
779
|
+
get(key) {
|
|
780
|
+
if (this.cache.has(key)) {
|
|
781
|
+
const value = this.cache.get(key);
|
|
782
|
+
this.cache.delete(key);
|
|
783
|
+
this.cache.set(key, value);
|
|
784
|
+
return value;
|
|
785
|
+
}
|
|
786
|
+
return void 0;
|
|
787
|
+
}
|
|
788
|
+
set(key, value) {
|
|
789
|
+
if (this.cache.has(key)) {
|
|
790
|
+
this.cache.delete(key);
|
|
791
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
792
|
+
const firstKey = this.cache.keys().next().value;
|
|
793
|
+
if (firstKey !== void 0) {
|
|
794
|
+
this.cache.delete(firstKey);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
this.cache.set(key, value);
|
|
798
|
+
}
|
|
799
|
+
size() {
|
|
800
|
+
return this.cache.size;
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
var queryCache = new LRUCache(500);
|
|
774
804
|
var QueryEngine = class {
|
|
775
805
|
name;
|
|
776
806
|
config;
|
|
@@ -889,6 +919,7 @@ var QueryEngine = class {
|
|
|
889
919
|
if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
|
|
890
920
|
await this.startTcpServer();
|
|
891
921
|
await this.waitForServerReady();
|
|
922
|
+
await this.initializeConnectionPool();
|
|
892
923
|
}
|
|
893
924
|
return this.sendTcpRequestFast(args);
|
|
894
925
|
}
|
|
@@ -924,15 +955,30 @@ var QueryEngine = class {
|
|
|
924
955
|
sleep(ms) {
|
|
925
956
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
926
957
|
}
|
|
958
|
+
async initializeConnectionPool() {
|
|
959
|
+
console.log("\u{1F3CA} Initializing connection pool...");
|
|
960
|
+
if (!connectionPools.has(this.connectionId)) {
|
|
961
|
+
connectionPools.set(this.connectionId, []);
|
|
962
|
+
}
|
|
963
|
+
const pool = connectionPools.get(this.connectionId);
|
|
964
|
+
for (let i = 0; i < MAX_POOL_SIZE; i++) {
|
|
965
|
+
try {
|
|
966
|
+
const connection = await this.createPooledConnection();
|
|
967
|
+
pool.push(connection);
|
|
968
|
+
console.log(`\u2705 Pool connection ${i + 1}/${MAX_POOL_SIZE} created`);
|
|
969
|
+
} catch (error) {
|
|
970
|
+
console.error(`\u274C Failed to create pool connection ${i + 1}:`, error);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
console.log(`\u{1F680} Connection pool ready with ${pool.length} connections`);
|
|
974
|
+
}
|
|
927
975
|
getCachedDML(dmlJson) {
|
|
928
|
-
|
|
929
|
-
|
|
976
|
+
const cached = queryCache.get(dmlJson);
|
|
977
|
+
if (cached) {
|
|
978
|
+
return cached;
|
|
930
979
|
}
|
|
931
980
|
const parsed = JSON.parse(dmlJson);
|
|
932
|
-
|
|
933
|
-
queryCache.set(dmlJson, parsed);
|
|
934
|
-
cacheSize++;
|
|
935
|
-
}
|
|
981
|
+
queryCache.set(dmlJson, parsed);
|
|
936
982
|
return parsed;
|
|
937
983
|
}
|
|
938
984
|
async startTcpServer() {
|
|
@@ -956,7 +1002,6 @@ var QueryEngine = class {
|
|
|
956
1002
|
if (output.includes("TCP Server listening on")) {
|
|
957
1003
|
if (!started) {
|
|
958
1004
|
started = true;
|
|
959
|
-
clearTimeout(timeout);
|
|
960
1005
|
globalTcpServers.set(this.connectionId, {
|
|
961
1006
|
port: this.tcpPort,
|
|
962
1007
|
process: serverProcess
|
|
@@ -973,7 +1018,6 @@ var QueryEngine = class {
|
|
|
973
1018
|
});
|
|
974
1019
|
serverProcess.on("error", (error) => {
|
|
975
1020
|
if (!started) {
|
|
976
|
-
clearTimeout(timeout);
|
|
977
1021
|
reject(error);
|
|
978
1022
|
}
|
|
979
1023
|
});
|
|
@@ -997,7 +1041,6 @@ var QueryEngine = class {
|
|
|
997
1041
|
if (!dmlJson) {
|
|
998
1042
|
if (!isResolved) {
|
|
999
1043
|
isResolved = true;
|
|
1000
|
-
clearTimeout(timeout);
|
|
1001
1044
|
client.destroy();
|
|
1002
1045
|
reject(new Error("No DML found in arguments"));
|
|
1003
1046
|
}
|
|
@@ -1014,7 +1057,6 @@ var QueryEngine = class {
|
|
|
1014
1057
|
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1015
1058
|
if (match && !isResolved) {
|
|
1016
1059
|
isResolved = true;
|
|
1017
|
-
clearTimeout(timeout);
|
|
1018
1060
|
client.destroy();
|
|
1019
1061
|
try {
|
|
1020
1062
|
const response = JSON.parse(match[1]);
|
|
@@ -1031,13 +1073,11 @@ var QueryEngine = class {
|
|
|
1031
1073
|
client.on("error", (error) => {
|
|
1032
1074
|
if (!isResolved) {
|
|
1033
1075
|
isResolved = true;
|
|
1034
|
-
clearTimeout(timeout);
|
|
1035
1076
|
reject(error);
|
|
1036
1077
|
}
|
|
1037
1078
|
});
|
|
1038
1079
|
client.on("close", () => {
|
|
1039
1080
|
if (!isResolved) {
|
|
1040
|
-
clearTimeout(timeout);
|
|
1041
1081
|
if (!responseBuffer.includes("PROCESS_RESPONSE:")) {
|
|
1042
1082
|
reject(new Error("Connection closed without valid response"));
|
|
1043
1083
|
}
|
|
@@ -1046,18 +1086,24 @@ var QueryEngine = class {
|
|
|
1046
1086
|
});
|
|
1047
1087
|
}
|
|
1048
1088
|
async sendTcpRequestFast(args) {
|
|
1049
|
-
|
|
1050
|
-
|
|
1089
|
+
if (!connectionPools.has(this.connectionId)) {
|
|
1090
|
+
return await this.createAndPoolConnection(args);
|
|
1091
|
+
}
|
|
1092
|
+
const pool = connectionPools.get(this.connectionId);
|
|
1093
|
+
if (pool.length > 0) {
|
|
1094
|
+
const connection = pool.pop();
|
|
1051
1095
|
try {
|
|
1052
|
-
|
|
1096
|
+
const result = await this.sendUltraFast(connection, args);
|
|
1097
|
+
pool.push(connection);
|
|
1098
|
+
return result;
|
|
1053
1099
|
} catch (error) {
|
|
1054
|
-
|
|
1055
|
-
|
|
1100
|
+
connection.destroy();
|
|
1101
|
+
return await this.createAndPoolConnection(args);
|
|
1056
1102
|
}
|
|
1057
1103
|
}
|
|
1058
|
-
return await this.
|
|
1104
|
+
return await this.createAndPoolConnection(args);
|
|
1059
1105
|
}
|
|
1060
|
-
async
|
|
1106
|
+
async sendUltraFast(connection, args) {
|
|
1061
1107
|
return new Promise((resolve5, reject) => {
|
|
1062
1108
|
const dmlIndex = args.findIndex((arg) => arg === "--dml");
|
|
1063
1109
|
const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
|
|
@@ -1067,20 +1113,96 @@ var QueryEngine = class {
|
|
|
1067
1113
|
}
|
|
1068
1114
|
let responseBuffer = "";
|
|
1069
1115
|
let isResolved = false;
|
|
1070
|
-
const
|
|
1116
|
+
const onData = (data) => {
|
|
1117
|
+
responseBuffer += data.toString();
|
|
1118
|
+
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1119
|
+
if (match && !isResolved) {
|
|
1120
|
+
isResolved = true;
|
|
1121
|
+
connection.off("data", onData);
|
|
1122
|
+
connection.off("error", onError);
|
|
1123
|
+
connection.off("close", onClose);
|
|
1124
|
+
try {
|
|
1125
|
+
const response = JSON.parse(match[1]);
|
|
1126
|
+
resolve5({
|
|
1127
|
+
status: response.status,
|
|
1128
|
+
message: response.message,
|
|
1129
|
+
data: response.data
|
|
1130
|
+
});
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
reject(new Error("Failed to parse TCP response"));
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
const onError = (error) => {
|
|
1071
1137
|
if (!isResolved) {
|
|
1072
1138
|
isResolved = true;
|
|
1073
|
-
|
|
1139
|
+
connection.off("data", onData);
|
|
1140
|
+
connection.off("error", onError);
|
|
1141
|
+
connection.off("close", onClose);
|
|
1142
|
+
reject(error);
|
|
1074
1143
|
}
|
|
1075
|
-
}
|
|
1144
|
+
};
|
|
1145
|
+
const onClose = () => {
|
|
1146
|
+
if (!isResolved) {
|
|
1147
|
+
isResolved = true;
|
|
1148
|
+
connection.off("data", onData);
|
|
1149
|
+
connection.off("error", onError);
|
|
1150
|
+
connection.off("close", onClose);
|
|
1151
|
+
connection.off("close", onClose);
|
|
1152
|
+
reject(new Error("Connection closed unexpectedly"));
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
connection.on("data", onData);
|
|
1156
|
+
connection.on("error", onError);
|
|
1157
|
+
connection.on("close", onClose);
|
|
1158
|
+
const command = `{"action":"execute","dml":${dmlJson}}`;
|
|
1159
|
+
connection.write(command);
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
async createAndPoolConnection(args) {
|
|
1163
|
+
const connection = await this.createPooledConnection();
|
|
1164
|
+
if (!connectionPools.has(this.connectionId)) {
|
|
1165
|
+
connectionPools.set(this.connectionId, []);
|
|
1166
|
+
}
|
|
1167
|
+
const result = await this.sendUltraFast(connection, args);
|
|
1168
|
+
const pool = connectionPools.get(this.connectionId);
|
|
1169
|
+
if (pool.length < MAX_POOL_SIZE) {
|
|
1170
|
+
pool.push(connection);
|
|
1171
|
+
} else {
|
|
1172
|
+
connection.destroy();
|
|
1173
|
+
}
|
|
1174
|
+
return result;
|
|
1175
|
+
}
|
|
1176
|
+
async createPooledConnection() {
|
|
1177
|
+
return new Promise((resolve5, reject) => {
|
|
1178
|
+
const client = new net.Socket();
|
|
1179
|
+
client.setNoDelay(true);
|
|
1180
|
+
client.setKeepAlive(true, 0);
|
|
1181
|
+
client.connect(this.tcpPort, "127.0.0.1", () => {
|
|
1182
|
+
resolve5(client);
|
|
1183
|
+
});
|
|
1184
|
+
client.on("error", reject);
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
async sendOnExistingConnection(connection, args) {
|
|
1188
|
+
return new Promise((resolve5, reject) => {
|
|
1189
|
+
const dmlIndex = args.findIndex((arg) => arg === "--dml");
|
|
1190
|
+
const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
|
|
1191
|
+
if (!dmlJson) {
|
|
1192
|
+
reject(new Error("No DML found in arguments"));
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
const dmlParsed = this.getCachedDML(dmlJson);
|
|
1196
|
+
let responseBuffer = "";
|
|
1197
|
+
let isResolved = false;
|
|
1076
1198
|
const onData = (data) => {
|
|
1077
1199
|
responseBuffer += data.toString();
|
|
1078
1200
|
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1079
1201
|
if (match && !isResolved) {
|
|
1080
1202
|
isResolved = true;
|
|
1081
|
-
clearTimeout(timeout);
|
|
1082
1203
|
connection.off("data", onData);
|
|
1083
1204
|
connection.off("error", onError);
|
|
1205
|
+
connection.off("close", onClose);
|
|
1084
1206
|
try {
|
|
1085
1207
|
const response = JSON.parse(match[1]);
|
|
1086
1208
|
resolve5({
|
|
@@ -1096,14 +1218,24 @@ var QueryEngine = class {
|
|
|
1096
1218
|
const onError = (error) => {
|
|
1097
1219
|
if (!isResolved) {
|
|
1098
1220
|
isResolved = true;
|
|
1099
|
-
clearTimeout(timeout);
|
|
1100
1221
|
connection.off("data", onData);
|
|
1101
1222
|
connection.off("error", onError);
|
|
1223
|
+
connection.off("close", onClose);
|
|
1102
1224
|
reject(error);
|
|
1103
1225
|
}
|
|
1104
1226
|
};
|
|
1227
|
+
const onClose = () => {
|
|
1228
|
+
if (!isResolved) {
|
|
1229
|
+
isResolved = true;
|
|
1230
|
+
connection.off("data", onData);
|
|
1231
|
+
connection.off("error", onError);
|
|
1232
|
+
connection.off("close", onClose);
|
|
1233
|
+
reject(new Error("Connection closed unexpectedly"));
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1105
1236
|
connection.on("data", onData);
|
|
1106
1237
|
connection.on("error", onError);
|
|
1238
|
+
connection.on("close", onClose);
|
|
1107
1239
|
const command = {
|
|
1108
1240
|
action: "execute",
|
|
1109
1241
|
dml: dmlJson
|