@mastra/clickhouse 1.17.0-alpha.0 → 1.17.0
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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/integrations-databases-clickhouse.md +6 -0
- package/dist/index.cjs +183 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +182 -33
- package/dist/index.js.map +1 -1
- package/dist/storage/db/replication.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts +3 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/deletion-requests.d.ts +28 -0
- package/dist/storage/domains/observability/v-next/deletion-requests.d.ts.map +1 -0
- package/dist/storage/domains/observability/v-next/helpers.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +3 -0
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/tracing.d.ts +22 -7
- package/dist/storage/domains/observability/v-next/tracing.d.ts.map +1 -1
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { MessageList } from "@mastra/core/agent";
|
|
|
6
6
|
import { MastraBase } from "@mastra/core/base";
|
|
7
7
|
import { parseFieldKey } from "@mastra/core/utils";
|
|
8
8
|
import { coreFeatures } from "@mastra/core/features";
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
9
10
|
import { saveScorePayloadSchema } from "@mastra/core/evals";
|
|
10
11
|
//#region src/storage/db/replication.ts
|
|
11
12
|
const DEFAULT_ZOOKEEPER_PATH = "/clickhouse/tables/{shard}/{database}/{table}";
|
|
@@ -71,12 +72,22 @@ function getEngineNameAndArgs(engine) {
|
|
|
71
72
|
}
|
|
72
73
|
function hasBalancedParens(s) {
|
|
73
74
|
let depth = 0;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (
|
|
75
|
+
let quote;
|
|
76
|
+
for (let i = 0; i < s.length; i++) {
|
|
77
|
+
const c = s[i];
|
|
78
|
+
if (quote) {
|
|
79
|
+
if (c === "\\") i++;
|
|
80
|
+
else if (c === quote) quote = void 0;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (c === "`" || c === "\"" || c === "'") quote = c;
|
|
84
|
+
else if (c === "(") depth++;
|
|
85
|
+
else if (c === ")") {
|
|
86
|
+
depth--;
|
|
87
|
+
if (depth < 0) return false;
|
|
88
|
+
}
|
|
78
89
|
}
|
|
79
|
-
return depth === 0;
|
|
90
|
+
return depth === 0 && quote === void 0;
|
|
80
91
|
}
|
|
81
92
|
function buildReplicatedTableEngine(engine, replication) {
|
|
82
93
|
if (!replication) return engine;
|
|
@@ -148,20 +159,51 @@ function addOnClusterToDDL(sql, replication) {
|
|
|
148
159
|
return out;
|
|
149
160
|
}
|
|
150
161
|
function rewriteEngineClauses(sql, replication) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
const enginePattern = /ENGINE\s*=\s*(\w+)/gi;
|
|
163
|
+
let result = "";
|
|
164
|
+
let consumedUntil = 0;
|
|
165
|
+
for (let match = enginePattern.exec(sql); match; match = enginePattern.exec(sql)) {
|
|
166
|
+
const engineName = match[1];
|
|
167
|
+
if (!engineName) continue;
|
|
168
|
+
let engineEnd = enginePattern.lastIndex;
|
|
169
|
+
let argsStart = engineEnd;
|
|
170
|
+
while (/\s/.test(sql[argsStart] ?? "")) argsStart++;
|
|
171
|
+
let engine = engineName;
|
|
172
|
+
if (sql[argsStart] === "(") {
|
|
173
|
+
let depth = 0;
|
|
174
|
+
let closingParenEnd;
|
|
175
|
+
let quote;
|
|
176
|
+
for (let i = argsStart; i < sql.length; i++) {
|
|
177
|
+
const char = sql[i];
|
|
178
|
+
if (quote) {
|
|
179
|
+
if (char === "\\") i++;
|
|
180
|
+
else if (char === quote) quote = void 0;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (char === "`" || char === "\"" || char === "'") quote = char;
|
|
184
|
+
else if (char === "(") depth++;
|
|
185
|
+
else if (char === ")") {
|
|
186
|
+
depth--;
|
|
187
|
+
if (depth === 0) {
|
|
188
|
+
closingParenEnd = i + 1;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
161
192
|
}
|
|
193
|
+
if (closingParenEnd === void 0) {
|
|
194
|
+
result += sql.slice(consumedUntil, enginePattern.lastIndex);
|
|
195
|
+
consumedUntil = enginePattern.lastIndex;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
engineEnd = closingParenEnd;
|
|
199
|
+
engine = `${engineName}${sql.slice(argsStart, engineEnd)}`;
|
|
162
200
|
}
|
|
163
|
-
|
|
164
|
-
|
|
201
|
+
result += sql.slice(consumedUntil, match.index);
|
|
202
|
+
result += `ENGINE = ${buildReplicatedTableEngine(engine, replication)}`;
|
|
203
|
+
consumedUntil = engineEnd;
|
|
204
|
+
enginePattern.lastIndex = engineEnd;
|
|
205
|
+
}
|
|
206
|
+
return result + sql.slice(consumedUntil);
|
|
165
207
|
}
|
|
166
208
|
function applyReplicationToDDL(sql, replication) {
|
|
167
209
|
return addOnClusterToDDL(replication ? rewriteEngineClauses(sql, replication) : sql, replication);
|
|
@@ -2478,6 +2520,7 @@ var ObservabilityStorageClickhouse = class extends ObservabilityStorage {
|
|
|
2478
2520
|
}
|
|
2479
2521
|
}
|
|
2480
2522
|
async batchDeleteTraces(args) {
|
|
2523
|
+
this.assertUnscopedBatchDeleteTraces(args);
|
|
2481
2524
|
try {
|
|
2482
2525
|
if (args.traceIds.length === 0) return;
|
|
2483
2526
|
await this.client.command({
|
|
@@ -2504,6 +2547,7 @@ const TABLE_METRIC_EVENTS = "mastra_metric_events";
|
|
|
2504
2547
|
const TABLE_LOG_EVENTS = "mastra_log_events";
|
|
2505
2548
|
const TABLE_SCORE_EVENTS = "mastra_score_events";
|
|
2506
2549
|
const TABLE_FEEDBACK_EVENTS = "mastra_feedback_events";
|
|
2550
|
+
const TABLE_DELETION_REQUESTS = "mastra_deletion_requests";
|
|
2507
2551
|
const TABLE_METRIC_EVENTS_DELTA = "mastra_metric_events_delta";
|
|
2508
2552
|
const TABLE_LOG_EVENTS_DELTA = "mastra_log_events_delta";
|
|
2509
2553
|
const TABLE_SCORE_EVENTS_DELTA = "mastra_score_events_delta";
|
|
@@ -3199,6 +3243,23 @@ PARTITION BY toDate(timestamp)
|
|
|
3199
3243
|
ORDER BY (traceId, timestamp, feedbackId)
|
|
3200
3244
|
SETTINGS allow_nullable_key = 1
|
|
3201
3245
|
`;
|
|
3246
|
+
const DELETION_REQUESTS_DDL = `
|
|
3247
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_DELETION_REQUESTS} (
|
|
3248
|
+
requestId String,
|
|
3249
|
+
organizationId String DEFAULT '',
|
|
3250
|
+
resourceId String DEFAULT '',
|
|
3251
|
+
signal LowCardinality(String),
|
|
3252
|
+
predicateType LowCardinality(String),
|
|
3253
|
+
predicateValues Array(String),
|
|
3254
|
+
requestedAt DateTime64(3),
|
|
3255
|
+
requestedBy String DEFAULT '',
|
|
3256
|
+
lastAppliedAt DateTime64(3) DEFAULT 0,
|
|
3257
|
+
purgeVerifiedAt DateTime64(3) DEFAULT 0,
|
|
3258
|
+
updatedAt DateTime64(3)
|
|
3259
|
+
)
|
|
3260
|
+
ENGINE = ReplacingMergeTree(updatedAt)
|
|
3261
|
+
ORDER BY (organizationId, resourceId, requestId)
|
|
3262
|
+
`;
|
|
3202
3263
|
function buildFeedbackEventsDeltaDDL() {
|
|
3203
3264
|
return `
|
|
3204
3265
|
CREATE TABLE IF NOT EXISTS ${TABLE_FEEDBACK_EVENTS_DELTA} (
|
|
@@ -3348,6 +3409,7 @@ const BASE_TABLE_DDL = [
|
|
|
3348
3409
|
LOG_EVENTS_DDL,
|
|
3349
3410
|
SCORE_EVENTS_DDL,
|
|
3350
3411
|
FEEDBACK_EVENTS_DDL,
|
|
3412
|
+
DELETION_REQUESTS_DDL,
|
|
3351
3413
|
DISCOVERY_VALUES_DDL,
|
|
3352
3414
|
DISCOVERY_PAIRS_DDL
|
|
3353
3415
|
];
|
|
@@ -3432,6 +3494,7 @@ const ALL_TABLE_NAMES = [
|
|
|
3432
3494
|
TABLE_LOG_EVENTS,
|
|
3433
3495
|
TABLE_SCORE_EVENTS,
|
|
3434
3496
|
TABLE_FEEDBACK_EVENTS,
|
|
3497
|
+
TABLE_DELETION_REQUESTS,
|
|
3435
3498
|
TABLE_METRIC_EVENTS_DELTA,
|
|
3436
3499
|
TABLE_LOG_EVENTS_DELTA,
|
|
3437
3500
|
TABLE_SCORE_EVENTS_DELTA,
|
|
@@ -4089,6 +4152,35 @@ function feedbackRecordToRow(feedback) {
|
|
|
4089
4152
|
};
|
|
4090
4153
|
}
|
|
4091
4154
|
//#endregion
|
|
4155
|
+
//#region src/storage/domains/observability/v-next/deletion-requests.ts
|
|
4156
|
+
const EPOCH = "1970-01-01T00:00:00.000Z";
|
|
4157
|
+
async function recordDeletionRequest(client, args) {
|
|
4158
|
+
const row = {
|
|
4159
|
+
requestId: args.requestId,
|
|
4160
|
+
organizationId: args.organizationId ?? "",
|
|
4161
|
+
resourceId: args.resourceId ?? "",
|
|
4162
|
+
signal: args.signal,
|
|
4163
|
+
predicateType: args.predicateType,
|
|
4164
|
+
predicateValues: args.predicateValues,
|
|
4165
|
+
requestedAt: args.requestedAt,
|
|
4166
|
+
requestedBy: args.requestedBy ?? "",
|
|
4167
|
+
lastAppliedAt: EPOCH,
|
|
4168
|
+
purgeVerifiedAt: EPOCH,
|
|
4169
|
+
updatedAt: args.requestedAt
|
|
4170
|
+
};
|
|
4171
|
+
await client.insert({
|
|
4172
|
+
table: TABLE_DELETION_REQUESTS,
|
|
4173
|
+
values: [row],
|
|
4174
|
+
format: "JSONEachRow",
|
|
4175
|
+
clickhouse_settings: isReplicationConfigured(args.replication) ? {
|
|
4176
|
+
...CH_INSERT_SETTINGS,
|
|
4177
|
+
insert_quorum: "auto",
|
|
4178
|
+
insert_quorum_parallel: 1
|
|
4179
|
+
} : CH_INSERT_SETTINGS
|
|
4180
|
+
});
|
|
4181
|
+
return row;
|
|
4182
|
+
}
|
|
4183
|
+
//#endregion
|
|
4092
4184
|
//#region src/storage/domains/observability/v-next/discovery.ts
|
|
4093
4185
|
async function queryJson$3(client, query, params = {}) {
|
|
4094
4186
|
return await (await client.query({
|
|
@@ -6591,6 +6683,17 @@ function buildTraceCursor(row) {
|
|
|
6591
6683
|
}
|
|
6592
6684
|
//#endregion
|
|
6593
6685
|
//#region src/storage/domains/observability/v-next/tracing.ts
|
|
6686
|
+
/**
|
|
6687
|
+
* Tracing operations for ClickHouse v-next observability.
|
|
6688
|
+
*
|
|
6689
|
+
* Owns: batchCreateSpans, getSpan, getSpans, getTrace, getTraceLight,
|
|
6690
|
+
* listBranches, batchDeleteTraces, dangerouslyClearSpanEvents.
|
|
6691
|
+
* Delegates to trace-roots.ts: listTraces, getRootSpan.
|
|
6692
|
+
*
|
|
6693
|
+
* `listBranches` reads from the MV-fed `mastra_trace_branches` table (one row
|
|
6694
|
+
* per branch anchor span). It lives here -- alongside the other read paths
|
|
6695
|
+
* over the trace data -- since branches are conceptually a subset of traces.
|
|
6696
|
+
*/
|
|
6594
6697
|
const BRANCH_SPAN_TYPE_SQL_LIST = BRANCH_SPAN_TYPES.map((t) => `'${t}'`).join(", ");
|
|
6595
6698
|
/** Insert a single completed span. */
|
|
6596
6699
|
async function createSpan(client, args) {
|
|
@@ -6730,16 +6833,40 @@ async function getTraceLight(client, args) {
|
|
|
6730
6833
|
};
|
|
6731
6834
|
}
|
|
6732
6835
|
/**
|
|
6733
|
-
* Delete traces by traceId
|
|
6734
|
-
*
|
|
6836
|
+
* Delete traces by traceId, cascading to trace-derived tables and trace-linked
|
|
6837
|
+
* signal events (metrics, logs, scores, feedback). Signal rows with a NULL
|
|
6838
|
+
* traceId are never affected.
|
|
6839
|
+
*
|
|
6840
|
+
* On the tracing tables, rows are targeted by tracing identity: traceId +
|
|
6841
|
+
* dedupeKey (which starts with traceId). The dedupeKey condition is redundant
|
|
6842
|
+
* for correctness (dedupeKey = traceId:spanId) but satisfies the design-doc
|
|
6843
|
+
* requirement that trace deletes reference dedupeKey and helps the engine
|
|
6844
|
+
* narrow within the sorted ORDER BY key. Signal tables key on their own event
|
|
6845
|
+
* ids, so they are targeted by traceId alone.
|
|
6846
|
+
*
|
|
6847
|
+
* `trace_branches` must be deleted explicitly: its MV fires on insert only,
|
|
6848
|
+
* so span deletes never propagate to it. Delta tables self-expire via TTL and
|
|
6849
|
+
* discovery tables self-heal, so neither needs explicit deletes.
|
|
6735
6850
|
*
|
|
6736
|
-
*
|
|
6737
|
-
*
|
|
6738
|
-
*
|
|
6739
|
-
*
|
|
6851
|
+
* Records the predicate before using lightweight DELETE FROM on every table.
|
|
6852
|
+
* Lightweight deletes hide rows through ClickHouse's delete mask; physical
|
|
6853
|
+
* removal depends on the deployment's configured retention and merge policy.
|
|
6854
|
+
*
|
|
6855
|
+
* When the optional tenant scope (`organizationId` / `resourceId`) is set,
|
|
6856
|
+
* every DELETE additionally requires the row's tenant columns to match.
|
|
6740
6857
|
*/
|
|
6741
|
-
async function batchDeleteTraces(client, args) {
|
|
6858
|
+
async function batchDeleteTraces(client, args, replication) {
|
|
6742
6859
|
if (args.traceIds.length === 0) return;
|
|
6860
|
+
await recordDeletionRequest(client, {
|
|
6861
|
+
requestId: randomUUID(),
|
|
6862
|
+
organizationId: args.organizationId,
|
|
6863
|
+
resourceId: args.resourceId,
|
|
6864
|
+
signal: "traces",
|
|
6865
|
+
predicateType: "traceIds",
|
|
6866
|
+
predicateValues: [...args.traceIds],
|
|
6867
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6868
|
+
replication
|
|
6869
|
+
});
|
|
6743
6870
|
const params = {};
|
|
6744
6871
|
const traceInPlaceholders = [];
|
|
6745
6872
|
const dedupeOrParts = [];
|
|
@@ -6753,13 +6880,35 @@ async function batchDeleteTraces(client, args) {
|
|
|
6753
6880
|
}
|
|
6754
6881
|
const traceInList = traceInPlaceholders.join(", ");
|
|
6755
6882
|
const dedupeCondition = dedupeOrParts.length === 1 ? dedupeOrParts[0] : `(${dedupeOrParts.join(" OR ")})`;
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6883
|
+
let scopeCondition = "";
|
|
6884
|
+
if (args.organizationId !== void 0) {
|
|
6885
|
+
params.scope_org = args.organizationId;
|
|
6886
|
+
scopeCondition += ` AND organizationId = {scope_org:String}`;
|
|
6887
|
+
}
|
|
6888
|
+
if (args.resourceId !== void 0) {
|
|
6889
|
+
params.scope_res = args.resourceId;
|
|
6890
|
+
scopeCondition += ` AND resourceId = {scope_res:String}`;
|
|
6891
|
+
}
|
|
6892
|
+
const tracingTables = [
|
|
6893
|
+
TABLE_SPAN_EVENTS,
|
|
6894
|
+
TABLE_TRACE_ROOTS,
|
|
6895
|
+
TABLE_TRACE_BRANCHES
|
|
6896
|
+
];
|
|
6897
|
+
const signalTables = [
|
|
6898
|
+
TABLE_METRIC_EVENTS,
|
|
6899
|
+
TABLE_LOG_EVENTS,
|
|
6900
|
+
TABLE_SCORE_EVENTS,
|
|
6901
|
+
TABLE_FEEDBACK_EVENTS
|
|
6902
|
+
];
|
|
6903
|
+
await Promise.all([...tracingTables.map((table) => client.command({
|
|
6904
|
+
query: `DELETE FROM ${table} WHERE traceId IN (${traceInList}) AND ${dedupeCondition}${scopeCondition}`,
|
|
6905
|
+
query_params: params,
|
|
6906
|
+
clickhouse_settings: { lightweight_deletes_sync: "2" }
|
|
6907
|
+
})), ...signalTables.map((table) => client.command({
|
|
6908
|
+
query: `DELETE FROM ${table} WHERE traceId IN (${traceInList})${scopeCondition}`,
|
|
6909
|
+
query_params: params,
|
|
6910
|
+
clickhouse_settings: { lightweight_deletes_sync: "2" }
|
|
6911
|
+
}))]);
|
|
6763
6912
|
}
|
|
6764
6913
|
/**
|
|
6765
6914
|
* List trace branches with optional filtering, pagination, and ordering.
|
|
@@ -7962,7 +8111,7 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
7962
8111
|
}
|
|
7963
8112
|
async batchDeleteTraces(args) {
|
|
7964
8113
|
try {
|
|
7965
|
-
await batchDeleteTraces(this.#client, args);
|
|
8114
|
+
await batchDeleteTraces(this.#client, args, this.#replication);
|
|
7966
8115
|
} catch (error) {
|
|
7967
8116
|
if (error instanceof MastraError) throw error;
|
|
7968
8117
|
throw new MastraError({
|
|
@@ -8832,6 +8981,6 @@ var ClickhouseStoreVNext = class extends ClickhouseStore {
|
|
|
8832
8981
|
}
|
|
8833
8982
|
};
|
|
8834
8983
|
//#endregion
|
|
8835
|
-
export { COLUMN_TYPES, ClickhouseStore, ClickhouseStoreVNext, MemoryStorageClickhouse, ObservabilityStorageClickhouse, ObservabilityStorageClickhouseVNext, ScoresStorageClickhouse, TABLE_ENGINES, WorkflowsStorageClickhouse };
|
|
8984
|
+
export { COLUMN_TYPES, ClickhouseStore, ClickhouseStoreVNext, MemoryStorageClickhouse, ObservabilityStorageClickhouse, ObservabilityStorageClickhouseVNext, ScoresStorageClickhouse, TABLE_DELETION_REQUESTS, TABLE_ENGINES, WorkflowsStorageClickhouse, recordDeletionRequest };
|
|
8836
8985
|
|
|
8837
8986
|
//# sourceMappingURL=index.js.map
|