Skip to content

Commit 80c660e

Browse files
Refactoring: Convert global config to client config and make it available through client context (#202)
Convert global config to client config and make it available through client context Signed-off-by: Levko Kravets <levko.ne@gmail.com>
1 parent 57c21d7 commit 80c660e

18 files changed

Lines changed: 397 additions & 266 deletions

lib/DBSQLClient.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import TCLIService from '../thrift/TCLIService';
55
import { TProtocolVersion } from '../thrift/TCLIService_types';
66
import IDBSQLClient, { ClientOptions, ConnectionOptions, OpenSessionRequest } from './contracts/IDBSQLClient';
77
import IDriver from './contracts/IDriver';
8-
import IClientContext from './contracts/IClientContext';
8+
import IClientContext, { ClientConfig } from './contracts/IClientContext';
99
import HiveDriver from './hive/HiveDriver';
1010
import { Int64 } from './hive/Types';
1111
import DBSQLSession from './DBSQLSession';
@@ -46,6 +46,8 @@ function getInitialNamespaceOptions(catalogName?: string, schemaName?: string) {
4646
export default class DBSQLClient extends EventEmitter implements IDBSQLClient, IClientContext {
4747
private static defaultLogger?: IDBSQLLogger;
4848

49+
private readonly config: ClientConfig;
50+
4951
private connectionProvider?: IConnectionProvider;
5052

5153
private authProvider?: IAuthentication;
@@ -69,8 +71,25 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I
6971
return this.defaultLogger;
7072
}
7173

74+
private static getDefaultConfig(): ClientConfig {
75+
return {
76+
arrowEnabled: true,
77+
useArrowNativeTypes: true,
78+
socketTimeout: 15 * 60 * 1000, // 15 minutes
79+
80+
retryMaxAttempts: 30,
81+
retriesTimeout: 900 * 1000,
82+
retryDelayMin: 1 * 1000,
83+
retryDelayMax: 60 * 1000,
84+
85+
useCloudFetch: false,
86+
cloudFetchConcurrentDownloads: 10,
87+
};
88+
}
89+
7290
constructor(options?: ClientOptions) {
7391
super();
92+
this.config = DBSQLClient.getDefaultConfig();
7493
this.logger = options?.logger ?? DBSQLClient.getDefaultLogger();
7594
this.logger.log(LogLevel.info, 'Created DBSQLClient');
7695
}
@@ -129,7 +148,7 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I
129148
public async connect(options: ConnectionOptions, authProvider?: IAuthentication): Promise<IDBSQLClient> {
130149
this.authProvider = this.initAuthProvider(options, authProvider);
131150

132-
this.connectionProvider = new HttpConnection(this.getConnectionOptions(options));
151+
this.connectionProvider = new HttpConnection(this.getConnectionOptions(options), this);
133152

134153
const thriftConnection = await this.connectionProvider.getThriftConnection();
135154

@@ -196,6 +215,10 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I
196215
this.authProvider = undefined;
197216
}
198217

218+
public getConfig(): ClientConfig {
219+
return this.config;
220+
}
221+
199222
public getLogger(): IDBSQLLogger {
200223
return this.logger;
201224
}

lib/DBSQLSession.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@ import { definedOrError } from './utils';
3333
import CloseableCollection from './utils/CloseableCollection';
3434
import { LogLevel } from './contracts/IDBSQLLogger';
3535
import HiveDriverError from './errors/HiveDriverError';
36-
import globalConfig from './globalConfig';
3736
import StagingError from './errors/StagingError';
3837
import { DBSQLParameter, DBSQLParameterValue } from './DBSQLParameter';
3938
import ParameterError from './errors/ParameterError';
40-
import IClientContext from './contracts/IClientContext';
39+
import IClientContext, { ClientConfig } from './contracts/IClientContext';
4140

4241
const defaultMaxRows = 100000;
4342

@@ -59,11 +58,11 @@ function getDirectResultsOptions(maxRows: number | null = defaultMaxRows) {
5958
};
6059
}
6160

62-
function getArrowOptions(): {
61+
function getArrowOptions(config: ClientConfig): {
6362
canReadArrowResult: boolean;
6463
useArrowNativeTypes?: TSparkArrowTypes;
6564
} {
66-
const { arrowEnabled = true, useArrowNativeTypes = true } = globalConfig;
65+
const { arrowEnabled = true, useArrowNativeTypes = true } = config;
6766

6867
if (!arrowEnabled) {
6968
return {
@@ -187,14 +186,15 @@ export default class DBSQLSession implements IDBSQLSession {
187186
public async executeStatement(statement: string, options: ExecuteStatementOptions = {}): Promise<IOperation> {
188187
await this.failIfClosed();
189188
const driver = await this.context.getDriver();
189+
const clientConfig = this.context.getConfig();
190190
const operationPromise = driver.executeStatement({
191191
sessionHandle: this.sessionHandle,
192192
statement,
193193
queryTimeout: options.queryTimeout,
194194
runAsync: true,
195195
...getDirectResultsOptions(options.maxRows),
196-
...getArrowOptions(),
197-
canDownloadResult: options.useCloudFetch ?? globalConfig.useCloudFetch,
196+
...getArrowOptions(clientConfig),
197+
canDownloadResult: options.useCloudFetch ?? clientConfig.useCloudFetch,
198198
parameters: getQueryParameters(this.sessionHandle, options.namedParameters, options.ordinalParameters),
199199
});
200200
const response = await this.handleResponse(operationPromise);

lib/connection/connections/HttpConnection.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,24 @@ import { ProxyAgent } from 'proxy-agent';
66

77
import IConnectionProvider from '../contracts/IConnectionProvider';
88
import IConnectionOptions, { ProxyOptions } from '../contracts/IConnectionOptions';
9-
import globalConfig from '../../globalConfig';
9+
import IClientContext from '../../contracts/IClientContext';
1010

1111
import ThriftHttpConnection from './ThriftHttpConnection';
1212

1313
export default class HttpConnection implements IConnectionProvider {
1414
private readonly options: IConnectionOptions;
1515

16+
private readonly context: IClientContext;
17+
1618
private headers: HeadersInit = {};
1719

1820
private connection?: ThriftHttpConnection;
1921

2022
private agent?: http.Agent;
2123

22-
constructor(options: IConnectionOptions) {
24+
constructor(options: IConnectionOptions, context: IClientContext) {
2325
this.options = options;
26+
this.context = context;
2427
}
2528

2629
public setHeaders(headers: HeadersInit) {
@@ -44,11 +47,12 @@ export default class HttpConnection implements IConnectionProvider {
4447
}
4548

4649
private getAgentDefaultOptions(): http.AgentOptions {
50+
const clientConfig = this.context.getConfig();
4751
return {
4852
keepAlive: true,
4953
maxSockets: 5,
5054
keepAliveMsecs: 10000,
51-
timeout: this.options.socketTimeout ?? globalConfig.socketTimeout,
55+
timeout: this.options.socketTimeout ?? clientConfig.socketTimeout,
5256
};
5357
}
5458

@@ -89,6 +93,7 @@ export default class HttpConnection implements IConnectionProvider {
8993
public async getThriftConnection(): Promise<any> {
9094
if (!this.connection) {
9195
const { options } = this;
96+
const clientConfig = this.context.getConfig();
9297
const agent = await this.getAgent();
9398

9499
this.connection = new ThriftHttpConnection(
@@ -99,7 +104,7 @@ export default class HttpConnection implements IConnectionProvider {
99104
},
100105
{
101106
agent,
102-
timeout: options.socketTimeout ?? globalConfig.socketTimeout,
107+
timeout: options.socketTimeout ?? clientConfig.socketTimeout,
103108
headers: {
104109
...options.headers,
105110
...this.headers,

lib/contracts/IClientContext.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,23 @@ import IDriver from './IDriver';
33
import IConnectionProvider from '../connection/contracts/IConnectionProvider';
44
import TCLIService from '../../thrift/TCLIService';
55

6+
export interface ClientConfig {
7+
arrowEnabled?: boolean;
8+
useArrowNativeTypes?: boolean;
9+
socketTimeout: number;
10+
11+
retryMaxAttempts: number;
12+
retriesTimeout: number; // in milliseconds
13+
retryDelayMin: number; // in milliseconds
14+
retryDelayMax: number; // in milliseconds
15+
16+
useCloudFetch: boolean;
17+
cloudFetchConcurrentDownloads: number;
18+
}
19+
620
export default interface IClientContext {
21+
getConfig(): ClientConfig;
22+
723
getLogger(): IDBSQLLogger;
824

925
getConnectionProvider(): Promise<IConnectionProvider>;

lib/globalConfig.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

lib/hive/Commands/BaseCommand.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { Thrift } from 'thrift';
22
import TCLIService from '../../../thrift/TCLIService';
33
import HiveDriverError from '../../errors/HiveDriverError';
4-
import globalConfig from '../../globalConfig';
4+
import IClientContext, { ClientConfig } from '../../contracts/IClientContext';
55

66
interface CommandExecutionInfo {
77
startTime: number; // in milliseconds
88
attempt: number;
99
}
1010

11-
function getRetryDelay(attempt: number): number {
11+
function getRetryDelay(attempt: number, config: ClientConfig): number {
1212
const scale = Math.max(1, 1.5 ** (attempt - 1)); // ensure scale >= 1
13-
return Math.min(globalConfig.retryDelayMin * scale, globalConfig.retryDelayMax);
13+
return Math.min(config.retryDelayMin * scale, config.retryDelayMax);
1414
}
1515

1616
function delay(milliseconds: number): Promise<void> {
@@ -22,8 +22,11 @@ function delay(milliseconds: number): Promise<void> {
2222
export default abstract class BaseCommand {
2323
protected client: TCLIService.Client;
2424

25-
constructor(client: TCLIService.Client) {
25+
protected context: IClientContext;
26+
27+
constructor(client: TCLIService.Client, context: IClientContext) {
2628
this.client = client;
29+
this.context = context;
2730
}
2831

2932
protected executeCommand<Response>(request: object, command: Function | void): Promise<Response> {
@@ -49,19 +52,21 @@ export default abstract class BaseCommand {
4952
case 503: // Service Unavailable
5053
info.attempt += 1;
5154

55+
const clientConfig = this.context.getConfig();
56+
5257
// Delay interval depends on current attempt - the more attempts we do
5358
// the longer the interval will be
5459
// TODO: Respect `Retry-After` header (PECO-729)
55-
const retryDelay = getRetryDelay(info.attempt);
60+
const retryDelay = getRetryDelay(info.attempt, clientConfig);
5661

57-
const attemptsExceeded = info.attempt >= globalConfig.retryMaxAttempts;
62+
const attemptsExceeded = info.attempt >= clientConfig.retryMaxAttempts;
5863
if (attemptsExceeded) {
5964
throw new HiveDriverError(
6065
`Hive driver: ${error.statusCode} when connecting to resource. Max retry count exceeded.`,
6166
);
6267
}
6368

64-
const timeoutExceeded = Date.now() - info.startTime + retryDelay >= globalConfig.retriesTimeout;
69+
const timeoutExceeded = Date.now() - info.startTime + retryDelay >= clientConfig.retriesTimeout;
6570
if (timeoutExceeded) {
6671
throw new HiveDriverError(
6772
`Hive driver: ${error.statusCode} when connecting to resource. Retry timeout exceeded.`,

0 commit comments

Comments
 (0)