@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.d.mts CHANGED
@@ -45,10 +45,14 @@ declare class QueryEngine {
45
45
  private waitForServerReady;
46
46
  private isServerResponding;
47
47
  private sleep;
48
+ private initializeConnectionPool;
48
49
  private getCachedDML;
49
50
  private startTcpServer;
50
51
  private sendTcpRequest;
51
52
  private sendTcpRequestFast;
53
+ private sendUltraFast;
54
+ private createAndPoolConnection;
55
+ private createPooledConnection;
52
56
  private sendOnExistingConnection;
53
57
  private createPersistentConnection;
54
58
  private createProcess;
package/dist/index.d.ts CHANGED
@@ -45,10 +45,14 @@ declare class QueryEngine {
45
45
  private waitForServerReady;
46
46
  private isServerResponding;
47
47
  private sleep;
48
+ private initializeConnectionPool;
48
49
  private getCachedDML;
49
50
  private startTcpServer;
50
51
  private sendTcpRequest;
51
52
  private sendTcpRequestFast;
53
+ private sendUltraFast;
54
+ private createAndPoolConnection;
55
+ private createPooledConnection;
52
56
  private sendOnExistingConnection;
53
57
  private createPersistentConnection;
54
58
  private createProcess;
package/dist/index.js CHANGED
@@ -730,9 +730,39 @@ import * as net from "net";
730
730
  import { spawn as spawn2 } from "child_process";
731
731
  var globalTcpServers = /* @__PURE__ */ new Map();
732
732
  var globalTcpConnections = /* @__PURE__ */ new Map();
733
- var queryCache = /* @__PURE__ */ new Map();
734
- var cacheSize = 0;
735
- var MAX_CACHE_SIZE = 500;
733
+ var connectionPools = /* @__PURE__ */ new Map();
734
+ var MAX_POOL_SIZE = 3;
735
+ var LRUCache = class {
736
+ cache = /* @__PURE__ */ new Map();
737
+ maxSize;
738
+ constructor(maxSize) {
739
+ this.maxSize = maxSize;
740
+ }
741
+ get(key) {
742
+ if (this.cache.has(key)) {
743
+ const value = this.cache.get(key);
744
+ this.cache.delete(key);
745
+ this.cache.set(key, value);
746
+ return value;
747
+ }
748
+ return void 0;
749
+ }
750
+ set(key, value) {
751
+ if (this.cache.has(key)) {
752
+ this.cache.delete(key);
753
+ } else if (this.cache.size >= this.maxSize) {
754
+ const firstKey = this.cache.keys().next().value;
755
+ if (firstKey !== void 0) {
756
+ this.cache.delete(firstKey);
757
+ }
758
+ }
759
+ this.cache.set(key, value);
760
+ }
761
+ size() {
762
+ return this.cache.size;
763
+ }
764
+ };
765
+ var queryCache = new LRUCache(500);
736
766
  var QueryEngine = class {
737
767
  name;
738
768
  config;
@@ -851,6 +881,7 @@ var QueryEngine = class {
851
881
  if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
852
882
  await this.startTcpServer();
853
883
  await this.waitForServerReady();
884
+ await this.initializeConnectionPool();
854
885
  }
855
886
  return this.sendTcpRequestFast(args);
856
887
  }
@@ -886,15 +917,30 @@ var QueryEngine = class {
886
917
  sleep(ms) {
887
918
  return new Promise((resolve5) => setTimeout(resolve5, ms));
888
919
  }
920
+ async initializeConnectionPool() {
921
+ console.log("\u{1F3CA} Initializing connection pool...");
922
+ if (!connectionPools.has(this.connectionId)) {
923
+ connectionPools.set(this.connectionId, []);
924
+ }
925
+ const pool = connectionPools.get(this.connectionId);
926
+ for (let i = 0; i < MAX_POOL_SIZE; i++) {
927
+ try {
928
+ const connection = await this.createPooledConnection();
929
+ pool.push(connection);
930
+ console.log(`\u2705 Pool connection ${i + 1}/${MAX_POOL_SIZE} created`);
931
+ } catch (error) {
932
+ console.error(`\u274C Failed to create pool connection ${i + 1}:`, error);
933
+ }
934
+ }
935
+ console.log(`\u{1F680} Connection pool ready with ${pool.length} connections`);
936
+ }
889
937
  getCachedDML(dmlJson) {
890
- if (queryCache.has(dmlJson)) {
891
- return queryCache.get(dmlJson);
938
+ const cached = queryCache.get(dmlJson);
939
+ if (cached) {
940
+ return cached;
892
941
  }
893
942
  const parsed = JSON.parse(dmlJson);
894
- if (cacheSize < MAX_CACHE_SIZE) {
895
- queryCache.set(dmlJson, parsed);
896
- cacheSize++;
897
- }
943
+ queryCache.set(dmlJson, parsed);
898
944
  return parsed;
899
945
  }
900
946
  async startTcpServer() {
@@ -918,7 +964,6 @@ var QueryEngine = class {
918
964
  if (output.includes("TCP Server listening on")) {
919
965
  if (!started) {
920
966
  started = true;
921
- clearTimeout(timeout);
922
967
  globalTcpServers.set(this.connectionId, {
923
968
  port: this.tcpPort,
924
969
  process: serverProcess
@@ -935,7 +980,6 @@ var QueryEngine = class {
935
980
  });
936
981
  serverProcess.on("error", (error) => {
937
982
  if (!started) {
938
- clearTimeout(timeout);
939
983
  reject(error);
940
984
  }
941
985
  });
@@ -959,7 +1003,6 @@ var QueryEngine = class {
959
1003
  if (!dmlJson) {
960
1004
  if (!isResolved) {
961
1005
  isResolved = true;
962
- clearTimeout(timeout);
963
1006
  client.destroy();
964
1007
  reject(new Error("No DML found in arguments"));
965
1008
  }
@@ -976,7 +1019,6 @@ var QueryEngine = class {
976
1019
  const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
977
1020
  if (match && !isResolved) {
978
1021
  isResolved = true;
979
- clearTimeout(timeout);
980
1022
  client.destroy();
981
1023
  try {
982
1024
  const response = JSON.parse(match[1]);
@@ -993,13 +1035,11 @@ var QueryEngine = class {
993
1035
  client.on("error", (error) => {
994
1036
  if (!isResolved) {
995
1037
  isResolved = true;
996
- clearTimeout(timeout);
997
1038
  reject(error);
998
1039
  }
999
1040
  });
1000
1041
  client.on("close", () => {
1001
1042
  if (!isResolved) {
1002
- clearTimeout(timeout);
1003
1043
  if (!responseBuffer.includes("PROCESS_RESPONSE:")) {
1004
1044
  reject(new Error("Connection closed without valid response"));
1005
1045
  }
@@ -1008,18 +1048,24 @@ var QueryEngine = class {
1008
1048
  });
1009
1049
  }
1010
1050
  async sendTcpRequestFast(args) {
1011
- const existingConnection = globalTcpConnections.get(this.connectionId);
1012
- if (existingConnection && existingConnection.readyState === "open") {
1051
+ if (!connectionPools.has(this.connectionId)) {
1052
+ return await this.createAndPoolConnection(args);
1053
+ }
1054
+ const pool = connectionPools.get(this.connectionId);
1055
+ if (pool.length > 0) {
1056
+ const connection = pool.pop();
1013
1057
  try {
1014
- return await this.sendOnExistingConnection(existingConnection, args);
1058
+ const result = await this.sendUltraFast(connection, args);
1059
+ pool.push(connection);
1060
+ return result;
1015
1061
  } catch (error) {
1016
- globalTcpConnections.delete(this.connectionId);
1017
- existingConnection.destroy();
1062
+ connection.destroy();
1063
+ return await this.createAndPoolConnection(args);
1018
1064
  }
1019
1065
  }
1020
- return await this.createPersistentConnection(args);
1066
+ return await this.createAndPoolConnection(args);
1021
1067
  }
1022
- async sendOnExistingConnection(connection, args) {
1068
+ async sendUltraFast(connection, args) {
1023
1069
  return new Promise((resolve5, reject) => {
1024
1070
  const dmlIndex = args.findIndex((arg) => arg === "--dml");
1025
1071
  const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
@@ -1029,20 +1075,96 @@ var QueryEngine = class {
1029
1075
  }
1030
1076
  let responseBuffer = "";
1031
1077
  let isResolved = false;
1032
- const timeout = setTimeout(() => {
1078
+ const onData = (data) => {
1079
+ responseBuffer += data.toString();
1080
+ const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1081
+ if (match && !isResolved) {
1082
+ isResolved = true;
1083
+ connection.off("data", onData);
1084
+ connection.off("error", onError);
1085
+ connection.off("close", onClose);
1086
+ try {
1087
+ const response = JSON.parse(match[1]);
1088
+ resolve5({
1089
+ status: response.status,
1090
+ message: response.message,
1091
+ data: response.data
1092
+ });
1093
+ } catch (error) {
1094
+ reject(new Error("Failed to parse TCP response"));
1095
+ }
1096
+ }
1097
+ };
1098
+ const onError = (error) => {
1033
1099
  if (!isResolved) {
1034
1100
  isResolved = true;
1035
- reject(new Error("TCP request timeout"));
1101
+ connection.off("data", onData);
1102
+ connection.off("error", onError);
1103
+ connection.off("close", onClose);
1104
+ reject(error);
1036
1105
  }
1037
- }, 100);
1106
+ };
1107
+ const onClose = () => {
1108
+ if (!isResolved) {
1109
+ isResolved = true;
1110
+ connection.off("data", onData);
1111
+ connection.off("error", onError);
1112
+ connection.off("close", onClose);
1113
+ connection.off("close", onClose);
1114
+ reject(new Error("Connection closed unexpectedly"));
1115
+ }
1116
+ };
1117
+ connection.on("data", onData);
1118
+ connection.on("error", onError);
1119
+ connection.on("close", onClose);
1120
+ const command = `{"action":"execute","dml":${dmlJson}}`;
1121
+ connection.write(command);
1122
+ });
1123
+ }
1124
+ async createAndPoolConnection(args) {
1125
+ const connection = await this.createPooledConnection();
1126
+ if (!connectionPools.has(this.connectionId)) {
1127
+ connectionPools.set(this.connectionId, []);
1128
+ }
1129
+ const result = await this.sendUltraFast(connection, args);
1130
+ const pool = connectionPools.get(this.connectionId);
1131
+ if (pool.length < MAX_POOL_SIZE) {
1132
+ pool.push(connection);
1133
+ } else {
1134
+ connection.destroy();
1135
+ }
1136
+ return result;
1137
+ }
1138
+ async createPooledConnection() {
1139
+ return new Promise((resolve5, reject) => {
1140
+ const client = new net.Socket();
1141
+ client.setNoDelay(true);
1142
+ client.setKeepAlive(true, 0);
1143
+ client.connect(this.tcpPort, "127.0.0.1", () => {
1144
+ resolve5(client);
1145
+ });
1146
+ client.on("error", reject);
1147
+ });
1148
+ }
1149
+ async sendOnExistingConnection(connection, args) {
1150
+ return new Promise((resolve5, reject) => {
1151
+ const dmlIndex = args.findIndex((arg) => arg === "--dml");
1152
+ const dmlJson = dmlIndex !== -1 ? args[dmlIndex + 1] : null;
1153
+ if (!dmlJson) {
1154
+ reject(new Error("No DML found in arguments"));
1155
+ return;
1156
+ }
1157
+ const dmlParsed = this.getCachedDML(dmlJson);
1158
+ let responseBuffer = "";
1159
+ let isResolved = false;
1038
1160
  const onData = (data) => {
1039
1161
  responseBuffer += data.toString();
1040
1162
  const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1041
1163
  if (match && !isResolved) {
1042
1164
  isResolved = true;
1043
- clearTimeout(timeout);
1044
1165
  connection.off("data", onData);
1045
1166
  connection.off("error", onError);
1167
+ connection.off("close", onClose);
1046
1168
  try {
1047
1169
  const response = JSON.parse(match[1]);
1048
1170
  resolve5({
@@ -1058,14 +1180,24 @@ var QueryEngine = class {
1058
1180
  const onError = (error) => {
1059
1181
  if (!isResolved) {
1060
1182
  isResolved = true;
1061
- clearTimeout(timeout);
1062
1183
  connection.off("data", onData);
1063
1184
  connection.off("error", onError);
1185
+ connection.off("close", onClose);
1064
1186
  reject(error);
1065
1187
  }
1066
1188
  };
1189
+ const onClose = () => {
1190
+ if (!isResolved) {
1191
+ isResolved = true;
1192
+ connection.off("data", onData);
1193
+ connection.off("error", onError);
1194
+ connection.off("close", onClose);
1195
+ reject(new Error("Connection closed unexpectedly"));
1196
+ }
1197
+ };
1067
1198
  connection.on("data", onData);
1068
1199
  connection.on("error", onError);
1200
+ connection.on("close", onClose);
1069
1201
  const command = {
1070
1202
  action: "execute",
1071
1203
  dml: dmlJson