@mastra/clickhouse 1.7.1-alpha.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-clickhouse.md +8 -8
- package/dist/docs/references/reference-storage-composite.md +1 -1
- package/dist/index.cjs +131 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +131 -36
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts +41 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -3422,44 +3422,56 @@ var ALL_TABLE_DDL = [
|
|
|
3422
3422
|
];
|
|
3423
3423
|
var ALL_MV_DDL = [TRACE_ROOTS_MV_DDL, TRACE_BRANCHES_MV_DDL];
|
|
3424
3424
|
var DISCOVERY_MV_DDL = [DISCOVERY_VALUES_MV_DDL, DISCOVERY_PAIRS_MV_DDL];
|
|
3425
|
+
var addColumn = (table, name, type) => ({
|
|
3426
|
+
kind: "column",
|
|
3427
|
+
table,
|
|
3428
|
+
name,
|
|
3429
|
+
sql: `ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS ${name} ${type}`
|
|
3430
|
+
});
|
|
3431
|
+
var addBloomIndex = (table, name, column) => ({
|
|
3432
|
+
kind: "index",
|
|
3433
|
+
table,
|
|
3434
|
+
name,
|
|
3435
|
+
sql: `ALTER TABLE ${table} ADD INDEX IF NOT EXISTS ${name} ${column} TYPE bloom_filter(0.01) GRANULARITY 2`
|
|
3436
|
+
});
|
|
3425
3437
|
var ALL_MIGRATIONS = [
|
|
3426
3438
|
// Span events
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3439
|
+
addColumn(TABLE_SPAN_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3440
|
+
addColumn(TABLE_SPAN_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3441
|
+
addColumn(TABLE_SPAN_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3430
3442
|
// Trace roots
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3443
|
+
addColumn(TABLE_TRACE_ROOTS, "entityVersionId", "Nullable(String)"),
|
|
3444
|
+
addColumn(TABLE_TRACE_ROOTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3445
|
+
addColumn(TABLE_TRACE_ROOTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3434
3446
|
// Metrics
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3447
|
+
addColumn(TABLE_METRIC_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3448
|
+
addColumn(TABLE_METRIC_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3449
|
+
addColumn(TABLE_METRIC_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3438
3450
|
// Logs
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3451
|
+
addColumn(TABLE_LOG_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3452
|
+
addColumn(TABLE_LOG_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3453
|
+
addColumn(TABLE_LOG_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3442
3454
|
// Scores
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3455
|
+
addColumn(TABLE_SCORE_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3456
|
+
addColumn(TABLE_SCORE_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3457
|
+
addColumn(TABLE_SCORE_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3446
3458
|
// Feedback
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3459
|
+
addColumn(TABLE_FEEDBACK_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3460
|
+
addColumn(TABLE_FEEDBACK_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3461
|
+
addColumn(TABLE_FEEDBACK_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3450
3462
|
// Metric skip indexes — additive, instant DDL. Existing parts keep no index
|
|
3451
3463
|
// until merged or `MATERIALIZE INDEX` is run; new parts are bloom-filtered
|
|
3452
3464
|
// immediately. With normal retention turning over the table, the index
|
|
3453
3465
|
// converges to full coverage without an explicit backfill.
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3466
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_traceId", "traceId"),
|
|
3467
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_threadId", "threadId"),
|
|
3468
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_resourceId", "resourceId"),
|
|
3469
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_userId", "userId"),
|
|
3470
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_organizationId", "organizationId"),
|
|
3471
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_experimentId", "experimentId"),
|
|
3472
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_runId", "runId"),
|
|
3473
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_sessionId", "sessionId"),
|
|
3474
|
+
addBloomIndex(TABLE_METRIC_EVENTS, "idx_requestId", "requestId")
|
|
3463
3475
|
];
|
|
3464
3476
|
var ALL_TABLE_NAMES = [
|
|
3465
3477
|
TABLE_SPAN_EVENTS,
|
|
@@ -3488,8 +3500,8 @@ var SIGNAL_TO_TABLES = {
|
|
|
3488
3500
|
scores: [TABLE_SCORE_EVENTS],
|
|
3489
3501
|
feedback: [TABLE_FEEDBACK_EVENTS]
|
|
3490
3502
|
};
|
|
3491
|
-
function
|
|
3492
|
-
const
|
|
3503
|
+
function buildRetentionEntries(retention) {
|
|
3504
|
+
const entries = [];
|
|
3493
3505
|
for (const [signal, days] of Object.entries(retention)) {
|
|
3494
3506
|
const safeDays = Math.floor(Number(days));
|
|
3495
3507
|
if (!Number.isFinite(safeDays) || safeDays <= 0) continue;
|
|
@@ -3498,10 +3510,24 @@ function buildRetentionDDL(retention) {
|
|
|
3498
3510
|
for (const table of tables) {
|
|
3499
3511
|
const col = SIGNAL_TTL_COLUMNS[table];
|
|
3500
3512
|
if (!col) continue;
|
|
3501
|
-
|
|
3513
|
+
entries.push({
|
|
3514
|
+
table,
|
|
3515
|
+
column: col,
|
|
3516
|
+
days: safeDays,
|
|
3517
|
+
sql: `ALTER TABLE ${table} MODIFY TTL ${col} + INTERVAL ${safeDays} DAY`
|
|
3518
|
+
});
|
|
3502
3519
|
}
|
|
3503
3520
|
}
|
|
3504
|
-
return
|
|
3521
|
+
return entries;
|
|
3522
|
+
}
|
|
3523
|
+
function parseTtlExpression(expr) {
|
|
3524
|
+
const match = expr.match(/TTL\s+(?:`([^`]+)`|(\w+))\s*\+\s*(?:toIntervalDay\((\d+)\)|INTERVAL\s+(\d+)\s+DAY)/i);
|
|
3525
|
+
if (!match) return null;
|
|
3526
|
+
const column = match[1] ?? match[2];
|
|
3527
|
+
if (!column) return null;
|
|
3528
|
+
const days = Number(match[3] ?? match[4]);
|
|
3529
|
+
if (!Number.isFinite(days)) return null;
|
|
3530
|
+
return { column, days };
|
|
3505
3531
|
}
|
|
3506
3532
|
var CH_SETTINGS = {
|
|
3507
3533
|
date_time_input_format: "best_effort",
|
|
@@ -5962,6 +5988,74 @@ time for large databases. Please ensure you have a backup before proceeding.
|
|
|
5962
5988
|
===========================================================================
|
|
5963
5989
|
`;
|
|
5964
5990
|
}
|
|
5991
|
+
async function filterAppliedMigrations(client, migrations) {
|
|
5992
|
+
if (migrations.length === 0) return migrations;
|
|
5993
|
+
const tables = [...new Set(migrations.map((m) => m.table))];
|
|
5994
|
+
let existingColumns;
|
|
5995
|
+
let existingIndices;
|
|
5996
|
+
try {
|
|
5997
|
+
[existingColumns, existingIndices] = await Promise.all([
|
|
5998
|
+
queryNamesByTable(
|
|
5999
|
+
client,
|
|
6000
|
+
`SELECT table, name FROM system.columns WHERE database = currentDatabase() AND table IN ({tables:Array(String)})`,
|
|
6001
|
+
tables
|
|
6002
|
+
),
|
|
6003
|
+
queryNamesByTable(
|
|
6004
|
+
client,
|
|
6005
|
+
`SELECT table, name FROM system.data_skipping_indices WHERE database = currentDatabase() AND table IN ({tables:Array(String)})`,
|
|
6006
|
+
tables
|
|
6007
|
+
)
|
|
6008
|
+
]);
|
|
6009
|
+
} catch {
|
|
6010
|
+
return migrations;
|
|
6011
|
+
}
|
|
6012
|
+
return migrations.filter((m) => {
|
|
6013
|
+
const present = m.kind === "column" ? existingColumns.get(m.table) : existingIndices.get(m.table);
|
|
6014
|
+
if (!present) return true;
|
|
6015
|
+
return !present.has(m.name);
|
|
6016
|
+
});
|
|
6017
|
+
}
|
|
6018
|
+
async function filterAppliedRetention(client, entries) {
|
|
6019
|
+
if (entries.length === 0) return entries;
|
|
6020
|
+
const tables = [...new Set(entries.map((e) => e.table))];
|
|
6021
|
+
let createQueries;
|
|
6022
|
+
try {
|
|
6023
|
+
const result = await client.query({
|
|
6024
|
+
query: `SELECT name, create_table_query FROM system.tables WHERE database = currentDatabase() AND name IN ({tables:Array(String)})`,
|
|
6025
|
+
query_params: { tables },
|
|
6026
|
+
format: "JSONEachRow"
|
|
6027
|
+
});
|
|
6028
|
+
const rows = await result.json();
|
|
6029
|
+
createQueries = new Map(rows.map((r) => [r.name, r.create_table_query ?? ""]));
|
|
6030
|
+
} catch {
|
|
6031
|
+
return entries;
|
|
6032
|
+
}
|
|
6033
|
+
return entries.filter((e) => {
|
|
6034
|
+
const createQuery = createQueries.get(e.table);
|
|
6035
|
+
if (!createQuery) return true;
|
|
6036
|
+
const current = parseTtlExpression(createQuery);
|
|
6037
|
+
if (!current) return true;
|
|
6038
|
+
return current.column !== e.column || current.days !== e.days;
|
|
6039
|
+
});
|
|
6040
|
+
}
|
|
6041
|
+
async function queryNamesByTable(client, query, tables) {
|
|
6042
|
+
const result = await client.query({
|
|
6043
|
+
query,
|
|
6044
|
+
query_params: { tables },
|
|
6045
|
+
format: "JSONEachRow"
|
|
6046
|
+
});
|
|
6047
|
+
const rows = await result.json();
|
|
6048
|
+
const out = /* @__PURE__ */ new Map();
|
|
6049
|
+
for (const row of rows) {
|
|
6050
|
+
let set = out.get(row.table);
|
|
6051
|
+
if (!set) {
|
|
6052
|
+
set = /* @__PURE__ */ new Set();
|
|
6053
|
+
out.set(row.table, set);
|
|
6054
|
+
}
|
|
6055
|
+
set.add(row.name);
|
|
6056
|
+
}
|
|
6057
|
+
return out;
|
|
6058
|
+
}
|
|
5965
6059
|
var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
5966
6060
|
#client;
|
|
5967
6061
|
#retention;
|
|
@@ -5991,13 +6085,14 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
5991
6085
|
for (const ddl of [...ALL_TABLE_DDL, ...ALL_MV_DDL]) {
|
|
5992
6086
|
await this.#client.command({ query: ddl });
|
|
5993
6087
|
}
|
|
5994
|
-
|
|
5995
|
-
|
|
6088
|
+
const pendingMigrations = await filterAppliedMigrations(this.#client, ALL_MIGRATIONS);
|
|
6089
|
+
for (const migration of pendingMigrations) {
|
|
6090
|
+
await this.#client.command({ query: migration.sql });
|
|
5996
6091
|
}
|
|
5997
6092
|
if (this.#retention) {
|
|
5998
|
-
const
|
|
5999
|
-
for (const
|
|
6000
|
-
await this.#client.command({ query:
|
|
6093
|
+
const pendingRetention = await filterAppliedRetention(this.#client, buildRetentionEntries(this.#retention));
|
|
6094
|
+
for (const entry of pendingRetention) {
|
|
6095
|
+
await this.#client.command({ query: entry.sql });
|
|
6001
6096
|
}
|
|
6002
6097
|
}
|
|
6003
6098
|
} catch (error) {
|