@geodedb/client 1.0.0-alpha.25 → 1.0.2
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.ts +64 -2
- package/dist/index.js +249 -73
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/proto/geode.proto +3 -0
package/dist/index.js
CHANGED
|
@@ -195,7 +195,7 @@ function defaultConfig() {
|
|
|
195
195
|
connectTimeout: 3e4,
|
|
196
196
|
requestTimeout: 12e4,
|
|
197
197
|
keepAliveInterval: 1e4,
|
|
198
|
-
maxIdleTime:
|
|
198
|
+
maxIdleTime: 12e4,
|
|
199
199
|
tls: true
|
|
200
200
|
};
|
|
201
201
|
}
|
|
@@ -294,6 +294,10 @@ function parseURLDSN(dsn, cfg, scheme) {
|
|
|
294
294
|
if (url.password) {
|
|
295
295
|
cfg.password = decodeURIComponent(url.password);
|
|
296
296
|
}
|
|
297
|
+
const urlPath = url.pathname;
|
|
298
|
+
if (urlPath && urlPath !== "/") {
|
|
299
|
+
cfg.graph = urlPath.replace(/^\//, "");
|
|
300
|
+
}
|
|
297
301
|
applyQueryParams(url.searchParams, cfg);
|
|
298
302
|
return cfg;
|
|
299
303
|
}
|
|
@@ -454,6 +458,9 @@ function applyQueryParams(params, cfg) {
|
|
|
454
458
|
}
|
|
455
459
|
break;
|
|
456
460
|
}
|
|
461
|
+
case "graph":
|
|
462
|
+
cfg.graph = value;
|
|
463
|
+
break;
|
|
457
464
|
}
|
|
458
465
|
}
|
|
459
466
|
if (cfg.tlsCert && !cfg.tlsKey || !cfg.tlsCert && cfg.tlsKey) {
|
|
@@ -1938,17 +1945,17 @@ function decodeLengthPrefix(data) {
|
|
|
1938
1945
|
}
|
|
1939
1946
|
return data.readUInt32BE(0);
|
|
1940
1947
|
}
|
|
1941
|
-
function buildHelloRequest(username, password, clientName, clientVersion, conformance, tenantId) {
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
}
|
|
1948
|
+
function buildHelloRequest(username, password, clientName, clientVersion, conformance, tenantId, graph) {
|
|
1949
|
+
const helloReq = {
|
|
1950
|
+
username,
|
|
1951
|
+
password,
|
|
1952
|
+
clientName,
|
|
1953
|
+
clientVersion,
|
|
1954
|
+
wantedConformance: conformance,
|
|
1955
|
+
...tenantId ? { tenantId } : {},
|
|
1956
|
+
...graph ? { graph } : {}
|
|
1951
1957
|
};
|
|
1958
|
+
return { hello: helloReq };
|
|
1952
1959
|
}
|
|
1953
1960
|
function buildExecuteRequest(sessionId, query2, params) {
|
|
1954
1961
|
const protoParams = [];
|
|
@@ -2141,7 +2148,8 @@ var init_grpc_transport = __esm({
|
|
|
2141
2148
|
rootCerts = Buffer.from(cfg.tlsCACert);
|
|
2142
2149
|
}
|
|
2143
2150
|
credentials2 = grpc.credentials.createSsl(rootCerts, null, null, {
|
|
2144
|
-
checkServerIdentity: () => void 0
|
|
2151
|
+
checkServerIdentity: () => void 0,
|
|
2152
|
+
rejectUnauthorized: false
|
|
2145
2153
|
});
|
|
2146
2154
|
} else {
|
|
2147
2155
|
const sslOptions = await buildGrpcSslOptions(cfg);
|
|
@@ -2159,6 +2167,11 @@ var init_grpc_transport = __esm({
|
|
|
2159
2167
|
"grpc.keepalive_timeout_ms": 5e3,
|
|
2160
2168
|
"grpc.keepalive_permit_without_calls": 1
|
|
2161
2169
|
};
|
|
2170
|
+
if (cfg.insecureSkipVerify) {
|
|
2171
|
+
const authority = cfg.serverName ?? "localhost";
|
|
2172
|
+
options["grpc.ssl_target_name_override"] = authority;
|
|
2173
|
+
options["grpc.default_authority"] = authority;
|
|
2174
|
+
}
|
|
2162
2175
|
transport._client = new protoDescriptor.geode.GeodeService(address, credentials2, options);
|
|
2163
2176
|
return transport;
|
|
2164
2177
|
} catch (e) {
|
|
@@ -2401,8 +2414,14 @@ var init_grpc_transport = __esm({
|
|
|
2401
2414
|
this.resetStreamTimeout(stream, reject, () => {
|
|
2402
2415
|
resolved = true;
|
|
2403
2416
|
});
|
|
2404
|
-
|
|
2405
|
-
|
|
2417
|
+
const execResponse = response;
|
|
2418
|
+
this.enqueueResponse({ execute: execResponse });
|
|
2419
|
+
if (execResponse.payload === "page" && execResponse.page?.final || execResponse.payload === "error" || execResponse.payload === "heartbeat") {
|
|
2420
|
+
this.clearStreamTimeout();
|
|
2421
|
+
this._activeStream = null;
|
|
2422
|
+
this._streamComplete = true;
|
|
2423
|
+
}
|
|
2424
|
+
if (this._activeStream === stream && this._pendingResponses.length >= this._backpressureThreshold) {
|
|
2406
2425
|
this._streamPaused = true;
|
|
2407
2426
|
stream.pause();
|
|
2408
2427
|
}
|
|
@@ -2413,8 +2432,10 @@ var init_grpc_transport = __esm({
|
|
|
2413
2432
|
});
|
|
2414
2433
|
stream.on("end", () => {
|
|
2415
2434
|
this.clearStreamTimeout();
|
|
2416
|
-
this._activeStream
|
|
2417
|
-
|
|
2435
|
+
if (this._activeStream === stream) {
|
|
2436
|
+
this._activeStream = null;
|
|
2437
|
+
this._streamComplete = true;
|
|
2438
|
+
}
|
|
2418
2439
|
if (!resolved) {
|
|
2419
2440
|
resolved = true;
|
|
2420
2441
|
resolve2();
|
|
@@ -2422,17 +2443,21 @@ var init_grpc_transport = __esm({
|
|
|
2422
2443
|
});
|
|
2423
2444
|
stream.on("error", (error) => {
|
|
2424
2445
|
this.clearStreamTimeout();
|
|
2425
|
-
this._activeStream
|
|
2426
|
-
|
|
2446
|
+
if (this._activeStream === stream) {
|
|
2447
|
+
this._activeStream = null;
|
|
2448
|
+
this._streamComplete = true;
|
|
2449
|
+
}
|
|
2427
2450
|
const transportError = new TransportError({
|
|
2428
2451
|
operation: "execute",
|
|
2429
2452
|
address: this._address,
|
|
2430
2453
|
cause: new Error(`gRPC error ${error.code}: ${error.message}`)
|
|
2431
2454
|
});
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
p
|
|
2455
|
+
if (this._activeStream === null || this._streamComplete) {
|
|
2456
|
+
const pendingReads = this._pendingProtoReads;
|
|
2457
|
+
this._pendingProtoReads = [];
|
|
2458
|
+
for (const p of pendingReads) {
|
|
2459
|
+
p.reject(transportError);
|
|
2460
|
+
}
|
|
2436
2461
|
}
|
|
2437
2462
|
if (!resolved) {
|
|
2438
2463
|
resolved = true;
|
|
@@ -2461,8 +2486,10 @@ var init_grpc_transport = __esm({
|
|
|
2461
2486
|
if (this._streamTimeoutMs <= 0) return;
|
|
2462
2487
|
this._streamTimeoutTimer = setTimeout(() => {
|
|
2463
2488
|
this._streamTimeoutTimer = null;
|
|
2464
|
-
this._activeStream
|
|
2465
|
-
|
|
2489
|
+
if (this._activeStream === stream) {
|
|
2490
|
+
this._activeStream = null;
|
|
2491
|
+
this._streamComplete = true;
|
|
2492
|
+
}
|
|
2466
2493
|
stream.cancel();
|
|
2467
2494
|
const timeoutError = new TransportError({
|
|
2468
2495
|
operation: "execute",
|
|
@@ -2471,10 +2498,12 @@ var init_grpc_transport = __esm({
|
|
|
2471
2498
|
`gRPC stream timed out: no data received within ${this._streamTimeoutMs}ms`
|
|
2472
2499
|
)
|
|
2473
2500
|
});
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
p
|
|
2501
|
+
if (this._activeStream === null || this._streamComplete) {
|
|
2502
|
+
const pendingReads = this._pendingProtoReads;
|
|
2503
|
+
this._pendingProtoReads = [];
|
|
2504
|
+
for (const p of pendingReads) {
|
|
2505
|
+
p.reject(timeoutError);
|
|
2506
|
+
}
|
|
2478
2507
|
}
|
|
2479
2508
|
markResolved();
|
|
2480
2509
|
reject(timeoutError);
|
|
@@ -2589,6 +2618,7 @@ var init_transport = __esm({
|
|
|
2589
2618
|
_maxMessageSize;
|
|
2590
2619
|
_maxBufferBytes;
|
|
2591
2620
|
_pendingProtoReads = [];
|
|
2621
|
+
_pendingResponses = [];
|
|
2592
2622
|
constructor(address, maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE, maxBufferBytes = DEFAULT_MAX_BUFFER_BYTES) {
|
|
2593
2623
|
super(address);
|
|
2594
2624
|
this._maxMessageSize = maxMessageSize;
|
|
@@ -2650,7 +2680,7 @@ var init_transport = __esm({
|
|
|
2650
2680
|
{
|
|
2651
2681
|
host,
|
|
2652
2682
|
port,
|
|
2653
|
-
serverName: cfg.serverName ?? host,
|
|
2683
|
+
serverName: cfg.serverName ?? (cfg.insecureSkipVerify ? "localhost" : host),
|
|
2654
2684
|
crypto: cryptoOps,
|
|
2655
2685
|
config
|
|
2656
2686
|
},
|
|
@@ -2770,6 +2800,8 @@ var init_transport = __esm({
|
|
|
2770
2800
|
const pending = this._pendingProtoReads.shift();
|
|
2771
2801
|
if (pending) {
|
|
2772
2802
|
pending.resolve(msg);
|
|
2803
|
+
} else {
|
|
2804
|
+
this._pendingResponses.push(msg);
|
|
2773
2805
|
}
|
|
2774
2806
|
} catch (err) {
|
|
2775
2807
|
const pending = this._pendingProtoReads.shift();
|
|
@@ -2813,8 +2845,11 @@ var init_transport = __esm({
|
|
|
2813
2845
|
try {
|
|
2814
2846
|
const stream = this._stream;
|
|
2815
2847
|
const writer = stream.writable.getWriter();
|
|
2816
|
-
|
|
2817
|
-
|
|
2848
|
+
try {
|
|
2849
|
+
await writer.write(new Uint8Array(data));
|
|
2850
|
+
} finally {
|
|
2851
|
+
writer.releaseLock();
|
|
2852
|
+
}
|
|
2818
2853
|
} catch (e) {
|
|
2819
2854
|
throw new TransportError({
|
|
2820
2855
|
operation: "sendProto",
|
|
@@ -2831,6 +2866,10 @@ var init_transport = __esm({
|
|
|
2831
2866
|
if (signal?.aborted) {
|
|
2832
2867
|
throw new TransportError({ operation: "receiveProto", cause: new Error("Aborted") });
|
|
2833
2868
|
}
|
|
2869
|
+
const queued = this._pendingResponses.shift();
|
|
2870
|
+
if (queued) {
|
|
2871
|
+
return queued;
|
|
2872
|
+
}
|
|
2834
2873
|
return new Promise((resolve2, reject) => {
|
|
2835
2874
|
let onAbort = null;
|
|
2836
2875
|
const pendingRead = {
|
|
@@ -2867,6 +2906,7 @@ var init_transport = __esm({
|
|
|
2867
2906
|
pending.reject(ErrClosed());
|
|
2868
2907
|
}
|
|
2869
2908
|
this._pendingProtoReads = [];
|
|
2909
|
+
this._pendingResponses = [];
|
|
2870
2910
|
this._chunks = [];
|
|
2871
2911
|
this._totalLength = 0;
|
|
2872
2912
|
if (this._client) {
|
|
@@ -4227,6 +4267,10 @@ var Transaction = class {
|
|
|
4227
4267
|
}
|
|
4228
4268
|
/**
|
|
4229
4269
|
* Create a savepoint.
|
|
4270
|
+
*
|
|
4271
|
+
* Savepoints are only supported over the QUIC transport. Over gRPC this
|
|
4272
|
+
* rejects with a {@link DriverError} (statusClass `58000`) directing callers
|
|
4273
|
+
* to use `quic://`.
|
|
4230
4274
|
*/
|
|
4231
4275
|
async savepoint(name, signal) {
|
|
4232
4276
|
this.checkDone();
|
|
@@ -4235,6 +4279,10 @@ var Transaction = class {
|
|
|
4235
4279
|
}
|
|
4236
4280
|
/**
|
|
4237
4281
|
* Rollback to a savepoint.
|
|
4282
|
+
*
|
|
4283
|
+
* Savepoints are only supported over the QUIC transport. Over gRPC this
|
|
4284
|
+
* rejects with a {@link DriverError} (statusClass `58000`) directing callers
|
|
4285
|
+
* to use `quic://`.
|
|
4238
4286
|
*/
|
|
4239
4287
|
async rollbackTo(name, signal) {
|
|
4240
4288
|
this.checkDone();
|
|
@@ -4655,7 +4703,10 @@ var Connection = class _Connection {
|
|
|
4655
4703
|
this._config.password ?? "",
|
|
4656
4704
|
this._config.helloName,
|
|
4657
4705
|
this._config.helloVersion,
|
|
4658
|
-
this._config.conformance
|
|
4706
|
+
this._config.conformance,
|
|
4707
|
+
void 0,
|
|
4708
|
+
// tenantId
|
|
4709
|
+
this._config.graph
|
|
4659
4710
|
);
|
|
4660
4711
|
await this._sendWithTimeout(msg);
|
|
4661
4712
|
const response = await this._receiveWithTimeout();
|
|
@@ -4723,9 +4774,8 @@ var Connection = class _Connection {
|
|
|
4723
4774
|
let isFinal = false;
|
|
4724
4775
|
let isOrdered = false;
|
|
4725
4776
|
let orderKeys = [];
|
|
4726
|
-
const
|
|
4727
|
-
if (
|
|
4728
|
-
const inlineExec = inlineResponse.execute;
|
|
4777
|
+
const inlineExec = await this._readInlineExecute(signal);
|
|
4778
|
+
if (inlineExec) {
|
|
4729
4779
|
if (isErrorResponse(inlineExec)) {
|
|
4730
4780
|
this._state = this._inTransaction ? "in_transaction" : "idle";
|
|
4731
4781
|
throw protoErrorToDriverError(inlineExec, inlineExec.status?.statusClass);
|
|
@@ -4744,9 +4794,12 @@ var Connection = class _Connection {
|
|
|
4744
4794
|
validatePageSize(pageSize);
|
|
4745
4795
|
const pullMsg = buildPullRequest(this._requestId, pageSize, this._sessionId);
|
|
4746
4796
|
await this._sendWithTimeout(pullMsg, signal);
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4797
|
+
while (true) {
|
|
4798
|
+
const pullResponse = await this._receiveWithTimeout(signal);
|
|
4799
|
+
const pullExec = pullResponse.pull?.response ?? pullResponse.execute;
|
|
4800
|
+
if (!pullExec) {
|
|
4801
|
+
break;
|
|
4802
|
+
}
|
|
4750
4803
|
if (isErrorResponse(pullExec)) {
|
|
4751
4804
|
this._state = this._inTransaction ? "in_transaction" : "idle";
|
|
4752
4805
|
throw protoErrorToDriverError(pullExec, pullExec.status?.statusClass);
|
|
@@ -4757,6 +4810,10 @@ var Connection = class _Connection {
|
|
|
4757
4810
|
isFinal = page.final;
|
|
4758
4811
|
isOrdered = page.ordered;
|
|
4759
4812
|
orderKeys = page.orderKeys;
|
|
4813
|
+
break;
|
|
4814
|
+
}
|
|
4815
|
+
if (pullExec.heartbeat) {
|
|
4816
|
+
break;
|
|
4760
4817
|
}
|
|
4761
4818
|
}
|
|
4762
4819
|
}
|
|
@@ -4810,15 +4867,12 @@ var Connection = class _Connection {
|
|
|
4810
4867
|
}
|
|
4811
4868
|
if (isSchemaResponse(execResp)) {
|
|
4812
4869
|
this._columns = execResp.schema.columns;
|
|
4813
|
-
const
|
|
4814
|
-
if (
|
|
4815
|
-
if (isErrorResponse(
|
|
4816
|
-
throw protoErrorToDriverError(
|
|
4817
|
-
inlineResponse.execute,
|
|
4818
|
-
inlineResponse.execute.status?.statusClass
|
|
4819
|
-
);
|
|
4870
|
+
const inlineExec = await this._readInlineExecute(signal);
|
|
4871
|
+
if (inlineExec) {
|
|
4872
|
+
if (isErrorResponse(inlineExec)) {
|
|
4873
|
+
throw protoErrorToDriverError(inlineExec, inlineExec.status?.statusClass);
|
|
4820
4874
|
}
|
|
4821
|
-
if (isDataPageResponse(
|
|
4875
|
+
if (isDataPageResponse(inlineExec) && !inlineExec.page.final) {
|
|
4822
4876
|
await this._drainRemainingPages(signal);
|
|
4823
4877
|
}
|
|
4824
4878
|
}
|
|
@@ -4833,22 +4887,26 @@ var Connection = class _Connection {
|
|
|
4833
4887
|
this._requestId++;
|
|
4834
4888
|
const pullMsg = buildPullRequest(this._requestId, pageSize, this._sessionId);
|
|
4835
4889
|
await this._sendWithTimeout(pullMsg, signal);
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4890
|
+
while (true) {
|
|
4891
|
+
const response = await this._receiveWithTimeout(signal);
|
|
4892
|
+
const execResp = response.pull?.response ?? response.execute;
|
|
4893
|
+
if (!execResp) {
|
|
4894
|
+
return { rows: [], final: true };
|
|
4895
|
+
}
|
|
4896
|
+
if (isErrorResponse(execResp)) {
|
|
4897
|
+
throw protoErrorToDriverError(execResp, execResp.status?.statusClass);
|
|
4898
|
+
}
|
|
4899
|
+
if (isDataPageResponse(execResp)) {
|
|
4900
|
+
const page = execResp.page;
|
|
4901
|
+
return {
|
|
4902
|
+
rows: dataPageToRows(page, this._columns),
|
|
4903
|
+
final: page.final
|
|
4904
|
+
};
|
|
4905
|
+
}
|
|
4906
|
+
if (execResp.heartbeat) {
|
|
4907
|
+
return { rows: [], final: true };
|
|
4908
|
+
}
|
|
4850
4909
|
}
|
|
4851
|
-
return { rows: [], final: true };
|
|
4852
4910
|
}
|
|
4853
4911
|
/** Try to receive an inline response with short timeout. */
|
|
4854
4912
|
async _tryReceiveInline(signal) {
|
|
@@ -4868,6 +4926,22 @@ var Connection = class _Connection {
|
|
|
4868
4926
|
cleanup();
|
|
4869
4927
|
}
|
|
4870
4928
|
}
|
|
4929
|
+
/** Read inline execute responses until a page, error, heartbeat, or timeout arrives. */
|
|
4930
|
+
async _readInlineExecute(signal) {
|
|
4931
|
+
while (true) {
|
|
4932
|
+
const inlineResponse = await this._tryReceiveInline(signal);
|
|
4933
|
+
const inlineExec = inlineResponse?.execute;
|
|
4934
|
+
if (!inlineExec) {
|
|
4935
|
+
return null;
|
|
4936
|
+
}
|
|
4937
|
+
if (isErrorResponse(inlineExec) || isDataPageResponse(inlineExec)) {
|
|
4938
|
+
return inlineExec;
|
|
4939
|
+
}
|
|
4940
|
+
if (inlineExec.heartbeat) {
|
|
4941
|
+
return null;
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4871
4945
|
/** Drain remaining data pages until final=true to prevent query corruption (QUAL-T7). */
|
|
4872
4946
|
async _drainRemainingPages(signal) {
|
|
4873
4947
|
let done = false;
|
|
@@ -4886,7 +4960,7 @@ var Connection = class _Connection {
|
|
|
4886
4960
|
}
|
|
4887
4961
|
if (isDataPageResponse(pullExec)) {
|
|
4888
4962
|
done = pullExec.page.final;
|
|
4889
|
-
} else {
|
|
4963
|
+
} else if (pullExec.heartbeat) {
|
|
4890
4964
|
done = true;
|
|
4891
4965
|
}
|
|
4892
4966
|
}
|
|
@@ -5080,6 +5154,9 @@ var Connection = class _Connection {
|
|
|
5080
5154
|
const { signal: timeoutSignal, cleanup } = this._withRequestTimeout(signal);
|
|
5081
5155
|
try {
|
|
5082
5156
|
await this._transport.sendProto(msg, timeoutSignal);
|
|
5157
|
+
} catch (e) {
|
|
5158
|
+
await this._closeOnTransportError(e);
|
|
5159
|
+
throw e;
|
|
5083
5160
|
} finally {
|
|
5084
5161
|
cleanup();
|
|
5085
5162
|
}
|
|
@@ -5089,6 +5166,9 @@ var Connection = class _Connection {
|
|
|
5089
5166
|
const { signal: timeoutSignal, cleanup } = this._withRequestTimeout(signal);
|
|
5090
5167
|
try {
|
|
5091
5168
|
return await this._transport.receiveProto(timeoutSignal);
|
|
5169
|
+
} catch (e) {
|
|
5170
|
+
await this._closeOnTransportError(e);
|
|
5171
|
+
throw e;
|
|
5092
5172
|
} finally {
|
|
5093
5173
|
cleanup();
|
|
5094
5174
|
}
|
|
@@ -5097,6 +5177,24 @@ var Connection = class _Connection {
|
|
|
5097
5177
|
_withRequestTimeout(signal) {
|
|
5098
5178
|
return withAbortTimeout(signal, this._config.requestTimeout);
|
|
5099
5179
|
}
|
|
5180
|
+
async _closeOnTransportError(err) {
|
|
5181
|
+
if (!(err instanceof TransportError) || err.cause?.message === "Aborted") {
|
|
5182
|
+
return;
|
|
5183
|
+
}
|
|
5184
|
+
if (this._state === "closed") {
|
|
5185
|
+
return;
|
|
5186
|
+
}
|
|
5187
|
+
this._state = "closed";
|
|
5188
|
+
this._inTransaction = false;
|
|
5189
|
+
if (this._activeResult) {
|
|
5190
|
+
this._activeResult._close();
|
|
5191
|
+
this._activeResult = null;
|
|
5192
|
+
}
|
|
5193
|
+
try {
|
|
5194
|
+
await this._transport.close();
|
|
5195
|
+
} catch {
|
|
5196
|
+
}
|
|
5197
|
+
}
|
|
5100
5198
|
};
|
|
5101
5199
|
|
|
5102
5200
|
// src/pool.ts
|
|
@@ -5165,6 +5263,7 @@ var RateLimiter = class {
|
|
|
5165
5263
|
var ConnectionPool = class _ConnectionPool {
|
|
5166
5264
|
_config;
|
|
5167
5265
|
_connections = [];
|
|
5266
|
+
_pendingConnections = 0;
|
|
5168
5267
|
_waitQueue = [];
|
|
5169
5268
|
_closed = false;
|
|
5170
5269
|
_maintenanceInterval;
|
|
@@ -5317,6 +5416,12 @@ var ConnectionPool = class _ConnectionPool {
|
|
|
5317
5416
|
}
|
|
5318
5417
|
} catch {
|
|
5319
5418
|
await this.removeConnection(pooledConn);
|
|
5419
|
+
await this.fulfillWaiters();
|
|
5420
|
+
return;
|
|
5421
|
+
}
|
|
5422
|
+
if (conn.isClosed) {
|
|
5423
|
+
await this.removeConnection(pooledConn);
|
|
5424
|
+
await this.fulfillWaiters();
|
|
5320
5425
|
return;
|
|
5321
5426
|
}
|
|
5322
5427
|
pooledConn.inUse = false;
|
|
@@ -5324,6 +5429,7 @@ var ConnectionPool = class _ConnectionPool {
|
|
|
5324
5429
|
const waiter = this._waitQueue.shift();
|
|
5325
5430
|
if (waiter) {
|
|
5326
5431
|
pooledConn.inUse = true;
|
|
5432
|
+
pooledConn.lastUsedAt = Date.now();
|
|
5327
5433
|
waiter.resolve(conn);
|
|
5328
5434
|
}
|
|
5329
5435
|
}
|
|
@@ -5397,18 +5503,19 @@ var ConnectionPool = class _ConnectionPool {
|
|
|
5397
5503
|
* Add a new connection to the pool with rate limiting and exponential backoff.
|
|
5398
5504
|
*/
|
|
5399
5505
|
async addConnection() {
|
|
5400
|
-
if (this._connections.length >= this._maxConnections) {
|
|
5506
|
+
if (this._connections.length + this._pendingConnections >= this._maxConnections) {
|
|
5401
5507
|
return;
|
|
5402
5508
|
}
|
|
5403
|
-
|
|
5404
|
-
throw new TransportError({
|
|
5405
|
-
operation: "connect",
|
|
5406
|
-
cause: new Error("Connection rate limit exceeded")
|
|
5407
|
-
});
|
|
5408
|
-
}
|
|
5409
|
-
await this._rateLimiter.waitForBackoff();
|
|
5410
|
-
this._rateLimiter.recordAttempt();
|
|
5509
|
+
this._pendingConnections++;
|
|
5411
5510
|
try {
|
|
5511
|
+
if (!this._rateLimiter.isAllowed()) {
|
|
5512
|
+
throw new TransportError({
|
|
5513
|
+
operation: "connect",
|
|
5514
|
+
cause: new Error("Connection rate limit exceeded")
|
|
5515
|
+
});
|
|
5516
|
+
}
|
|
5517
|
+
await this._rateLimiter.waitForBackoff();
|
|
5518
|
+
this._rateLimiter.recordAttempt();
|
|
5412
5519
|
const conn = await Connection.connect(this._config);
|
|
5413
5520
|
this._rateLimiter.recordSuccess();
|
|
5414
5521
|
this._connections.push({
|
|
@@ -5420,6 +5527,8 @@ var ConnectionPool = class _ConnectionPool {
|
|
|
5420
5527
|
} catch (e) {
|
|
5421
5528
|
this._rateLimiter.recordFailure();
|
|
5422
5529
|
throw e;
|
|
5530
|
+
} finally {
|
|
5531
|
+
this._pendingConnections--;
|
|
5423
5532
|
}
|
|
5424
5533
|
}
|
|
5425
5534
|
/**
|
|
@@ -5435,6 +5544,26 @@ var ConnectionPool = class _ConnectionPool {
|
|
|
5435
5544
|
} catch {
|
|
5436
5545
|
}
|
|
5437
5546
|
}
|
|
5547
|
+
async fulfillWaiters() {
|
|
5548
|
+
while (this._waitQueue.length > 0) {
|
|
5549
|
+
const available = this._connections.find((c) => !c.inUse && !c.connection.isClosed);
|
|
5550
|
+
if (available) {
|
|
5551
|
+
available.inUse = true;
|
|
5552
|
+
available.lastUsedAt = Date.now();
|
|
5553
|
+
const waiter = this._waitQueue.shift();
|
|
5554
|
+
waiter?.resolve(available.connection);
|
|
5555
|
+
continue;
|
|
5556
|
+
}
|
|
5557
|
+
if (this._connections.length + this._pendingConnections >= this._maxConnections) {
|
|
5558
|
+
return;
|
|
5559
|
+
}
|
|
5560
|
+
try {
|
|
5561
|
+
await this.addConnection();
|
|
5562
|
+
} catch {
|
|
5563
|
+
return;
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5438
5567
|
/**
|
|
5439
5568
|
* Perform pool maintenance.
|
|
5440
5569
|
*/
|
|
@@ -5458,7 +5587,7 @@ var ConnectionPool = class _ConnectionPool {
|
|
|
5458
5587
|
});
|
|
5459
5588
|
}
|
|
5460
5589
|
const available = this._connections.filter((c) => !c.connection.isClosed).length;
|
|
5461
|
-
const toCreate = this._minConnections - available;
|
|
5590
|
+
const toCreate = this._minConnections - (available + this._pendingConnections);
|
|
5462
5591
|
for (let i = 0; i < toCreate; i++) {
|
|
5463
5592
|
this.addConnection().catch(() => {
|
|
5464
5593
|
});
|
|
@@ -5947,6 +6076,53 @@ async function createClientWithConfig(config, options) {
|
|
|
5947
6076
|
init_config();
|
|
5948
6077
|
await init_types();
|
|
5949
6078
|
init_errors();
|
|
6079
|
+
|
|
6080
|
+
// src/retry.ts
|
|
6081
|
+
init_errors();
|
|
6082
|
+
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
6083
|
+
var DEFAULT_INITIAL_BACKOFF_MS = 1e3;
|
|
6084
|
+
var DEFAULT_MAX_BACKOFF_MS = 3e4;
|
|
6085
|
+
var DEFAULT_MULTIPLIER = 2;
|
|
6086
|
+
function defaultRetryPolicy() {
|
|
6087
|
+
return {
|
|
6088
|
+
maxAttempts: DEFAULT_MAX_ATTEMPTS,
|
|
6089
|
+
initialBackoffMs: DEFAULT_INITIAL_BACKOFF_MS,
|
|
6090
|
+
maxBackoffMs: DEFAULT_MAX_BACKOFF_MS,
|
|
6091
|
+
multiplier: DEFAULT_MULTIPLIER
|
|
6092
|
+
};
|
|
6093
|
+
}
|
|
6094
|
+
function backoffMs(policy, attempt) {
|
|
6095
|
+
const a = attempt < 1 ? 1 : attempt;
|
|
6096
|
+
const d = policy.initialBackoffMs * Math.pow(policy.multiplier, a - 1);
|
|
6097
|
+
return d > policy.maxBackoffMs ? policy.maxBackoffMs : d;
|
|
6098
|
+
}
|
|
6099
|
+
function sleep(ms) {
|
|
6100
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
6101
|
+
}
|
|
6102
|
+
async function withRetry(fn, policy = defaultRetryPolicy()) {
|
|
6103
|
+
const maxAttempts = policy.maxAttempts < 1 ? 1 : policy.maxAttempts;
|
|
6104
|
+
let lastErr;
|
|
6105
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6106
|
+
try {
|
|
6107
|
+
return await fn();
|
|
6108
|
+
} catch (e) {
|
|
6109
|
+
lastErr = e;
|
|
6110
|
+
if (!isRetryableError(e)) {
|
|
6111
|
+
throw e;
|
|
6112
|
+
}
|
|
6113
|
+
if (attempt === maxAttempts) {
|
|
6114
|
+
break;
|
|
6115
|
+
}
|
|
6116
|
+
const delay = backoffMs(policy, attempt);
|
|
6117
|
+
if (delay > 0) {
|
|
6118
|
+
await sleep(delay);
|
|
6119
|
+
}
|
|
6120
|
+
}
|
|
6121
|
+
}
|
|
6122
|
+
throw lastErr;
|
|
6123
|
+
}
|
|
6124
|
+
|
|
6125
|
+
// src/index.ts
|
|
5950
6126
|
await init_transport();
|
|
5951
6127
|
await init_grpc_transport();
|
|
5952
6128
|
init_validate();
|
|
@@ -6689,6 +6865,6 @@ await init_batch();
|
|
|
6689
6865
|
init_auth();
|
|
6690
6866
|
await init_proto();
|
|
6691
6867
|
|
|
6692
|
-
export { AuthClient, BaseTransport, ConfigError, Connection, ConnectionPool, DEFAULT_CONFORMANCE, DEFAULT_GRPC_PORT, DEFAULT_HELLO_NAME, DEFAULT_HELLO_VERSION, DEFAULT_PAGE_SIZE, DEFAULT_PORT, DriverError, ERR_BAD_CONN_MESSAGE, ERR_CLOSED_MESSAGE, ERR_NO_TX_MESSAGE, ERR_QUERY_IN_PROGRESS_MESSAGE, ERR_ROWS_CLOSED_MESSAGE, ERR_TX_DONE_MESSAGE, ERR_TX_IN_PROGRESS_MESSAGE, EdgePatternBuilder, ErrBadConn, ErrClosed, ErrNoTx, ErrQueryInProgress, ErrRowsClosed, ErrTxDone, ErrTxInProgress, GQLValue, GeodeClient, GrpcTransport, MAX_PAGE_SIZE, MAX_QUERY_LENGTH, MockTransport, NodePatternBuilder, PatternBuilder, PredicateBuilder, PreparedStatement, QueryBuilder, QueryResult, QueryResultIterator, QuicTransport, QuicTransport as QuicheTransport, SUPPORTED_SCHEMES, SecurityError, StateError, StatusClass, Transaction, TransportError, batch, batchAll, batchFirst, batchMap, batchParallel, buildBeginRequest, buildCommitRequest, buildExecuteRequest, buildHelloRequest, buildPingRequest, buildPullRequest, buildRollbackRequest, buildRollbackToRequest, buildSavepointRequest, buildTLSConfig, cloneConfig, createAuthClient, createClient, createClientWithConfig, createTransport, decodeLengthPrefix, decodeQuicServerMessage, defaultConfig, edge, encodeQuicClientMessage, encodeWithLengthPrefix, ensureProtoInitialized, explain, extractParameters, formatPlan, formatProfile, fromJSON, getAddress, getProtoPath, initProtoSync, isDriverError, isGeodeError, isRetryableError, isSentinelError, jsToProtoValue, node, parseDSN, parseGQLType, parseRow, pattern, predicate, prepare, profile, protoValueToJS, query, redactConfig, redactDSN, rowToObject, rowToRecord, sanitizeForLog, validateConfig, validateHostname, validatePageSize, validateParamName, validateParamValue, validatePort, validateQuery, validateSavepointName, withTransaction };
|
|
6868
|
+
export { AuthClient, BaseTransport, ConfigError, Connection, ConnectionPool, DEFAULT_CONFORMANCE, DEFAULT_GRPC_PORT, DEFAULT_HELLO_NAME, DEFAULT_HELLO_VERSION, DEFAULT_PAGE_SIZE, DEFAULT_PORT, DriverError, ERR_BAD_CONN_MESSAGE, ERR_CLOSED_MESSAGE, ERR_NO_TX_MESSAGE, ERR_QUERY_IN_PROGRESS_MESSAGE, ERR_ROWS_CLOSED_MESSAGE, ERR_TX_DONE_MESSAGE, ERR_TX_IN_PROGRESS_MESSAGE, EdgePatternBuilder, ErrBadConn, ErrClosed, ErrNoTx, ErrQueryInProgress, ErrRowsClosed, ErrTxDone, ErrTxInProgress, GQLValue, GeodeClient, GrpcTransport, MAX_PAGE_SIZE, MAX_QUERY_LENGTH, MockTransport, NodePatternBuilder, PatternBuilder, PredicateBuilder, PreparedStatement, QueryBuilder, QueryResult, QueryResultIterator, QuicTransport, QuicTransport as QuicheTransport, SUPPORTED_SCHEMES, SecurityError, StateError, StatusClass, Transaction, TransportError, batch, batchAll, batchFirst, batchMap, batchParallel, buildBeginRequest, buildCommitRequest, buildExecuteRequest, buildHelloRequest, buildPingRequest, buildPullRequest, buildRollbackRequest, buildRollbackToRequest, buildSavepointRequest, buildTLSConfig, cloneConfig, createAuthClient, createClient, createClientWithConfig, createTransport, decodeLengthPrefix, decodeQuicServerMessage, defaultConfig, defaultRetryPolicy, edge, encodeQuicClientMessage, encodeWithLengthPrefix, ensureProtoInitialized, explain, extractParameters, formatPlan, formatProfile, fromJSON, getAddress, getProtoPath, initProtoSync, isDriverError, isGeodeError, isRetryableError, isSentinelError, jsToProtoValue, node, parseDSN, parseGQLType, parseRow, pattern, predicate, prepare, profile, protoValueToJS, query, redactConfig, redactDSN, rowToObject, rowToRecord, sanitizeForLog, validateConfig, validateHostname, validatePageSize, validateParamName, validateParamValue, validatePort, validateQuery, validateSavepointName, withRetry, withTransaction };
|
|
6693
6869
|
//# sourceMappingURL=index.js.map
|
|
6694
6870
|
//# sourceMappingURL=index.js.map
|