@dbcube/core 3.0.6 → 3.0.8
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 +221 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +228 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -767,6 +767,7 @@ var import_module2 = require("module");
|
|
|
767
767
|
var net = __toESM(require("net"));
|
|
768
768
|
var import_child_process2 = require("child_process");
|
|
769
769
|
var globalTcpServers = /* @__PURE__ */ new Map();
|
|
770
|
+
var globalTcpConnections = /* @__PURE__ */ new Map();
|
|
770
771
|
var QueryEngine = class {
|
|
771
772
|
name;
|
|
772
773
|
config;
|
|
@@ -784,13 +785,27 @@ var QueryEngine = class {
|
|
|
784
785
|
this.tcpPort = this.generatePort();
|
|
785
786
|
}
|
|
786
787
|
generatePort() {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
788
|
+
return 9944;
|
|
789
|
+
}
|
|
790
|
+
async findAvailablePort(startPort) {
|
|
791
|
+
for (let port = startPort; port >= 9900; port--) {
|
|
792
|
+
if (await this.isPortAvailable(port)) {
|
|
793
|
+
return port;
|
|
794
|
+
}
|
|
792
795
|
}
|
|
793
|
-
|
|
796
|
+
throw new Error("No available ports found in range 9900-9944");
|
|
797
|
+
}
|
|
798
|
+
isPortAvailable(port) {
|
|
799
|
+
return new Promise((resolve5) => {
|
|
800
|
+
const net2 = require("net");
|
|
801
|
+
const tester = net2.createServer();
|
|
802
|
+
tester.once("error", () => resolve5(false));
|
|
803
|
+
tester.once("listening", () => {
|
|
804
|
+
tester.close();
|
|
805
|
+
resolve5(true);
|
|
806
|
+
});
|
|
807
|
+
tester.listen(port, "127.0.0.1");
|
|
808
|
+
});
|
|
794
809
|
}
|
|
795
810
|
async initializeBinary() {
|
|
796
811
|
if (!this.binary) {
|
|
@@ -871,15 +886,51 @@ var QueryEngine = class {
|
|
|
871
886
|
if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
|
|
872
887
|
console.log("\u{1F680} Starting TCP server for ultra-fast queries...");
|
|
873
888
|
await this.startTcpServer();
|
|
889
|
+
await this.waitForServerReady();
|
|
874
890
|
}
|
|
875
891
|
console.log("\u26A1 Using TCP server (ultra-fast)");
|
|
876
|
-
return this.
|
|
892
|
+
return this.sendTcpRequestFast(args);
|
|
893
|
+
}
|
|
894
|
+
async waitForServerReady() {
|
|
895
|
+
const maxRetries = 10;
|
|
896
|
+
const retryDelay = 500;
|
|
897
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
898
|
+
if (await this.isServerResponding()) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
console.log(`\u23F3 Waiting for TCP server to be ready... (${i + 1}/${maxRetries})`);
|
|
902
|
+
await this.sleep(retryDelay);
|
|
903
|
+
}
|
|
904
|
+
throw new Error("TCP server failed to become ready within timeout");
|
|
905
|
+
}
|
|
906
|
+
async isServerResponding() {
|
|
907
|
+
return new Promise((resolve5) => {
|
|
908
|
+
const client = new net.Socket();
|
|
909
|
+
const timeout = setTimeout(() => {
|
|
910
|
+
client.destroy();
|
|
911
|
+
resolve5(false);
|
|
912
|
+
}, 1e3);
|
|
913
|
+
client.connect(this.tcpPort, "127.0.0.1", () => {
|
|
914
|
+
clearTimeout(timeout);
|
|
915
|
+
client.destroy();
|
|
916
|
+
resolve5(true);
|
|
917
|
+
});
|
|
918
|
+
client.on("error", () => {
|
|
919
|
+
clearTimeout(timeout);
|
|
920
|
+
resolve5(false);
|
|
921
|
+
});
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
sleep(ms) {
|
|
925
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
877
926
|
}
|
|
878
927
|
async startTcpServer() {
|
|
879
928
|
await this.initializeBinary();
|
|
880
929
|
if (!this.binary) {
|
|
881
930
|
throw new Error("Binary not initialized");
|
|
882
931
|
}
|
|
932
|
+
this.tcpPort = await this.findAvailablePort(this.tcpPort);
|
|
933
|
+
console.log(`\u{1F310} Using port ${this.tcpPort} for TCP server`);
|
|
883
934
|
return new Promise((resolve5, reject) => {
|
|
884
935
|
const serverArgs = [...this.arguments, "--action", "server", "--port", this.tcpPort.toString()];
|
|
885
936
|
const serverProcess = (0, import_child_process2.spawn)(this.binary["query_engine"], serverArgs);
|
|
@@ -889,7 +940,7 @@ var QueryEngine = class {
|
|
|
889
940
|
serverProcess.kill();
|
|
890
941
|
reject(new Error("TCP server startup timeout"));
|
|
891
942
|
}
|
|
892
|
-
},
|
|
943
|
+
}, 15e3);
|
|
893
944
|
serverProcess.stdout.on("data", (data) => {
|
|
894
945
|
const output = data.toString();
|
|
895
946
|
console.log(`[TCP Server] ${output.trim()}`);
|
|
@@ -924,16 +975,24 @@ var QueryEngine = class {
|
|
|
924
975
|
return new Promise((resolve5, reject) => {
|
|
925
976
|
const client = new net.Socket();
|
|
926
977
|
let responseBuffer = "";
|
|
978
|
+
let isResolved = false;
|
|
927
979
|
const timeout = setTimeout(() => {
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
980
|
+
if (!isResolved) {
|
|
981
|
+
isResolved = true;
|
|
982
|
+
client.destroy();
|
|
983
|
+
reject(new Error("TCP request timeout"));
|
|
984
|
+
}
|
|
985
|
+
}, this.timeout * 2);
|
|
931
986
|
client.connect(this.tcpPort, "127.0.0.1", () => {
|
|
932
987
|
const dmlIndex = args.findIndex((arg) => arg === "--dml");
|
|
933
988
|
const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
|
|
934
989
|
if (!dmlJson) {
|
|
935
|
-
|
|
936
|
-
|
|
990
|
+
if (!isResolved) {
|
|
991
|
+
isResolved = true;
|
|
992
|
+
clearTimeout(timeout);
|
|
993
|
+
client.destroy();
|
|
994
|
+
reject(new Error("No DML found in arguments"));
|
|
995
|
+
}
|
|
937
996
|
return;
|
|
938
997
|
}
|
|
939
998
|
const command = {
|
|
@@ -945,7 +1004,8 @@ var QueryEngine = class {
|
|
|
945
1004
|
client.on("data", (data) => {
|
|
946
1005
|
responseBuffer += data.toString();
|
|
947
1006
|
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
948
|
-
if (match) {
|
|
1007
|
+
if (match && !isResolved) {
|
|
1008
|
+
isResolved = true;
|
|
949
1009
|
clearTimeout(timeout);
|
|
950
1010
|
client.destroy();
|
|
951
1011
|
try {
|
|
@@ -961,13 +1021,149 @@ var QueryEngine = class {
|
|
|
961
1021
|
}
|
|
962
1022
|
});
|
|
963
1023
|
client.on("error", (error) => {
|
|
964
|
-
|
|
965
|
-
|
|
1024
|
+
if (!isResolved) {
|
|
1025
|
+
isResolved = true;
|
|
1026
|
+
clearTimeout(timeout);
|
|
1027
|
+
reject(error);
|
|
1028
|
+
}
|
|
966
1029
|
});
|
|
967
1030
|
client.on("close", () => {
|
|
1031
|
+
if (!isResolved) {
|
|
1032
|
+
clearTimeout(timeout);
|
|
1033
|
+
if (!responseBuffer.includes("PROCESS_RESPONSE:")) {
|
|
1034
|
+
reject(new Error("Connection closed without valid response"));
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
async sendTcpRequestFast(args) {
|
|
1041
|
+
const existingConnection = globalTcpConnections.get(this.connectionId);
|
|
1042
|
+
if (existingConnection && existingConnection.readyState === "open") {
|
|
1043
|
+
try {
|
|
1044
|
+
return await this.sendOnExistingConnection(existingConnection, args);
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1047
|
+
existingConnection.destroy();
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
return await this.createPersistentConnection(args);
|
|
1051
|
+
}
|
|
1052
|
+
async sendOnExistingConnection(connection, args) {
|
|
1053
|
+
return new Promise((resolve5, reject) => {
|
|
1054
|
+
const dmlIndex = args.findIndex((arg) => arg === "--dml");
|
|
1055
|
+
const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
|
|
1056
|
+
if (!dmlJson) {
|
|
1057
|
+
reject(new Error("No DML found in arguments"));
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
let responseBuffer = "";
|
|
1061
|
+
let isResolved = false;
|
|
1062
|
+
const timeout = setTimeout(() => {
|
|
1063
|
+
if (!isResolved) {
|
|
1064
|
+
isResolved = true;
|
|
1065
|
+
reject(new Error("TCP request timeout"));
|
|
1066
|
+
}
|
|
1067
|
+
}, 5e3);
|
|
1068
|
+
const onData = (data) => {
|
|
1069
|
+
responseBuffer += data.toString();
|
|
1070
|
+
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1071
|
+
if (match && !isResolved) {
|
|
1072
|
+
isResolved = true;
|
|
1073
|
+
clearTimeout(timeout);
|
|
1074
|
+
connection.off("data", onData);
|
|
1075
|
+
connection.off("error", onError);
|
|
1076
|
+
try {
|
|
1077
|
+
const response = JSON.parse(match[1]);
|
|
1078
|
+
resolve5({
|
|
1079
|
+
status: response.status,
|
|
1080
|
+
message: response.message,
|
|
1081
|
+
data: response.data
|
|
1082
|
+
});
|
|
1083
|
+
} catch (error) {
|
|
1084
|
+
reject(new Error("Failed to parse TCP response"));
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
const onError = (error) => {
|
|
1089
|
+
if (!isResolved) {
|
|
1090
|
+
isResolved = true;
|
|
1091
|
+
clearTimeout(timeout);
|
|
1092
|
+
connection.off("data", onData);
|
|
1093
|
+
connection.off("error", onError);
|
|
1094
|
+
reject(error);
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
connection.on("data", onData);
|
|
1098
|
+
connection.on("error", onError);
|
|
1099
|
+
const command = {
|
|
1100
|
+
action: "execute",
|
|
1101
|
+
dml: dmlJson
|
|
1102
|
+
};
|
|
1103
|
+
connection.write(JSON.stringify(command));
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
async createPersistentConnection(args) {
|
|
1107
|
+
return new Promise((resolve5, reject) => {
|
|
1108
|
+
const client = new net.Socket();
|
|
1109
|
+
let responseBuffer = "";
|
|
1110
|
+
let isResolved = false;
|
|
1111
|
+
client.setNoDelay(true);
|
|
1112
|
+
client.setKeepAlive(true, 6e4);
|
|
1113
|
+
const timeout = setTimeout(() => {
|
|
1114
|
+
if (!isResolved) {
|
|
1115
|
+
isResolved = true;
|
|
1116
|
+
client.destroy();
|
|
1117
|
+
reject(new Error("TCP connection timeout"));
|
|
1118
|
+
}
|
|
1119
|
+
}, 5e3);
|
|
1120
|
+
client.connect(this.tcpPort, "127.0.0.1", () => {
|
|
968
1121
|
clearTimeout(timeout);
|
|
969
|
-
|
|
970
|
-
|
|
1122
|
+
const dmlIndex = args.findIndex((arg) => arg === "--dml");
|
|
1123
|
+
const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
|
|
1124
|
+
if (!dmlJson) {
|
|
1125
|
+
if (!isResolved) {
|
|
1126
|
+
isResolved = true;
|
|
1127
|
+
client.destroy();
|
|
1128
|
+
reject(new Error("No DML found in arguments"));
|
|
1129
|
+
}
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
globalTcpConnections.set(this.connectionId, client);
|
|
1133
|
+
const command = {
|
|
1134
|
+
action: "execute",
|
|
1135
|
+
dml: dmlJson
|
|
1136
|
+
};
|
|
1137
|
+
client.write(JSON.stringify(command));
|
|
1138
|
+
});
|
|
1139
|
+
client.on("data", (data) => {
|
|
1140
|
+
responseBuffer += data.toString();
|
|
1141
|
+
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1142
|
+
if (match && !isResolved) {
|
|
1143
|
+
isResolved = true;
|
|
1144
|
+
try {
|
|
1145
|
+
const response = JSON.parse(match[1]);
|
|
1146
|
+
resolve5({
|
|
1147
|
+
status: response.status,
|
|
1148
|
+
message: response.message,
|
|
1149
|
+
data: response.data
|
|
1150
|
+
});
|
|
1151
|
+
} catch (error) {
|
|
1152
|
+
reject(new Error("Failed to parse TCP response"));
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
client.on("error", (error) => {
|
|
1157
|
+
if (!isResolved) {
|
|
1158
|
+
isResolved = true;
|
|
1159
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1160
|
+
reject(error);
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
client.on("close", () => {
|
|
1164
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1165
|
+
if (!isResolved && !responseBuffer.includes("PROCESS_RESPONSE:")) {
|
|
1166
|
+
reject(new Error("Connection closed without valid response"));
|
|
971
1167
|
}
|
|
972
1168
|
});
|
|
973
1169
|
});
|
|
@@ -1060,6 +1256,12 @@ var QueryEngine = class {
|
|
|
1060
1256
|
});
|
|
1061
1257
|
}
|
|
1062
1258
|
async disconnect() {
|
|
1259
|
+
const connection = globalTcpConnections.get(this.connectionId);
|
|
1260
|
+
if (connection && connection.readyState === "open") {
|
|
1261
|
+
connection.write(JSON.stringify({ action: "disconnect" }));
|
|
1262
|
+
connection.destroy();
|
|
1263
|
+
globalTcpConnections.delete(this.connectionId);
|
|
1264
|
+
}
|
|
1063
1265
|
const serverInfo = globalTcpServers.get(this.connectionId);
|
|
1064
1266
|
if (serverInfo && serverInfo.process && !serverInfo.process.killed) {
|
|
1065
1267
|
console.log("\u{1F50C} Stopping TCP server...");
|
|
@@ -1067,7 +1269,7 @@ var QueryEngine = class {
|
|
|
1067
1269
|
globalTcpServers.delete(this.connectionId);
|
|
1068
1270
|
return {
|
|
1069
1271
|
status: 200,
|
|
1070
|
-
message: "TCP server stopped",
|
|
1272
|
+
message: "TCP server and connections stopped",
|
|
1071
1273
|
data: null
|
|
1072
1274
|
};
|
|
1073
1275
|
}
|