Skip to content

Merge dev into main#23

Closed
levivannoort wants to merge 4 commits into
mainfrom
dev
Closed

Merge dev into main#23
levivannoort wants to merge 4 commits into
mainfrom
dev

Conversation

@levivannoort

Copy link
Copy Markdown
Contributor

Changes that landed on dev (accidental merge target) to bring main up to date.

Commits

🤖 Generated with Claude Code

levivannoort and others added 4 commits July 2, 2026 18:48
Add setRetention(?int $days) to the ClickHouse adapter. When set, setup()
applies an idempotent `ALTER TABLE ... MODIFY TTL toDateTime(time) + INTERVAL
<days> DAY` to the snapshot (ReplacingMergeTree) table so latest-state rows
older than the window are dropped by background merges.

- Only the snapshot table gets a TTL; the aggregated (SummingMergeTree) table
  is left untouched since it backs long-term usage/billing history.
- Applied as a separate ALTER (not in CREATE TABLE) so it also covers
  already-existing tables; MODIFY TTL is a no-op when unchanged, keeping
  setup() re-runnable.
- materialize_ttl_after_modify = 0 defers the purge to background merges
  instead of an immediate mutation.
- Default null preserves existing behaviour (no TTL).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n private

Addresses review feedback on the retention TTL:
- setup() now issues ALTER TABLE ... REMOVE TTL on the null path so
  disabling retention actually strips a previously applied TTL, matching
  the documented "pass null to disable" contract. REMOVE TTL is a no-op
  on a table without a TTL, so setup() stays idempotent.
- $retention is now private, matching the other sensitive fields and
  preventing subclasses from bypassing the positive-day guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
REMOVE TTL is not a no-op — ClickHouse raises error 36 (BAD_ARGUMENTS,
"Table doesn't have any table TTL expression, cannot remove") when the
snapshot table has no TTL. That broke setup() on every fresh table when
retention is disabled. Swallow that specific error to keep setup()
idempotent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(clickhouse): add optional retention TTL on the snapshot table
@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown

Greptile Summary

This PR brings dev into main by adding an optional retention TTL feature for the ClickHouse snapshot table. When setRetention($days) is called before setup(), the snapshot table receives a MODIFY TTL clause; passing null issues a REMOVE TTL instead, with error swallowing to stay idempotent on tables that never had a TTL.

  • setRetention(?int $days) / getRetention() – new fluent API to configure a positive-day window; validated to reject zero or negative values.
  • TTL wiring in setup() – two new ALTER TABLE paths: MODIFY TTL … INTERVAL N DAY SETTINGS materialize_ttl_after_modify = 0 when retention is set, and REMOVE TTL (with exception suppression for the "no existing TTL" case) when it is null.
  • The aggregated (SummingMergeTree) table is deliberately left without a TTL to preserve long-term billing history.

Confidence Score: 4/5

Safe to merge; the retention feature is well-scoped and the only concern is defensive robustness of the error-swallowing path.

The change is small and well-contained — setRetention validates its input, the int type prevents SQL injection in the TTL expression, and the aggregated table is correctly left untouched. The one rough edge is that the REMOVE TTL error suppression relies on a substring of ClickHouse's human-readable error message rather than a stable error code, which could silently break idempotency if ClickHouse ever rewords the message.

The REMOVE TTL exception-handling block in src/Usage/Adapter/ClickHouse.php (around line 1126) is worth a second look before merging.

Important Files Changed

Filename Overview
src/Usage/Adapter/ClickHouse.php Adds optional TTL-based retention on the snapshot table via setRetention()/getRetention() and a pair of ALTER TABLE calls inside setup(); error suppression for the REMOVE TTL path uses fragile message substring matching.

Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
src/Usage/Adapter/ClickHouse.php:1126-1133
**Fragile error-message matching to detect "no TTL" case**

The exception is suppressed by checking that the message contains `"doesn't have any table TTL expression"`. This substring is not part of a stable ClickHouse API contract — the wording can vary across ClickHouse versions or distributions. If ClickHouse ever rewords that message, the condition will never match, every `REMOVE TTL` on a table without a TTL will surface as an uncaught exception, and `setup()` will stop being idempotent when disabling retention. Consider also guarding on the ClickHouse error code (36 / `NO_SUCH_DATA_PART`) via a dedicated exception type or numeric code check if the client library exposes one, and logging a warning rather than silently swallowing the mismatch.

Reviews (1): Last reviewed commit: "Merge pull request #20 from levivannoort..." | Re-trigger Greptile

Comment on lines +1126 to +1133
try {
$this->query(
"ALTER TABLE {$escapedSnapshotDatabaseAndTable} REMOVE TTL"
);
} catch (Exception $e) {
if (!str_contains($e->getMessage(), "doesn't have any table TTL expression")) {
throw $e;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Fragile error-message matching to detect "no TTL" case

The exception is suppressed by checking that the message contains "doesn't have any table TTL expression". This substring is not part of a stable ClickHouse API contract — the wording can vary across ClickHouse versions or distributions. If ClickHouse ever rewords that message, the condition will never match, every REMOVE TTL on a table without a TTL will surface as an uncaught exception, and setup() will stop being idempotent when disabling retention. Consider also guarding on the ClickHouse error code (36 / NO_SUCH_DATA_PART) via a dedicated exception type or numeric code check if the client library exposes one, and logging a warning rather than silently swallowing the mismatch.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/Usage/Adapter/ClickHouse.php
Line: 1126-1133

Comment:
**Fragile error-message matching to detect "no TTL" case**

The exception is suppressed by checking that the message contains `"doesn't have any table TTL expression"`. This substring is not part of a stable ClickHouse API contract — the wording can vary across ClickHouse versions or distributions. If ClickHouse ever rewords that message, the condition will never match, every `REMOVE TTL` on a table without a TTL will surface as an uncaught exception, and `setup()` will stop being idempotent when disabling retention. Consider also guarding on the ClickHouse error code (36 / `NO_SUCH_DATA_PART`) via a dedicated exception type or numeric code check if the client library exposes one, and logging a warning rather than silently swallowing the mismatch.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants