Skip to content

Commit a2a4b32

Browse files
Refactoring (#40)
* Use `import` instead of `require` * Merge HiveClient into DBSQLClient * Rename some Hive classes * Update docs
1 parent c8242ff commit a2a4b32

18 files changed

+361
-475
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ client
5353
console.table(result);
5454

5555
await session.close();
56-
client.close();
56+
await client.close();
5757
})
5858
.catch((error) => {
5959
console.log(error);

examples/session.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ client
3737
console.log();
3838

3939
await session.close();
40+
await client.close();
4041
})
4142
.catch((error) => {
4243
console.log(error);

examples/usage.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ client
1313
console.log(response.getValue());
1414

1515
await session.close();
16+
await client.close();
1617
})
1718
.catch((error) => {
1819
console.log(error);

lib/DBSQLClient.ts

Lines changed: 115 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,134 @@
1-
import TCLIService_types from '../thrift/TCLIService_types';
2-
import HiveClient from './HiveClient';
3-
import HiveUtils from './utils/HiveUtils';
4-
import PlainHttpAuthentication from './connection/auth/PlainHttpAuthentication';
1+
import thrift from 'thrift';
2+
3+
import TCLIService from '../thrift/TCLIService';
4+
import TCLIService_types, { TOpenSessionReq } from '../thrift/TCLIService_types';
5+
import IDBSQLClient, { IDBSQLConnectionOptions } from './contracts/IDBSQLClient';
6+
import HiveDriver from './hive/HiveDriver';
7+
import DBSQLSession from './DBSQLSession';
8+
import IDBSQLSession from './contracts/IDBSQLSession';
9+
import IThriftConnection from './connection/contracts/IThriftConnection';
10+
import IConnectionProvider from './connection/contracts/IConnectionProvider';
11+
import IAuthentication from './connection/contracts/IAuthentication';
12+
import NoSaslAuthentication from './connection/auth/NoSaslAuthentication';
513
import HttpConnection from './connection/connections/HttpConnection';
14+
import IConnectionOptions from './connection/contracts/IConnectionOptions';
15+
import { EventEmitter } from 'events';
16+
import StatusFactory from './factory/StatusFactory';
17+
import HiveDriverError from './errors/HiveDriverError';
18+
import { buildUserAgentString, definedOrError } from './utils';
19+
import PlainHttpAuthentication from './connection/auth/PlainHttpAuthentication';
20+
import HiveUtils from './utils/HiveUtils';
621

7-
import IHiveSession from './contracts/IHiveSession';
22+
export default class DBSQLClient extends EventEmitter implements IDBSQLClient {
23+
static utils = new HiveUtils();
824

9-
import { buildUserAgentString } from './utils';
25+
private client: TCLIService.Client | null;
26+
private connection: IThriftConnection | null;
27+
private statusFactory: StatusFactory;
28+
private connectionProvider: IConnectionProvider;
29+
private authProvider: IAuthentication;
30+
private thrift = thrift;
1031

11-
interface EventEmitter extends NodeJS.EventEmitter {}
32+
constructor() {
33+
super();
34+
this.connectionProvider = new HttpConnection();
35+
this.authProvider = new NoSaslAuthentication();
36+
this.statusFactory = new StatusFactory();
37+
this.client = null;
38+
this.connection = null;
39+
}
1240

13-
interface IConnectionOptions {
14-
host: string;
15-
port?: number;
16-
path: string;
17-
token: string;
18-
clientId?: string;
19-
}
41+
private getConnectionOptions(options: IDBSQLConnectionOptions): IConnectionOptions {
42+
const { host, port, token, clientId, ...otherOptions } = options;
43+
return {
44+
host,
45+
port: port || 443,
46+
options: {
47+
https: true,
48+
...otherOptions,
49+
},
50+
};
51+
}
2052

21-
/**
22-
* @see IHiveClient
23-
*/
24-
interface IDBSQLClient {
25-
connect(options: IConnectionOptions): Promise<IDBSQLClient>;
26-
openSession(): Promise<IHiveSession>;
27-
close(): void;
28-
}
53+
async connect(options: IDBSQLConnectionOptions): Promise<IDBSQLClient> {
54+
this.authProvider = new PlainHttpAuthentication({
55+
username: 'token',
56+
password: options.token,
57+
headers: {
58+
'User-Agent': buildUserAgentString(options.clientId),
59+
},
60+
});
2961

30-
function prependSlash(str: string): string {
31-
if (str.length > 0 && str.charAt(0) !== '/') {
32-
return `/${str}`;
33-
}
34-
return str;
35-
}
62+
this.connection = await this.connectionProvider.connect(this.getConnectionOptions(options), this.authProvider);
3663

37-
export default class DBSQLClient implements IDBSQLClient, EventEmitter {
38-
static utils = new HiveUtils();
64+
this.client = this.thrift.createClient(TCLIService, this.connection.getConnection());
3965

40-
private client: HiveClient = new HiveClient();
41-
42-
connect(options: IConnectionOptions) {
43-
return this.client
44-
.connect(
45-
{
46-
host: options.host,
47-
port: options.port || 443,
48-
options: {
49-
path: prependSlash(options.path),
50-
https: true,
51-
},
52-
},
53-
new HttpConnection(),
54-
new PlainHttpAuthentication({
55-
username: 'token',
56-
password: options.token,
57-
headers: {
58-
'User-Agent': buildUserAgentString(options.clientId),
59-
},
60-
}),
61-
)
62-
.then(() => this);
63-
}
66+
this.connection.getConnection().on('error', (error: Error) => {
67+
this.emit('error', error);
68+
});
6469

65-
openSession() {
66-
return this.client.openSession({
67-
client_protocol: TCLIService_types.TProtocolVersion.SPARK_CLI_SERVICE_PROTOCOL_V6,
70+
this.connection.getConnection().on('reconnecting', (params: { delay: number; attempt: number }) => {
71+
this.emit('reconnecting', params);
6872
});
69-
}
7073

71-
close() {
72-
this.client.close();
73-
}
74+
this.connection.getConnection().on('close', () => {
75+
this.emit('close');
76+
});
77+
78+
this.connection.getConnection().on('timeout', () => {
79+
this.emit('timeout');
80+
});
7481

75-
// EventEmitter
76-
addListener(event: string | symbol, listener: (...args: any[]) => void) {
77-
this.client.addListener(event, listener);
78-
return this;
79-
}
80-
on(event: string | symbol, listener: (...args: any[]) => void) {
81-
this.client.on(event, listener);
82-
return this;
83-
}
84-
once(event: string | symbol, listener: (...args: any[]) => void) {
85-
this.client.once(event, listener);
86-
return this;
87-
}
88-
removeListener(event: string | symbol, listener: (...args: any[]) => void) {
89-
this.client.removeListener(event, listener);
90-
return this;
91-
}
92-
off(event: string | symbol, listener: (...args: any[]) => void) {
93-
this.client.off(event, listener);
94-
return this;
95-
}
96-
removeAllListeners(event?: string | symbol) {
97-
this.client.removeAllListeners(event);
98-
return this;
99-
}
100-
setMaxListeners(n: number) {
101-
this.client.setMaxListeners(n);
10282
return this;
10383
}
104-
getMaxListeners() {
105-
return this.client.getMaxListeners();
106-
}
107-
listeners(event: string | symbol) {
108-
return this.client.listeners(event);
109-
}
110-
rawListeners(event: string | symbol) {
111-
return this.client.rawListeners(event);
112-
}
113-
emit(event: string | symbol, ...args: any[]) {
114-
return this.client.emit(event, ...args);
115-
}
116-
listenerCount(type: string | symbol) {
117-
return this.client.listenerCount(type);
118-
}
119-
prependListener(event: string | symbol, listener: (...args: any[]) => void) {
120-
this.client.prependListener(event, listener);
121-
return this;
84+
85+
/**
86+
* Starts new session
87+
*
88+
* @param request
89+
* @throws {StatusError}
90+
*/
91+
openSession(request?: TOpenSessionReq): Promise<IDBSQLSession> {
92+
if (!this.connection?.isConnected()) {
93+
return Promise.reject(new HiveDriverError('DBSQLClient: connection is lost'));
94+
}
95+
96+
const driver = new HiveDriver(this.getClient());
97+
98+
if (!request) {
99+
request = {
100+
client_protocol: TCLIService_types.TProtocolVersion.SPARK_CLI_SERVICE_PROTOCOL_V6,
101+
};
102+
}
103+
104+
return driver.openSession(request).then((response) => {
105+
this.statusFactory.create(response.status);
106+
107+
const session = new DBSQLSession(driver, definedOrError(response.sessionHandle));
108+
109+
return session;
110+
});
122111
}
123-
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void) {
124-
this.client.prependOnceListener(event, listener);
125-
return this;
112+
113+
getClient() {
114+
if (!this.client) {
115+
throw new HiveDriverError('DBSQLClient: client is not initialized');
116+
}
117+
118+
return this.client;
126119
}
127-
eventNames() {
128-
return this.client.eventNames();
120+
121+
close(): Promise<void> {
122+
if (!this.connection) {
123+
return Promise.resolve();
124+
}
125+
126+
const thriftConnection = this.connection.getConnection();
127+
128+
if (typeof thriftConnection.end === 'function') {
129+
this.connection.getConnection().end();
130+
}
131+
132+
return Promise.resolve();
129133
}
130134
}

lib/HiveOperation.ts renamed to lib/DBSQLOperation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Status from './dto/Status';
1515
import StatusFactory from './factory/StatusFactory';
1616
import { definedOrError } from './utils';
1717

18-
export default class HiveOperation implements IOperation {
18+
export default class DBSQLOperation implements IOperation {
1919
private driver: HiveDriver;
2020
private operationHandle: TOperationHandle;
2121
private schema: TTableSchema | null;

lib/HiveSession.ts renamed to lib/DBSQLSession.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import { TSessionHandle, TStatus, TOperationHandle } from '../thrift/TCLIService_types';
22
import HiveDriver from './hive/HiveDriver';
3-
import IHiveSession, {
3+
import IDBSQLSession, {
44
ExecuteStatementOptions,
55
SchemasRequest,
66
TablesRequest,
77
ColumnRequest,
88
PrimaryKeysRequest,
99
FunctionNameRequest,
1010
CrossReferenceRequest,
11-
} from './contracts/IHiveSession';
11+
} from './contracts/IDBSQLSession';
1212
import IOperation from './contracts/IOperation';
13-
import HiveOperation from './HiveOperation';
13+
import DBSQLOperation from './DBSQLOperation';
1414
import Status from './dto/Status';
1515
import StatusFactory from './factory/StatusFactory';
1616
import InfoValue from './dto/InfoValue';
1717
import { definedOrError } from './utils';
1818

19-
export default class HiveSession implements IHiveSession {
19+
export default class DBSQLSession implements IDBSQLSession {
2020
private driver: HiveDriver;
2121
private sessionHandle: TSessionHandle;
2222
private statusFactory: StatusFactory;
@@ -240,7 +240,7 @@ export default class HiveSession implements IHiveSession {
240240
}
241241

242242
private createOperation(handle: TOperationHandle): IOperation {
243-
return new HiveOperation(this.driver, handle);
243+
return new DBSQLOperation(this.driver, handle);
244244
}
245245

246246
private assertStatus(responseStatus: TStatus): void {

0 commit comments

Comments
 (0)