Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions lib/DBSQLClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,24 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I
this.config.preserveBigNumericPrecision = options.preserveBigNumericPrecision;
}

// Retry-policy knobs. These live in ClientConfig (consumed by the Thrift
// HttpRetryPolicy and forwarded to the kernel on the SEA path), so copying
// them here makes them configurable from connect() on BOTH backends. A
// per-key narrowed copy (not a spread) keeps the structural type system
// honest, matching the metricView / precision / telemetry knobs above.
if (options.retryMaxAttempts !== undefined) {
this.config.retryMaxAttempts = options.retryMaxAttempts;
}
if (options.retriesTimeout !== undefined) {
this.config.retriesTimeout = options.retriesTimeout;
}
if (options.retryDelayMin !== undefined) {
this.config.retryDelayMin = options.retryDelayMin;
}
if (options.retryDelayMax !== undefined) {
this.config.retryDelayMax = options.retryDelayMax;
}

// Override telemetry config if provided in options. Per-key narrowed copy
// preserves the structural type system: `ConnectionOptions` and
// `ClientConfig` declare identical types for these knobs, so a user
Expand Down
23 changes: 23 additions & 0 deletions lib/contracts/IDBSQLClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@ export type ConnectionOptions = {
proxy?: ProxyOptions;
enableMetricViewMetadata?: boolean;

/**
* Retry-policy knobs governing how the driver retries retryable requests.
* They apply to **both** backends: the Thrift `HttpRetryPolicy` reads them
* directly, and on the kernel (SEA) path they are forwarded to the kernel
* (which owns the retry loop) via `buildKernelRetryOptions`. An unset field
* keeps the driver default shown below.
*
* • `retryMaxAttempts` — maximum TOTAL number of attempts (the initial
* request plus any retries). Default 5. `0` or `1` both mean a single
* attempt with no retry. Both backends honour the same total-attempt
* semantics (the kernel converts it to its after-initial retry count).
* • `retriesTimeout` — maximum total wallclock spent retrying, in
* milliseconds. Default 900000 (15 minutes).
* • `retryDelayMin` — minimum backoff between attempts, in milliseconds.
* Default 1000.
* • `retryDelayMax` — maximum backoff between attempts, in milliseconds.
* Default 60000.
*/
retryMaxAttempts?: number;
retriesTimeout?: number;
retryDelayMin?: number;
retryDelayMax?: number;

/**
* Preserve full numeric precision in results. When `true`, DECIMAL columns
* are returned as exact strings and 64-bit integers (BIGINT) as JS `bigint`,
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/DBSQLClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,42 @@ describe('DBSQLClient.createAuthProvider', () => {
});
});

describe('DBSQLClient retry-policy ConnectionOptions', () => {
it('ingests retry-policy options from connect() into ClientConfig', async () => {
const client = new DBSQLClient();

// Defaults before connect.
expect(client.getConfig().retryMaxAttempts).to.equal(5);
expect(client.getConfig().retriesTimeout).to.equal(15 * 60 * 1000);
expect(client.getConfig().retryDelayMin).to.equal(1000);
expect(client.getConfig().retryDelayMax).to.equal(60 * 1000);

await client.connect({
...connectOptions,
retryMaxAttempts: 2,
retriesTimeout: 5000,
retryDelayMin: 100,
retryDelayMax: 500,
});

expect(client.getConfig().retryMaxAttempts).to.equal(2);
expect(client.getConfig().retriesTimeout).to.equal(5000);
expect(client.getConfig().retryDelayMin).to.equal(100);
expect(client.getConfig().retryDelayMax).to.equal(500);
});

it('keeps defaults when retry-policy options are omitted', async () => {
const client = new DBSQLClient();

await client.connect({ ...connectOptions });

expect(client.getConfig().retryMaxAttempts).to.equal(5);
expect(client.getConfig().retriesTimeout).to.equal(15 * 60 * 1000);
expect(client.getConfig().retryDelayMin).to.equal(1000);
expect(client.getConfig().retryDelayMax).to.equal(60 * 1000);
});
});

describe('DBSQLClient.enableMetricViewMetadata', () => {
it('should store enableMetricViewMetadata config when enabled', async () => {
const client = new DBSQLClient();
Expand Down
Loading