Skip to content

Commit 1fd9e1e

Browse files
Make lz4 module optional (#246)
* Make `lz4` module optional Signed-off-by: Levko Kravets <levko.ne@gmail.com> * Fix lint errors Signed-off-by: Levko Kravets <levko.ne@gmail.com> --------- Signed-off-by: Levko Kravets <levko.ne@gmail.com>
1 parent 38db1b0 commit 1fd9e1e

File tree

8 files changed

+70
-18
lines changed

8 files changed

+70
-18
lines changed

.eslintrc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@
1515
"@typescript-eslint/no-throw-literal": "off",
1616
"no-restricted-syntax": "off",
1717
"no-case-declarations": "off",
18-
"max-classes-per-file": "off"
18+
"max-classes-per-file": "off",
19+
"import/no-extraneous-dependencies": [
20+
"error",
21+
{
22+
"devDependencies": true,
23+
"optionalDependencies": true
24+
}
25+
]
1926
}
2027
}
2128
]

lib/DBSQLSession.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import IOperation from './contracts/IOperation';
2929
import DBSQLOperation from './DBSQLOperation';
3030
import Status from './dto/Status';
3131
import InfoValue from './dto/InfoValue';
32-
import { definedOrError } from './utils';
32+
import { definedOrError, LZ4 } from './utils';
3333
import CloseableCollection from './utils/CloseableCollection';
3434
import { LogLevel } from './contracts/IDBSQLLogger';
3535
import HiveDriverError from './errors/HiveDriverError';
@@ -190,7 +190,7 @@ export default class DBSQLSession implements IDBSQLSession {
190190
...getArrowOptions(clientConfig),
191191
canDownloadResult: options.useCloudFetch ?? clientConfig.useCloudFetch,
192192
parameters: getQueryParameters(this.sessionHandle, options.namedParameters, options.ordinalParameters),
193-
canDecompressLZ4Result: clientConfig.useLZ4Compression,
193+
canDecompressLZ4Result: clientConfig.useLZ4Compression && Boolean(LZ4),
194194
});
195195
const response = await this.handleResponse(operationPromise);
196196
const operation = this.createOperation(response);

lib/result/ArrowResultHandler.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import LZ4 from 'lz4';
21
import { TGetResultSetMetadataResp, TRowSet } from '../../thrift/TCLIService_types';
2+
import HiveDriverError from '../errors/HiveDriverError';
33
import IClientContext from '../contracts/IClientContext';
44
import IResultsProvider, { ResultsProviderFetchNextOptions } from './IResultsProvider';
55
import { ArrowBatch, hiveSchemaToArrowSchema } from './utils';
6+
import { LZ4 } from '../utils';
67

78
export default class ArrowResultHandler implements IResultsProvider<ArrowBatch> {
89
protected readonly context: IClientContext;
@@ -24,6 +25,10 @@ export default class ArrowResultHandler implements IResultsProvider<ArrowBatch>
2425
// so it's possible to infer Arrow schema from Hive schema ignoring `useArrowNativeTypes` option
2526
this.arrowSchema = arrowSchema ?? hiveSchemaToArrowSchema(schema);
2627
this.isLZ4Compressed = lz4Compressed ?? false;
28+
29+
if (this.isLZ4Compressed && !LZ4) {
30+
throw new HiveDriverError('Cannot handle LZ4 compressed result: module `lz4` not installed');
31+
}
2732
}
2833

2934
public async hasMore() {
@@ -47,7 +52,7 @@ export default class ArrowResultHandler implements IResultsProvider<ArrowBatch>
4752
let totalRowCount = 0;
4853
rowSet?.arrowBatches?.forEach(({ batch, rowCount }) => {
4954
if (batch) {
50-
batches.push(this.isLZ4Compressed ? LZ4.decode(batch) : batch);
55+
batches.push(this.isLZ4Compressed ? LZ4!.decode(batch) : batch);
5156
totalRowCount += rowCount.toNumber(true);
5257
}
5358
});

lib/result/CloudFetchResultHandler.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import LZ4 from 'lz4';
21
import fetch, { RequestInfo, RequestInit, Request } from 'node-fetch';
32
import { TGetResultSetMetadataResp, TRowSet, TSparkArrowResultLink } from '../../thrift/TCLIService_types';
3+
import HiveDriverError from '../errors/HiveDriverError';
44
import IClientContext from '../contracts/IClientContext';
55
import IResultsProvider, { ResultsProviderFetchNextOptions } from './IResultsProvider';
66
import { ArrowBatch } from './utils';
7+
import { LZ4 } from '../utils';
78

89
export default class CloudFetchResultHandler implements IResultsProvider<ArrowBatch> {
910
protected readonly context: IClientContext;
@@ -24,6 +25,10 @@ export default class CloudFetchResultHandler implements IResultsProvider<ArrowBa
2425
this.context = context;
2526
this.source = source;
2627
this.isLZ4Compressed = lz4Compressed ?? false;
28+
29+
if (this.isLZ4Compressed && !LZ4) {
30+
throw new HiveDriverError('Cannot handle LZ4 compressed result: module `lz4` not installed');
31+
}
2732
}
2833

2934
public async hasMore() {
@@ -58,7 +63,7 @@ export default class CloudFetchResultHandler implements IResultsProvider<ArrowBa
5863
}
5964

6065
if (this.isLZ4Compressed) {
61-
batch.batches = batch.batches.map((buffer) => LZ4.decode(buffer));
66+
batch.batches = batch.batches.map((buffer) => LZ4!.decode(buffer));
6267
}
6368
return batch;
6469
}

lib/utils/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import definedOrError from './definedOrError';
22
import buildUserAgentString from './buildUserAgentString';
33
import formatProgress, { ProgressUpdateTransformer } from './formatProgress';
4+
import LZ4 from './lz4';
45

5-
export { definedOrError, buildUserAgentString, formatProgress, ProgressUpdateTransformer };
6+
export { definedOrError, buildUserAgentString, formatProgress, ProgressUpdateTransformer, LZ4 };

lib/utils/lz4.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type LZ4Namespace from 'lz4';
2+
3+
type LZ4Module = typeof LZ4Namespace;
4+
5+
function tryLoadLZ4Module(): LZ4Module | undefined {
6+
try {
7+
return require('lz4'); // eslint-disable-line global-require
8+
} catch (err) {
9+
const isModuleNotFoundError = err instanceof Error && 'code' in err && err.code === 'MODULE_NOT_FOUND';
10+
if (!isModuleNotFoundError) {
11+
throw err;
12+
}
13+
}
14+
}
15+
16+
export default tryLoadLZ4Module();

package-lock.json

Lines changed: 25 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
"dependencies": {
7575
"apache-arrow": "^13.0.0",
7676
"commander": "^9.3.0",
77-
"lz4": "^0.6.5",
7877
"node-fetch": "^2.6.12",
7978
"node-int64": "^0.4.0",
8079
"open": "^8.4.2",
@@ -83,5 +82,8 @@
8382
"thrift": "^0.16.0",
8483
"uuid": "^9.0.0",
8584
"winston": "^3.8.2"
85+
},
86+
"optionalDependencies": {
87+
"lz4": "^0.6.5"
8688
}
8789
}

0 commit comments

Comments
 (0)