Socket
Socket
Sign inDemoInstall

@clickhouse/client

Package Overview
Dependencies
Maintainers
3
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@clickhouse/client - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

49

dist/client.d.ts

@@ -11,26 +11,34 @@ /// <reference types="node" />

export interface ClickHouseClientConfigOptions {
/** A ClickHouse instance URL. Default value: `http://localhost:8123`. */
/** A ClickHouse instance URL.
* <br/> Default value: `http://localhost:8123`. */
host?: string;
/** The request timeout in milliseconds. Default value: `30_000`. */
/** The request timeout in milliseconds.
* <br/> Default value: `30_000`. */
request_timeout?: number;
/** Maximum number of sockets to allow per host. Default value: `Infinity`. */
/** Maximum number of sockets to allow per host.
* <br/> Default value: `Infinity`. */
max_open_connections?: number;
compression?: {
/** `response: true` instructs ClickHouse server to respond with compressed response body. Default: true. */
/** `response: true` instructs ClickHouse server to respond with
* compressed response body. <br/> Default: true. */
response?: boolean;
/** `request: true` enabled compression on the client request body. Default: false. */
/** `request: true` enabled compression on the client request body.
* <br/> Default: false. */
request?: boolean;
};
/** The name of the user on whose behalf requests are made. Default: 'default'. */
/** The name of the user on whose behalf requests are made.
* <br/> Default: 'default'. */
username?: string;
/** The user password. Default: ''. */
/** The user password. <br/> Default: ''. */
password?: string;
/** The name of the application using the nodejs client. Default: empty. */
/** The name of the application using the nodejs client.
* <br/> Default: empty. */
application?: string;
/** Database name to use. Default value: `default`. */
/** Database name to use. <br/> Default value: `default`. */
database?: string;
/** ClickHouse settings to apply to all requests. Default value: {} */
/** ClickHouse settings to apply to all requests. <br/> Default value: {} */
clickhouse_settings?: ClickHouseSettings;
log?: {
/** A class to instantiate a custom logger implementation. */
/** A class to instantiate a custom logger implementation.
* <br/> Default: {@link DefaultLogger} */
LoggerClass?: new () => Logger;

@@ -40,2 +48,21 @@ };

session_id?: string;
/** HTTP Keep-Alive related settings */
keep_alive?: {
/** Enable or disable HTTP Keep-Alive mechanism. <br/> Default: true */
enabled?: boolean;
/** How long to keep a particular open socket alive
* on the client side (in milliseconds).
* Should be less than the server setting
* (see `keep_alive_timeout` in server's `config.xml`). <br/>
* Currently, has no effect if {@link retry_on_expired_socket}
* is unset or false. <br/> Default value: 2500
* (based on the default ClickHouse server setting, which is 3000) */
socket_ttl?: number;
/** If the client detects a potentially expired socket based on the
* {@link socket_ttl}, this socket will be immediately destroyed
* before sending the request, and this request will be retried
* with a new socket up to 3 times.
* <br/> * Default: false (no retries) */
retry_on_expired_socket?: boolean;
};
}

@@ -42,0 +69,0 @@ interface BasicTLSOptions {

@@ -28,3 +28,3 @@ "use strict";

function normalizeConfig(config) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
let tls = undefined;

@@ -57,9 +57,13 @@ if (config.tls) {

password: (_j = config.password) !== null && _j !== void 0 ? _j : '',
application: (_k = config.application) !== null && _k !== void 0 ? _k : 'clickhouse-js',
database: (_l = config.database) !== null && _l !== void 0 ? _l : 'default',
clickhouse_settings: (_m = config.clickhouse_settings) !== null && _m !== void 0 ? _m : {},
database: (_k = config.database) !== null && _k !== void 0 ? _k : 'default',
clickhouse_settings: (_l = config.clickhouse_settings) !== null && _l !== void 0 ? _l : {},
log: {
LoggerClass: (_p = (_o = config.log) === null || _o === void 0 ? void 0 : _o.LoggerClass) !== null && _p !== void 0 ? _p : logger_1.DefaultLogger,
LoggerClass: (_o = (_m = config.log) === null || _m === void 0 ? void 0 : _m.LoggerClass) !== null && _o !== void 0 ? _o : logger_1.DefaultLogger,
},
session_id: config.session_id,
keep_alive: {
enabled: (_q = (_p = config.keep_alive) === null || _p === void 0 ? void 0 : _p.enabled) !== null && _q !== void 0 ? _q : true,
socket_ttl: (_s = (_r = config.keep_alive) === null || _r === void 0 ? void 0 : _r.socket_ttl) !== null && _s !== void 0 ? _s : 2500,
retry_on_expired_socket: (_u = (_t = config.keep_alive) === null || _t === void 0 ? void 0 : _t.retry_on_expired_socket) !== null && _u !== void 0 ? _u : false,
},
};

@@ -66,0 +70,0 @@ }

@@ -20,6 +20,9 @@ /// <reference types="node" />

protected readonly headers: Http.OutgoingHttpHeaders;
private readonly retry_expired_sockets;
private readonly known_sockets;
protected constructor(config: ConnectionParams, logger: Logger, agent: Http.Agent);
protected buildDefaultHeaders(username: string, password: string): Http.OutgoingHttpHeaders;
protected abstract createClientRequest(params: RequestParams, abort_signal?: AbortSignal): Http.ClientRequest;
protected request(params: RequestParams): Promise<Stream.Readable>;
private request;
private _request;
ping(): Promise<boolean>;

@@ -26,0 +29,0 @@ query(params: QueryParams): Promise<QueryResult>;

@@ -72,2 +72,3 @@ "use strict";

}
const expiredSocketMessage = 'expired socket';
class BaseHttpAdapter {

@@ -99,3 +100,18 @@ constructor(config, logger, agent) {

});
Object.defineProperty(this, "retry_expired_sockets", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "known_sockets", {
enumerable: true,
configurable: true,
writable: true,
value: new WeakMap()
});
this.headers = this.buildDefaultHeaders(config.username, config.password);
this.retry_expired_sockets =
this.config.keep_alive.enabled &&
this.config.keep_alive.retry_on_expired_socket;
}

@@ -108,3 +124,23 @@ buildDefaultHeaders(username, password) {

}
async request(params) {
async request(params, retryCount = 0) {
try {
return await this._request(params);
}
catch (e) {
if (e instanceof Error && e.message === expiredSocketMessage) {
if (this.retry_expired_sockets && retryCount < 3) {
this.logger.trace({
module: 'Connection',
message: `Keep-Alive socket is expired, retrying with a new one, retries so far: ${retryCount}`,
});
return await this.request(params, retryCount + 1);
}
else {
throw new Error(`Socket hang up after ${retryCount} retries`);
}
}
throw e;
}
}
async _request(params) {
return new Promise((resolve, reject) => {

@@ -148,9 +184,82 @@ const start = Date.now();

}
const config = this.config;
function onSocket(socket) {
// Force KeepAlive usage (workaround due to Node.js bug)
// https://github.com/nodejs/node/issues/47137#issuecomment-1477075229
socket.setKeepAlive(true, 1000);
socket.setTimeout(config.request_timeout, onTimeout);
function pipeStream() {
// if request.end() was called due to no data to send
if (request.writableEnded) {
return;
}
const bodyStream = (0, utils_1.isStream)(params.body)
? params.body
: stream_1.default.Readable.from([params.body]);
const callback = (err) => {
if (err) {
removeRequestListeners();
reject(err);
}
};
if (params.compress_request) {
stream_1.default.pipeline(bodyStream, zlib_1.default.createGzip(), request, callback);
}
else {
stream_1.default.pipeline(bodyStream, request, callback);
}
}
const onSocket = (socket) => {
if (this.retry_expired_sockets) {
// if socket is reused
const socketInfo = this.known_sockets.get(socket);
if (socketInfo !== undefined) {
this.logger.trace({
module: 'Connection',
message: `Reused socket ${socketInfo.id}`,
});
// if a socket was reused at an unfortunate time,
// and is likely about to expire
const isPossiblyExpired = Date.now() - socketInfo.last_used_time >
this.config.keep_alive.socket_ttl;
if (isPossiblyExpired) {
this.logger.trace({
module: 'Connection',
message: 'Socket should be expired - terminate it',
});
this.known_sockets.delete(socket);
socket.destroy(); // immediately terminate the connection
request.destroy();
reject(new Error(expiredSocketMessage));
}
else {
this.logger.trace({
module: 'Connection',
message: `Socket ${socketInfo.id} is safe to be reused`,
});
this.known_sockets.set(socket, {
id: socketInfo.id,
last_used_time: Date.now(),
});
pipeStream();
}
}
else {
const socketId = uuid.v4();
this.logger.trace({
module: 'Connection',
message: `Using a new socket ${socketId}`,
});
this.known_sockets.set(socket, {
id: socketId,
last_used_time: Date.now(),
});
pipeStream();
}
}
else {
// no need to track the reused sockets;
// keep alive is disabled or retry mechanism is not enabled
pipeStream();
}
// this is for request timeout only.
// The socket won't be actually destroyed,
// and it will be returned to the pool.
// TODO: investigate if can actually remove the idle sockets properly
socket.setTimeout(this.config.request_timeout, onTimeout);
};
function onTimeout() {

@@ -183,17 +292,2 @@ removeRequestListeners();

return request.end();
const bodyStream = (0, utils_1.isStream)(params.body)
? params.body
: stream_1.default.Readable.from([params.body]);
const callback = (err) => {
if (err) {
removeRequestListeners();
reject(err);
}
};
if (params.compress_request) {
stream_1.default.pipeline(bodyStream, zlib_1.default.createGzip(), request, callback);
}
else {
stream_1.default.pipeline(bodyStream, request, callback);
}
});

@@ -285,3 +379,3 @@ }

this.logger.debug({
module: 'HTTP Adapter',
module: 'Connection',
message: 'Got a response from ClickHouse',

@@ -288,0 +382,0 @@ args: {

@@ -12,3 +12,3 @@ "use strict";

const agent = new http_1.default.Agent({
keepAlive: true,
keepAlive: config.keep_alive.enabled,
maxSockets: config.max_open_connections,

@@ -15,0 +15,0 @@ });

@@ -13,3 +13,3 @@ "use strict";

const agent = new https_1.default.Agent({
keepAlive: true,
keepAlive: config.keep_alive.enabled,
maxSockets: config.max_open_connections,

@@ -16,0 +16,0 @@ ca: (_a = config.tls) === null || _a === void 0 ? void 0 : _a.ca_cert,

@@ -19,2 +19,7 @@ /// <reference types="node" />

database: string;
keep_alive: {
enabled: boolean;
socket_ttl: number;
retry_on_expired_socket: boolean;
};
}

@@ -21,0 +26,0 @@ export type TLSParams = {

@@ -10,2 +10,3 @@ export interface LogParams {

export interface Logger {
trace(params: LogParams): void;
debug(params: LogParams): void;

@@ -17,2 +18,3 @@ info(params: LogParams): void;

export declare class DefaultLogger implements Logger {
trace({ module, message, args }: LogParams): void;
debug({ module, message, args }: LogParams): void;

@@ -27,2 +29,3 @@ info({ module, message, args }: LogParams): void;

constructor(logger: Logger);
trace(params: LogParams): void;
debug(params: LogParams): void;

@@ -29,0 +32,0 @@ info(params: LogParams): void;

@@ -5,2 +5,5 @@ "use strict";

class DefaultLogger {
trace({ module, message, args }) {
console.trace(formatMessage({ module, message }), args);
}
debug({ module, message, args }) {

@@ -40,2 +43,7 @@ console.debug(formatMessage({ module, message }), args);

}
trace(params) {
if (this.logLevel <= ClickHouseLogLevel.TRACE) {
this.logger.trace(params);
}
}
debug(params) {

@@ -42,0 +50,0 @@ if (this.logLevel <= ClickHouseLogLevel.DEBUG) {

@@ -1,2 +0,2 @@

declare const _default: "0.1.0";
declare const _default: "0.1.1";
export default _default;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = '0.1.0';
exports.default = '0.1.1';
//# sourceMappingURL=version.js.map
{
"name": "@clickhouse/client",
"version": "0.1.0",
"version": "0.1.1",
"description": "Official JS client for ClickHouse DB",

@@ -5,0 +5,0 @@ "license": "Apache-2.0",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc