Files
smartclickhouse/ts/smartclickhouse.classes.timedatatable.ts

114 lines
3.6 KiB
TypeScript

import * as plugins from './smartclickhouse.plugins.js';
import type { SmartClickHouseDb } from './smartclickhouse.classes.smartclickhouse.js';
import { ClickhouseTable } from './smartclickhouse.classes.clickhousetable.js';
/**
* Creates a pre-configured ClickhouseTable for time-series data.
* This is the backward-compatible equivalent of the old TimeDataTable class.
*
* The table uses MergeTree engine, orders by timestamp, and has auto-schema evolution enabled.
*/
export async function createTimeDataTable(
db: SmartClickHouseDb,
tableName: string,
retainDataForDays: number = 30,
): Promise<TimeDataTable> {
const table = new TimeDataTable(db, tableName, retainDataForDays);
await table.setup();
return table;
}
/**
* TimeDataTable — a ClickhouseTable pre-configured for time-series data.
* Provides backward-compatible convenience methods (addData, getLastEntries, etc.).
*/
export class TimeDataTable extends ClickhouseTable<any> {
/**
* Static factory for backward compatibility
*/
public static async getTable(
smartClickHouseDbRefArg: SmartClickHouseDb,
tableNameArg: string,
retainDataForDays: number = 30,
): Promise<TimeDataTable> {
return createTimeDataTable(smartClickHouseDbRefArg, tableNameArg, retainDataForDays);
}
constructor(db: SmartClickHouseDb, tableName: string, retainDataForDays: number = 30) {
super(db, {
tableName,
engine: { engine: 'MergeTree' },
orderBy: 'timestamp' as any,
retainDataForDays,
autoSchemaEvolution: true,
});
}
/**
* Insert data with auto-schema evolution and object flattening.
* Backward-compatible: accepts arbitrary JSON objects with a timestamp field.
*/
public async addData(dataArg: any): Promise<any> {
if (!dataArg.timestamp || typeof dataArg.timestamp !== 'number') {
throw new Error('timestamp must be of type number');
}
return this.insert(dataArg);
}
/**
* Get the last N entries ordered by timestamp DESC
*/
public async getLastEntries(count: number): Promise<any[]> {
return this.query()
.orderBy('timestamp' as any, 'DESC')
.limit(count)
.toArray();
}
/**
* Get entries newer than a unix timestamp (in milliseconds)
*/
public async getEntriesNewerThan(unixTimestamp: number): Promise<any[]> {
return this.db.clickhouseHttpClient.queryPromise(`
SELECT * FROM ${this.options.database}.${this.options.tableName}
WHERE timestamp > toDateTime(${unixTimestamp / 1000}) FORMAT JSONEachRow
`);
}
/**
* Get entries between two unix timestamps (in milliseconds)
*/
public async getEntriesBetween(unixTimestampStart: number, unixTimestampEnd: number): Promise<any[]> {
return this.db.clickhouseHttpClient.queryPromise(`
SELECT * FROM ${this.options.database}.${this.options.tableName}
WHERE timestamp > toDateTime(${unixTimestampStart / 1000})
AND timestamp < toDateTime(${unixTimestampEnd / 1000}) FORMAT JSONEachRow
`);
}
/**
* Delete entries older than N days
*/
public async deleteOldEntries(days: number): Promise<void> {
await this.db.clickhouseHttpClient.mutatePromise(`
ALTER TABLE ${this.options.database}.${this.options.tableName}
DELETE WHERE timestamp < now() - INTERVAL ${days} DAY
`);
await this.waitForMutations();
}
/**
* Drop the table (backward-compatible alias for drop())
*/
public async delete(): Promise<void> {
return this.drop();
}
/**
* Watch for new entries via polling (backward-compatible wrapper)
*/
public watchNewEntries(): plugins.smartrx.rxjs.Observable<any> {
return this.watch();
}
}