@mastra/clickhouse 1.21.0 → 1.21.1-alpha.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 +2 -10
- package/dist/index.cjs +52 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +52 -70
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts +0 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/feedback.d.ts +15 -1
- package/dist/storage/domains/observability/v-next/feedback.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/docs/SKILL.md
CHANGED
|
@@ -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.21.0"
|
|
6
|
+
version: "1.21.1-alpha.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -93,9 +93,7 @@ Lightweight deletion is a hide-only operation that marks rows with ClickHouse's
|
|
|
93
93
|
|
|
94
94
|
When all five observability signals have finite retention, Mastra also applies a TTL to deletion requests so they outlive the signal rows they protect. If any signal is unbounded, deletion requests remain unbounded. See [storage retention](https://mastra.ai/reference/storage/retention) for how the deletion-request TTL is calculated.
|
|
95
95
|
|
|
96
|
-
Feedback review-status updates
|
|
97
|
-
|
|
98
|
-
The status mutation and the delta insert are separate operations. If the delta insert fails, the API returns an error even though the status may have changed, and continued delta polling doesn't recover that notification: later polls from the same cursor never return it, and starting delta mode without a cursor subscribes at the current head. To recover, retry the review update after resolving the error, or reread the feedback with a regular list query.
|
|
96
|
+
Feedback review-status updates read the current row and insert a replacement, so they need `SELECT` and `INSERT` rather than `ALTER UPDATE`, and the insert materialized view publishes each update to delta polling. An update that re-runs a delete also needs the delete permissions listed in [initialization](#initialization). A review update that lands while a delete of the same feedback is in progress re-runs that delete and returns not found, so it can't recreate deleted feedback. A failed delete doesn't block review updates, but the next update retries it: if the retry succeeds, the update returns not found; if it fails again, the new status is saved but the update returns the delete's error. If a network error or a lagging replica lets a review row outlive a successful delete, the next review update of that feedback deletes it again and returns not found.
|
|
99
97
|
|
|
100
98
|
### Observability with the legacy domain
|
|
101
99
|
|
|
@@ -372,16 +370,10 @@ const observability = new ObservabilityStorageClickhouseVNext({
|
|
|
372
370
|
await observability.init()
|
|
373
371
|
```
|
|
374
372
|
|
|
375
|
-
In CI/CD pipelines, set `disableInit: true` on `ClickhouseStore` and run `init()` from a deployment step that uses elevated credentials. Runtime application credentials
|
|
373
|
+
In CI/CD pipelines, set `disableInit: true` on `ClickhouseStore` and run `init()` from a deployment step that uses elevated credentials. Runtime application credentials need:
|
|
376
374
|
|
|
377
375
|
- `SELECT` and `INSERT` on the Mastra tables.
|
|
378
376
|
- `ALTER DELETE` on the observability tables you delete from. On ClickHouse 26.6 and earlier, lightweight deletes also require `ALTER UPDATE` on those tables; ClickHouse 26.7 removed that requirement.
|
|
379
|
-
- For feedback review updates, `ALTER UPDATE(reviewStatus)` on `mastra_feedback_events` and `INSERT` on `mastra_feedback_events_delta`.
|
|
380
|
-
|
|
381
|
-
```sql
|
|
382
|
-
GRANT ALTER UPDATE(reviewStatus) ON <database>.mastra_feedback_events TO <runtime_user>;
|
|
383
|
-
GRANT INSERT ON <database>.mastra_feedback_events_delta TO <runtime_user>;
|
|
384
|
-
```
|
|
385
377
|
|
|
386
378
|
## Observability
|
|
387
379
|
|
package/dist/index.cjs
CHANGED
|
@@ -4879,29 +4879,16 @@ function feedbackNotFoundError(feedbackId) {
|
|
|
4879
4879
|
details: { feedbackId }
|
|
4880
4880
|
});
|
|
4881
4881
|
}
|
|
4882
|
-
function feedbackConflictError(feedbackId) {
|
|
4883
|
-
return new _mastra_core_error.MastraError({
|
|
4884
|
-
id: "OBSERVABILITY_UPDATE_FEEDBACK_REVIEW_STATUS_CONFLICT",
|
|
4885
|
-
domain: _mastra_core_error.ErrorDomain.MASTRA_OBSERVABILITY,
|
|
4886
|
-
category: _mastra_core_error.ErrorCategory.USER,
|
|
4887
|
-
text: "Feedback record changed while its review status was being updated; retry the update",
|
|
4888
|
-
details: { feedbackId }
|
|
4889
|
-
});
|
|
4890
|
-
}
|
|
4891
|
-
/** Re-reads before giving up when ingestion keeps superseding the observed row. */
|
|
4892
|
-
const REVIEW_UPDATE_ATTEMPTS = 3;
|
|
4893
4882
|
/**
|
|
4894
|
-
*
|
|
4895
|
-
*
|
|
4896
|
-
*
|
|
4897
|
-
* mis-report a status, never bring deleted feedback back.
|
|
4883
|
+
* Finds a deletion request covering this feedback. With `appliedOnly`, only
|
|
4884
|
+
* requests whose DELETE succeeded count; otherwise pending requests count too,
|
|
4885
|
+
* including a delete that is still running or one that failed.
|
|
4898
4886
|
*/
|
|
4899
|
-
async function hasFeedbackDeletionRequest(client, feedbackId, organizationId, resourceId) {
|
|
4887
|
+
async function hasFeedbackDeletionRequest(client, feedbackId, organizationId, resourceId, { appliedOnly }) {
|
|
4900
4888
|
return (await queryJson$2(client, `SELECT 1 AS found FROM ${TABLE_DELETION_REQUESTS} FINAL
|
|
4901
4889
|
WHERE signal = 'feedback'
|
|
4902
4890
|
AND predicateType = 'itemIds'
|
|
4903
|
-
AND has(predicateValues, {feedbackId:String})
|
|
4904
|
-
AND lastAppliedAt > toDateTime64(0, 3)
|
|
4891
|
+
AND has(predicateValues, {feedbackId:String})${appliedOnly ? "\n AND lastAppliedAt > toDateTime64(0, 3)" : ""}
|
|
4905
4892
|
AND (organizationId = '' OR organizationId = {organizationId:String})
|
|
4906
4893
|
AND (resourceId = '' OR resourceId = {resourceId:String})
|
|
4907
4894
|
LIMIT 1`, {
|
|
@@ -4910,63 +4897,44 @@ async function hasFeedbackDeletionRequest(client, feedbackId, organizationId, re
|
|
|
4910
4897
|
resourceId: resourceId ?? ""
|
|
4911
4898
|
})).length > 0;
|
|
4912
4899
|
}
|
|
4913
|
-
async function updateFeedbackReviewStatus(client, args, strategy = null) {
|
|
4914
|
-
const { feedbackId, reviewStatus } = parseUpdateFeedbackReviewStatusArgs(args);
|
|
4915
|
-
for (let attempt = 1;; attempt++) {
|
|
4916
|
-
const updated = await applyReviewStatus(client, feedbackId, reviewStatus, strategy);
|
|
4917
|
-
if (updated) return updated;
|
|
4918
|
-
if (attempt >= REVIEW_UPDATE_ATTEMPTS) throw feedbackConflictError(feedbackId);
|
|
4919
|
-
}
|
|
4920
|
-
}
|
|
4921
4900
|
/**
|
|
4922
|
-
*
|
|
4923
|
-
*
|
|
4924
|
-
*
|
|
4925
|
-
*
|
|
4901
|
+
* Review updates insert a replacement row, so they need only `INSERT` and the
|
|
4902
|
+
* insert materialized view publishes the delta cursor.
|
|
4903
|
+
*
|
|
4904
|
+
* A replacement written after a concurrent DELETE is not covered by that
|
|
4905
|
+
* DELETE. The post-write check therefore looks for any request, pending or
|
|
4906
|
+
* applied, and re-runs the delete when it finds one. Only applied requests
|
|
4907
|
+
* block the update up front, so feedback whose delete failed stays editable.
|
|
4908
|
+
*
|
|
4909
|
+
* If the post-write check reads a replica that has not received the request
|
|
4910
|
+
* yet, or the check or its delete fails, the replacement stays visible. A row
|
|
4911
|
+
* that is still visible under an applied request can only be such a leftover,
|
|
4912
|
+
* so the next update deletes it again.
|
|
4926
4913
|
*/
|
|
4927
|
-
async function
|
|
4928
|
-
const
|
|
4914
|
+
async function updateFeedbackReviewStatus(client, args, replication) {
|
|
4915
|
+
const { feedbackId, reviewStatus } = parseUpdateFeedbackReviewStatusArgs(args);
|
|
4916
|
+
const existingRow = (await queryJson$2(client, `SELECT * FROM ${TABLE_FEEDBACK_EVENTS} FINAL
|
|
4929
4917
|
WHERE feedbackId = {feedbackId:String}
|
|
4930
4918
|
ORDER BY writeVersion DESC, timestamp DESC
|
|
4931
4919
|
LIMIT 1`, { feedbackId }))[0];
|
|
4932
4920
|
if (!existingRow) throw feedbackNotFoundError(feedbackId);
|
|
4933
|
-
|
|
4934
|
-
const
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
traceId: existingRow.traceId,
|
|
4942
|
-
writeVersion: existingRow.reviewWriteVersion,
|
|
4943
|
-
reviewStatus
|
|
4921
|
+
const { organizationId, resourceId } = existingRow;
|
|
4922
|
+
const redelete = async () => {
|
|
4923
|
+
await deleteFeedback(client, {
|
|
4924
|
+
feedbackIds: [feedbackId],
|
|
4925
|
+
organizationId: organizationId ?? void 0,
|
|
4926
|
+
resourceId: resourceId ?? void 0
|
|
4927
|
+
}, replication);
|
|
4928
|
+
throw feedbackNotFoundError(feedbackId);
|
|
4944
4929
|
};
|
|
4945
|
-
await client
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
...CH_SETTINGS,
|
|
4950
|
-
mutations_sync: "1"
|
|
4951
|
-
}
|
|
4952
|
-
});
|
|
4953
|
-
if (strategy !== null) await client.command({
|
|
4954
|
-
query: `INSERT INTO ${TABLE_FEEDBACK_EVENTS_DELTA}
|
|
4955
|
-
SELECT ${buildDeltaCursorExpr(strategy, "mastra_feedback_events_delta_cursor", "feedbackId")} AS cursorId,
|
|
4956
|
-
ingestedAt, traceId, timestamp, feedbackId
|
|
4957
|
-
FROM (
|
|
4958
|
-
SELECT now64(9, 'UTC') AS ingestedAt, traceId, timestamp, feedbackId
|
|
4959
|
-
FROM ${TABLE_FEEDBACK_EVENTS} FINAL WHERE ${identity}
|
|
4960
|
-
)`,
|
|
4961
|
-
query_params: params,
|
|
4962
|
-
clickhouse_settings: {
|
|
4963
|
-
...CH_INSERT_SETTINGS,
|
|
4964
|
-
async_insert: 0
|
|
4965
|
-
}
|
|
4930
|
+
if (await hasFeedbackDeletionRequest(client, feedbackId, organizationId, resourceId, { appliedOnly: true })) return redelete();
|
|
4931
|
+
const updated = rowToFeedbackRecord({
|
|
4932
|
+
...existingRow,
|
|
4933
|
+
reviewStatus
|
|
4966
4934
|
});
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
return
|
|
4935
|
+
await batchCreateFeedback(client, { feedbacks: [updated] });
|
|
4936
|
+
if (await hasFeedbackDeletionRequest(client, feedbackId, organizationId, resourceId, { appliedOnly: false })) return redelete();
|
|
4937
|
+
return updated;
|
|
4970
4938
|
}
|
|
4971
4939
|
async function listFeedback(client, args, strategy) {
|
|
4972
4940
|
const parsed = _mastra_core_storage.listFeedbackArgsSchema.parse(args);
|
|
@@ -8665,21 +8633,35 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
|
|
|
8665
8633
|
if (!deltaPollingSupported(this.#deltaCursorStrategy)) return [
|
|
8666
8634
|
"metrics",
|
|
8667
8635
|
"logs",
|
|
8636
|
+
"entity-type-discovery",
|
|
8637
|
+
"entity-name-discovery",
|
|
8638
|
+
"service-name-discovery",
|
|
8639
|
+
"environment-discovery",
|
|
8640
|
+
"tag-discovery",
|
|
8641
|
+
"metric-discovery",
|
|
8668
8642
|
"trace-query",
|
|
8669
8643
|
"trace-query-root-duration",
|
|
8670
8644
|
"trace-query-discovery",
|
|
8671
8645
|
"thread-query",
|
|
8672
|
-
"trace-query-tenant-scope"
|
|
8646
|
+
"trace-query-tenant-scope",
|
|
8647
|
+
"feedback"
|
|
8673
8648
|
];
|
|
8674
8649
|
return [
|
|
8675
8650
|
"metrics",
|
|
8676
8651
|
"logs",
|
|
8652
|
+
"entity-type-discovery",
|
|
8653
|
+
"entity-name-discovery",
|
|
8654
|
+
"service-name-discovery",
|
|
8655
|
+
"environment-discovery",
|
|
8656
|
+
"tag-discovery",
|
|
8657
|
+
"metric-discovery",
|
|
8677
8658
|
"delta-polling",
|
|
8678
8659
|
"trace-query",
|
|
8679
8660
|
"trace-query-root-duration",
|
|
8680
8661
|
"trace-query-discovery",
|
|
8681
8662
|
"thread-query",
|
|
8682
|
-
"trace-query-tenant-scope"
|
|
8663
|
+
"trace-query-tenant-scope",
|
|
8664
|
+
"feedback"
|
|
8683
8665
|
];
|
|
8684
8666
|
}
|
|
8685
8667
|
async createSpan(args) {
|
|
@@ -9019,7 +9001,7 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
|
|
|
9019
9001
|
}
|
|
9020
9002
|
async updateFeedbackReviewStatus(args) {
|
|
9021
9003
|
try {
|
|
9022
|
-
return await updateFeedbackReviewStatus(this.#client, args,
|
|
9004
|
+
return await updateFeedbackReviewStatus(this.#client, args, this.#replication);
|
|
9023
9005
|
} catch (error) {
|
|
9024
9006
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
9025
9007
|
throw new _mastra_core_error.MastraError({
|