@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.d.mts CHANGED
@@ -32,6 +32,8 @@ declare class QueryEngine {
32
32
  private tcpPort;
33
33
  constructor(name: string, timeout?: number);
34
34
  private generatePort;
35
+ private findAvailablePort;
36
+ private isPortAvailable;
35
37
  initializeBinary(): Promise<void>;
36
38
  setArguments(): any[];
37
39
  setConfig(name: string): {
@@ -40,8 +42,14 @@ declare class QueryEngine {
40
42
  getConfig(): any;
41
43
  run(binary: string, args: string[]): Promise<ResponseEngine>;
42
44
  private executeWithTcpServer;
45
+ private waitForServerReady;
46
+ private isServerResponding;
47
+ private sleep;
43
48
  private startTcpServer;
44
49
  private sendTcpRequest;
50
+ private sendTcpRequestFast;
51
+ private sendOnExistingConnection;
52
+ private createPersistentConnection;
45
53
  private createProcess;
46
54
  disconnect(): Promise<ResponseEngine>;
47
55
  }
package/dist/index.d.ts CHANGED
@@ -32,6 +32,8 @@ declare class QueryEngine {
32
32
  private tcpPort;
33
33
  constructor(name: string, timeout?: number);
34
34
  private generatePort;
35
+ private findAvailablePort;
36
+ private isPortAvailable;
35
37
  initializeBinary(): Promise<void>;
36
38
  setArguments(): any[];
37
39
  setConfig(name: string): {
@@ -40,8 +42,14 @@ declare class QueryEngine {
40
42
  getConfig(): any;
41
43
  run(binary: string, args: string[]): Promise<ResponseEngine>;
42
44
  private executeWithTcpServer;
45
+ private waitForServerReady;
46
+ private isServerResponding;
47
+ private sleep;
43
48
  private startTcpServer;
44
49
  private sendTcpRequest;
50
+ private sendTcpRequestFast;
51
+ private sendOnExistingConnection;
52
+ private createPersistentConnection;
45
53
  private createProcess;
46
54
  disconnect(): Promise<ResponseEngine>;
47
55
  }
package/dist/index.js CHANGED
@@ -1,3 +1,10 @@
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
+
1
8
  // src/lib/Engine.ts
2
9
  import path3 from "path";
3
10
 
@@ -722,6 +729,7 @@ import { createRequire as createRequire2 } from "module";
722
729
  import * as net from "net";
723
730
  import { spawn as spawn2 } from "child_process";
724
731
  var globalTcpServers = /* @__PURE__ */ new Map();
732
+ var globalTcpConnections = /* @__PURE__ */ new Map();
725
733
  var QueryEngine = class {
726
734
  name;
727
735
  config;
@@ -739,13 +747,27 @@ var QueryEngine = class {
739
747
  this.tcpPort = this.generatePort();
740
748
  }
741
749
  generatePort() {
742
- let hash = 0;
743
- for (let i = 0; i < this.connectionId.length; i++) {
744
- const char = this.connectionId.charCodeAt(i);
745
- hash = (hash << 5) - hash + char;
746
- hash = hash & hash;
750
+ return 9944;
751
+ }
752
+ async findAvailablePort(startPort) {
753
+ for (let port = startPort; port >= 9900; port--) {
754
+ if (await this.isPortAvailable(port)) {
755
+ return port;
756
+ }
747
757
  }
748
- return 8100 + Math.abs(hash % 900);
758
+ throw new Error("No available ports found in range 9900-9944");
759
+ }
760
+ isPortAvailable(port) {
761
+ return new Promise((resolve5) => {
762
+ const net2 = __require("net");
763
+ const tester = net2.createServer();
764
+ tester.once("error", () => resolve5(false));
765
+ tester.once("listening", () => {
766
+ tester.close();
767
+ resolve5(true);
768
+ });
769
+ tester.listen(port, "127.0.0.1");
770
+ });
749
771
  }
750
772
  async initializeBinary() {
751
773
  if (!this.binary) {
@@ -826,15 +848,51 @@ var QueryEngine = class {
826
848
  if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
827
849
  console.log("\u{1F680} Starting TCP server for ultra-fast queries...");
828
850
  await this.startTcpServer();
851
+ await this.waitForServerReady();
829
852
  }
830
853
  console.log("\u26A1 Using TCP server (ultra-fast)");
831
- return this.sendTcpRequest(args);
854
+ return this.sendTcpRequestFast(args);
855
+ }
856
+ async waitForServerReady() {
857
+ const maxRetries = 10;
858
+ const retryDelay = 500;
859
+ for (let i = 0; i < maxRetries; i++) {
860
+ if (await this.isServerResponding()) {
861
+ return;
862
+ }
863
+ console.log(`\u23F3 Waiting for TCP server to be ready... (${i + 1}/${maxRetries})`);
864
+ await this.sleep(retryDelay);
865
+ }
866
+ throw new Error("TCP server failed to become ready within timeout");
867
+ }
868
+ async isServerResponding() {
869
+ return new Promise((resolve5) => {
870
+ const client = new net.Socket();
871
+ const timeout = setTimeout(() => {
872
+ client.destroy();
873
+ resolve5(false);
874
+ }, 1e3);
875
+ client.connect(this.tcpPort, "127.0.0.1", () => {
876
+ clearTimeout(timeout);
877
+ client.destroy();
878
+ resolve5(true);
879
+ });
880
+ client.on("error", () => {
881
+ clearTimeout(timeout);
882
+ resolve5(false);
883
+ });
884
+ });
885
+ }
886
+ sleep(ms) {
887
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
832
888
  }
833
889
  async startTcpServer() {
834
890
  await this.initializeBinary();
835
891
  if (!this.binary) {
836
892
  throw new Error("Binary not initialized");
837
893
  }
894
+ this.tcpPort = await this.findAvailablePort(this.tcpPort);
895
+ console.log(`\u{1F310} Using port ${this.tcpPort} for TCP server`);
838
896
  return new Promise((resolve5, reject) => {
839
897
  const serverArgs = [...this.arguments, "--action", "server", "--port", this.tcpPort.toString()];
840
898
  const serverProcess = spawn2(this.binary["query_engine"], serverArgs);
@@ -844,7 +902,7 @@ var QueryEngine = class {
844
902
  serverProcess.kill();
845
903
  reject(new Error("TCP server startup timeout"));
846
904
  }
847
- }, 1e4);
905
+ }, 15e3);
848
906
  serverProcess.stdout.on("data", (data) => {
849
907
  const output = data.toString();
850
908
  console.log(`[TCP Server] ${output.trim()}`);
@@ -879,16 +937,24 @@ var QueryEngine = class {
879
937
  return new Promise((resolve5, reject) => {
880
938
  const client = new net.Socket();
881
939
  let responseBuffer = "";
940
+ let isResolved = false;
882
941
  const timeout = setTimeout(() => {
883
- client.destroy();
884
- reject(new Error("TCP request timeout"));
885
- }, this.timeout);
942
+ if (!isResolved) {
943
+ isResolved = true;
944
+ client.destroy();
945
+ reject(new Error("TCP request timeout"));
946
+ }
947
+ }, this.timeout * 2);
886
948
  client.connect(this.tcpPort, "127.0.0.1", () => {
887
949
  const dmlIndex = args.findIndex((arg) => arg === "--dml");
888
950
  const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
889
951
  if (!dmlJson) {
890
- client.destroy();
891
- reject(new Error("No DML found in arguments"));
952
+ if (!isResolved) {
953
+ isResolved = true;
954
+ clearTimeout(timeout);
955
+ client.destroy();
956
+ reject(new Error("No DML found in arguments"));
957
+ }
892
958
  return;
893
959
  }
894
960
  const command = {
@@ -900,7 +966,8 @@ var QueryEngine = class {
900
966
  client.on("data", (data) => {
901
967
  responseBuffer += data.toString();
902
968
  const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
903
- if (match) {
969
+ if (match && !isResolved) {
970
+ isResolved = true;
904
971
  clearTimeout(timeout);
905
972
  client.destroy();
906
973
  try {
@@ -916,13 +983,149 @@ var QueryEngine = class {
916
983
  }
917
984
  });
918
985
  client.on("error", (error) => {
919
- clearTimeout(timeout);
920
- reject(error);
986
+ if (!isResolved) {
987
+ isResolved = true;
988
+ clearTimeout(timeout);
989
+ reject(error);
990
+ }
921
991
  });
922
992
  client.on("close", () => {
993
+ if (!isResolved) {
994
+ clearTimeout(timeout);
995
+ if (!responseBuffer.includes("PROCESS_RESPONSE:")) {
996
+ reject(new Error("Connection closed without valid response"));
997
+ }
998
+ }
999
+ });
1000
+ });
1001
+ }
1002
+ async sendTcpRequestFast(args) {
1003
+ const existingConnection = globalTcpConnections.get(this.connectionId);
1004
+ if (existingConnection && existingConnection.readyState === "open") {
1005
+ try {
1006
+ return await this.sendOnExistingConnection(existingConnection, args);
1007
+ } catch (error) {
1008
+ globalTcpConnections.delete(this.connectionId);
1009
+ existingConnection.destroy();
1010
+ }
1011
+ }
1012
+ return await this.createPersistentConnection(args);
1013
+ }
1014
+ async sendOnExistingConnection(connection, args) {
1015
+ return new Promise((resolve5, reject) => {
1016
+ const dmlIndex = args.findIndex((arg) => arg === "--dml");
1017
+ const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
1018
+ if (!dmlJson) {
1019
+ reject(new Error("No DML found in arguments"));
1020
+ return;
1021
+ }
1022
+ let responseBuffer = "";
1023
+ let isResolved = false;
1024
+ const timeout = setTimeout(() => {
1025
+ if (!isResolved) {
1026
+ isResolved = true;
1027
+ reject(new Error("TCP request timeout"));
1028
+ }
1029
+ }, 5e3);
1030
+ const onData = (data) => {
1031
+ responseBuffer += data.toString();
1032
+ const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1033
+ if (match && !isResolved) {
1034
+ isResolved = true;
1035
+ clearTimeout(timeout);
1036
+ connection.off("data", onData);
1037
+ connection.off("error", onError);
1038
+ try {
1039
+ const response = JSON.parse(match[1]);
1040
+ resolve5({
1041
+ status: response.status,
1042
+ message: response.message,
1043
+ data: response.data
1044
+ });
1045
+ } catch (error) {
1046
+ reject(new Error("Failed to parse TCP response"));
1047
+ }
1048
+ }
1049
+ };
1050
+ const onError = (error) => {
1051
+ if (!isResolved) {
1052
+ isResolved = true;
1053
+ clearTimeout(timeout);
1054
+ connection.off("data", onData);
1055
+ connection.off("error", onError);
1056
+ reject(error);
1057
+ }
1058
+ };
1059
+ connection.on("data", onData);
1060
+ connection.on("error", onError);
1061
+ const command = {
1062
+ action: "execute",
1063
+ dml: dmlJson
1064
+ };
1065
+ connection.write(JSON.stringify(command));
1066
+ });
1067
+ }
1068
+ async createPersistentConnection(args) {
1069
+ return new Promise((resolve5, reject) => {
1070
+ const client = new net.Socket();
1071
+ let responseBuffer = "";
1072
+ let isResolved = false;
1073
+ client.setNoDelay(true);
1074
+ client.setKeepAlive(true, 6e4);
1075
+ const timeout = setTimeout(() => {
1076
+ if (!isResolved) {
1077
+ isResolved = true;
1078
+ client.destroy();
1079
+ reject(new Error("TCP connection timeout"));
1080
+ }
1081
+ }, 5e3);
1082
+ client.connect(this.tcpPort, "127.0.0.1", () => {
923
1083
  clearTimeout(timeout);
924
- if (responseBuffer && !responseBuffer.includes("\n")) {
925
- reject(new Error("Incomplete TCP response"));
1084
+ const dmlIndex = args.findIndex((arg) => arg === "--dml");
1085
+ const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
1086
+ if (!dmlJson) {
1087
+ if (!isResolved) {
1088
+ isResolved = true;
1089
+ client.destroy();
1090
+ reject(new Error("No DML found in arguments"));
1091
+ }
1092
+ return;
1093
+ }
1094
+ globalTcpConnections.set(this.connectionId, client);
1095
+ const command = {
1096
+ action: "execute",
1097
+ dml: dmlJson
1098
+ };
1099
+ client.write(JSON.stringify(command));
1100
+ });
1101
+ client.on("data", (data) => {
1102
+ responseBuffer += data.toString();
1103
+ const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1104
+ if (match && !isResolved) {
1105
+ isResolved = true;
1106
+ try {
1107
+ const response = JSON.parse(match[1]);
1108
+ resolve5({
1109
+ status: response.status,
1110
+ message: response.message,
1111
+ data: response.data
1112
+ });
1113
+ } catch (error) {
1114
+ reject(new Error("Failed to parse TCP response"));
1115
+ }
1116
+ }
1117
+ });
1118
+ client.on("error", (error) => {
1119
+ if (!isResolved) {
1120
+ isResolved = true;
1121
+ globalTcpConnections.delete(this.connectionId);
1122
+ reject(error);
1123
+ }
1124
+ });
1125
+ client.on("close", () => {
1126
+ globalTcpConnections.delete(this.connectionId);
1127
+ if (!isResolved && !responseBuffer.includes("PROCESS_RESPONSE:")) {
1128
+ reject(new Error("Connection closed without valid response"));
926
1129
  }
927
1130
  });
928
1131
  });
@@ -1015,6 +1218,12 @@ var QueryEngine = class {
1015
1218
  });
1016
1219
  }
1017
1220
  async disconnect() {
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
+ }
1018
1227
  const serverInfo = globalTcpServers.get(this.connectionId);
1019
1228
  if (serverInfo && serverInfo.process && !serverInfo.process.killed) {
1020
1229
  console.log("\u{1F50C} Stopping TCP server...");
@@ -1022,7 +1231,7 @@ var QueryEngine = class {
1022
1231
  globalTcpServers.delete(this.connectionId);
1023
1232
  return {
1024
1233
  status: 200,
1025
- message: "TCP server stopped",
1234
+ message: "TCP server and connections stopped",
1026
1235
  data: null
1027
1236
  };
1028
1237
  }