@mastra/clickhouse 1.9.0-alpha.0 → 1.9.0-alpha.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @mastra/clickhouse
2
2
 
3
+ ## 1.9.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed duplicate entries in the ClickHouse v-next observability discovery endpoints — tags, services, environments, entities, metric names, and metric labels now return each value once. Existing deployments are reconciled automatically on next startup; no manual migration required. ([#16798](https://github.com/mastra-ai/mastra/pull/16798))
8
+
3
9
  ## 1.9.0-alpha.0
4
10
 
5
11
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-clickhouse
3
3
  description: Documentation for @mastra/clickhouse. Use when working with @mastra/clickhouse APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/clickhouse"
6
- version: "1.9.0-alpha.0"
6
+ version: "1.9.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.9.0-alpha.0",
2
+ "version": "1.9.0-alpha.1",
3
3
  "package": "@mastra/clickhouse",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -3611,7 +3611,7 @@ CREATE TABLE IF NOT EXISTS ${TABLE_DISCOVERY_VALUES} (
3611
3611
  key1 String,
3612
3612
  value String
3613
3613
  )
3614
- ENGINE = MergeTree
3614
+ ENGINE = ReplacingMergeTree
3615
3615
  ORDER BY (kind, key1, value)
3616
3616
  `;
3617
3617
  var DISCOVERY_PAIRS_DDL = `
@@ -3621,7 +3621,7 @@ CREATE TABLE IF NOT EXISTS ${TABLE_DISCOVERY_PAIRS} (
3621
3621
  key2 String,
3622
3622
  value String
3623
3623
  )
3624
- ENGINE = MergeTree
3624
+ ENGINE = ReplacingMergeTree
3625
3625
  ORDER BY (kind, key1, key2, value)
3626
3626
  `;
3627
3627
  var SIGNAL_TABLES = [TABLE_SPAN_EVENTS, TABLE_METRIC_EVENTS, TABLE_LOG_EVENTS];
@@ -4391,7 +4391,7 @@ async function queryJson(client, query, params = {}) {
4391
4391
  async function getEntityTypes(client, _args) {
4392
4392
  const rows = await queryJson(
4393
4393
  client,
4394
- `SELECT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'entityType' ORDER BY value`
4394
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'entityType' ORDER BY value`
4395
4395
  );
4396
4396
  const validTypes = new Set(Object.values(storage.EntityType));
4397
4397
  const entityTypes = [];
@@ -4411,7 +4411,7 @@ async function getEntityNames(client, args) {
4411
4411
  }
4412
4412
  const rows = await queryJson(
4413
4413
  client,
4414
- `SELECT value FROM ${TABLE_DISCOVERY_PAIRS} WHERE ${conditions.join(" AND ")} ORDER BY value`,
4414
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_PAIRS} WHERE ${conditions.join(" AND ")} ORDER BY value`,
4415
4415
  params
4416
4416
  );
4417
4417
  return { names: rows.map((r) => r.value) };
@@ -4419,14 +4419,14 @@ async function getEntityNames(client, args) {
4419
4419
  async function getServiceNames(client, _args) {
4420
4420
  const rows = await queryJson(
4421
4421
  client,
4422
- `SELECT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'serviceName' ORDER BY value`
4422
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'serviceName' ORDER BY value`
4423
4423
  );
4424
4424
  return { serviceNames: rows.map((r) => r.value) };
4425
4425
  }
4426
4426
  async function getEnvironments(client, _args) {
4427
4427
  const rows = await queryJson(
4428
4428
  client,
4429
- `SELECT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'environment' ORDER BY value`
4429
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'environment' ORDER BY value`
4430
4430
  );
4431
4431
  return { environments: rows.map((r) => r.value) };
4432
4432
  }
@@ -4439,7 +4439,7 @@ async function getTags(client, args) {
4439
4439
  }
4440
4440
  const rows = await queryJson(
4441
4441
  client,
4442
- `SELECT value FROM ${TABLE_DISCOVERY_VALUES} WHERE ${conditions.join(" AND ")} ORDER BY value`,
4442
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_VALUES} WHERE ${conditions.join(" AND ")} ORDER BY value`,
4443
4443
  params
4444
4444
  );
4445
4445
  return { tags: rows.map((r) => r.value) };
@@ -5719,7 +5719,7 @@ async function getMetricNames(client, args) {
5719
5719
  if (args.limit) params.nameLimit = args.limit;
5720
5720
  const rows = await queryJson3(
5721
5721
  client,
5722
- `SELECT value FROM ${TABLE_DISCOVERY_VALUES} WHERE ${conditions.join(" AND ")} ORDER BY value ${limitClause}`,
5722
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_VALUES} WHERE ${conditions.join(" AND ")} ORDER BY value ${limitClause}`,
5723
5723
  params
5724
5724
  );
5725
5725
  return { names: rows.map((r) => r.value) };
@@ -5727,7 +5727,7 @@ async function getMetricNames(client, args) {
5727
5727
  async function getMetricLabelKeys(client, args) {
5728
5728
  const rows = await queryJson3(
5729
5729
  client,
5730
- `SELECT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'metricLabelKey' AND key1 = {metricName:String} ORDER BY value`,
5730
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_VALUES} WHERE kind = 'metricLabelKey' AND key1 = {metricName:String} ORDER BY value`,
5731
5731
  { metricName: args.metricName }
5732
5732
  );
5733
5733
  return { keys: rows.map((r) => r.value) };
@@ -5746,7 +5746,7 @@ async function getMetricLabelValues(client, args) {
5746
5746
  if (args.limit) params.valLimit = args.limit;
5747
5747
  const rows = await queryJson3(
5748
5748
  client,
5749
- `SELECT value FROM ${TABLE_DISCOVERY_PAIRS} WHERE ${conditions.join(" AND ")} ORDER BY value ${limitClause}`,
5749
+ `SELECT DISTINCT value FROM ${TABLE_DISCOVERY_PAIRS} WHERE ${conditions.join(" AND ")} ORDER BY value ${limitClause}`,
5750
5750
  params
5751
5751
  );
5752
5752
  return { values: rows.map((r) => r.value) };
@@ -6981,6 +6981,30 @@ async function filterAppliedRetention(client, entries) {
6981
6981
  return current.column !== e.column || current.days !== e.days;
6982
6982
  });
6983
6983
  }
6984
+ async function reconcileDiscoveryTables(client) {
6985
+ let engines;
6986
+ try {
6987
+ const result = await client.query({
6988
+ query: `SELECT name, engine FROM system.tables WHERE database = currentDatabase() AND name IN ({tables:Array(String)})`,
6989
+ query_params: { tables: [TABLE_DISCOVERY_VALUES, TABLE_DISCOVERY_PAIRS] },
6990
+ format: "JSONEachRow"
6991
+ });
6992
+ const rows = await result.json();
6993
+ engines = new Map(rows.map((r) => [r.name, r.engine]));
6994
+ } catch {
6995
+ return;
6996
+ }
6997
+ const targets = [
6998
+ { table: TABLE_DISCOVERY_VALUES, mv: MV_DISCOVERY_VALUES },
6999
+ { table: TABLE_DISCOVERY_PAIRS, mv: MV_DISCOVERY_PAIRS }
7000
+ ];
7001
+ for (const { table, mv } of targets) {
7002
+ const engine = engines.get(table);
7003
+ if (!engine || isReplacingMergeTreeEngine(engine)) continue;
7004
+ await client.command({ query: `DROP VIEW IF EXISTS ${mv}` });
7005
+ await client.command({ query: `DROP TABLE IF EXISTS ${table}` });
7006
+ }
7007
+ }
6984
7008
  async function queryNamesByTable(client, query, tables) {
6985
7009
  const result = await client.query({
6986
7010
  query,
@@ -7096,6 +7120,7 @@ var ObservabilityStorageClickhouseVNext = class extends storage.ObservabilitySto
7096
7120
  } else {
7097
7121
  this.#deltaCursorStrategy = await detectDeltaCursorStrategy(this.#client, void 0, existingStrategy);
7098
7122
  }
7123
+ await reconcileDiscoveryTables(this.#client);
7099
7124
  const coreDdl = this.#deltaCursorStrategy === null ? [...BASE_TABLE_DDL, ...BASE_MV_DDL] : [...buildAllTableDDL(), ...buildAllMvDDL(this.#deltaCursorStrategy)];
7100
7125
  for (const ddl of coreDdl) {
7101
7126
  await this.#client.command({ query: ddl });