import * as plugins from './smartclickhouse.plugins.js'; import { TimeDataTable } from './smartclickhouse.classes.timedatatable.js'; import { ClickhouseHttpClient } from './smartclickhouse.classes.httpclient.js'; export interface IClickhouseConstructorOptions { url: string; database: string; username?: string; password?: string; /** * allow services to exit when waiting for clickhouse startup * this allows to leave the lifecycle flow to other processes * like a listening server. */ unref?: boolean; } export class SmartClickHouseDb { public options: IClickhouseConstructorOptions; public clickhouseHttpClient: ClickhouseHttpClient; constructor(optionsArg: IClickhouseConstructorOptions) { this.options = optionsArg; } /** * starts the connection to the Clickhouse db */ public async start(dropOld = false) { console.log(`Connecting to default database first.`); // lets connect this.clickhouseHttpClient = await ClickhouseHttpClient.createAndStart(this.options); await this.pingDatabaseUntilAvailable(); console.log(`Create database ${this.options.database}, if it does not exist...`); await this.createDatabase(dropOld); } public async createDatabase(dropOld: boolean = false) { if (dropOld) { await this.clickhouseHttpClient.queryPromise(`DROP DATABASE IF EXISTS ${this.options.database}`); } await this.clickhouseHttpClient.queryPromise( `CREATE DATABASE IF NOT EXISTS ${this.options.database}` ); } public async pingDatabaseUntilAvailable() { let available = false; while (!available) { available = await this.clickhouseHttpClient.ping().catch((err) => { return false; }); if (!available) { console.log(`NOT OK: tried pinging ${this.options.url}... Trying again in 5 seconds.`); await plugins.smartdelay.delayFor(5000, null, this.options.unref); } } } /** * gets a table */ public async getTable(tableName: string) { const newTable = TimeDataTable.getTable(this, tableName); return newTable; } }