Commit 712826e
[OPIK-8230] fix(traces): scope the delete mutation to the batch's own partitions
A ClickHouse mutation is registered against every active part of the target
table before its WHERE clause is even considered - the existing partition
predicate (OPIK_6901) prunes which rows a matched part rewrites, not which
parts the mutation visits at all. Post-cutover traces_local has ~1,900
partitions / ~3,650 parts, so an ordinary delete matching a handful of rows
was registered against all of them, at ~19ms/part fixed overhead. That is
what pushed deletes past max_execution_time (Code 159 TIMEOUT_EXCEEDED),
where the statement errors and skips the TracesDeleted cascade and the
deletion-events bridge write even though the mutation completes and the
rows are in fact deleted.
Scope each statement to the partitions its own batch resolves to via
IN PARTITION, derived by WeeklyPartitions#groupByPartition (new; groups
ids by partition rather than naming their union - IN PARTITION accepts
exactly one partition per statement). One statement per partition,
falling back to the unbounded form when the batch cannot be derived
exactly, or when the target table is not partitioned.
That last condition has to be gated, not inferred from the table name.
Unlike the id_at predicate it supersedes - MATERIALIZED on both topologies,
so valid everywhere and merely unpruned on an unpartitioned table -
IN PARTITION against a table with no PARTITION BY is a hard Code 248
INVALID_PARTITION_VALUE. A name check is wrong in both directions:
post-EXCHANGE/pre-wrap `traces` is already the partitioned successor while
the wrap flag is still false, so the check resolves to "traces", takes the
fallback on every delete, and does nothing in exactly the state production
is in today; and wrap-on without the EXCHANGE is a real supported topology
(TracesDistributedWrapMutationTest) where traces_local is the legacy
unpartitioned table and IN PARTITION fails outright.
The gate reuses traceColumnsNonNullable rather than adding a flag. The
EXCHANGE that replaces the Nullable(...) columns is the same one that puts
the weekly-partitioned successor behind the name mutations target, so the
two facts have only ever flipped together, and a second flag would have to
be carried through the cutover runbook and tooling to track no independent
state. Verified against all four topologies: legacy pre-cutover and
wrap-without-EXCHANGE both read false and take the unbounded form;
production today and the pruning suite both read true and scope. The name
says only its first duty and is deliberately not renamed - the env var is
exposed - so both it and the config comment now document the second.
This leaves no deployment surface: no new config key, no Helm or
docker-compose change, nothing to add to the runbook.
Both forms share one SQL template with an <if(partition)> conditional, and
WeeklyPartitions#of (the flat-union predecessor) is removed - it had no
production callers once TraceDAO switched to groupByPartition. Its unique
boundary-case coverage moved to groupByPartition rather than being dropped.
Verified locally against real ClickHouse via testcontainers, 34/34:
- WeeklyPartitionsTest 17, TracesPartitionPruningMutationTest 8,
TracesDistributedWrapMutationTest 4, TracesLegacyTablePruningMutationTest 2,
TraceMutationRoutingArchTest 3
- The pruning suite asserts on system.part_log MutatePart events rather than
EXPLAIN, which reports read-planner pruning - a different layer from what a
mutation is registered against, and the gap the previous coverage fell into.
- Gate verified by negative control: forced off, the emitted SQL carries no
IN PARTITION and 5 of the 8 pruning tests fail, so the gate is not vacuous.
- Log reads poll a fast-flushing container config instead of SYSTEM FLUSH
LOGS, which pushed only what had already buffered and so raced the rows it
was meant to reveal.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 4ef186c commit 712826e
8 files changed
Lines changed: 730 additions & 563 deletions
File tree
- apps/opik-backend/src
- main/java/com/comet/opik
- domain
- infrastructure
- utils
- test/java/com/comet/opik
- infrastructure
- utils
Lines changed: 70 additions & 57 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1967 | 1967 | | |
1968 | 1968 | | |
1969 | 1969 | | |
1970 | | - | |
1971 | | - | |
1972 | | - | |
1973 | | - | |
1974 | | - | |
| 1970 | + | |
| 1971 | + | |
| 1972 | + | |
1975 | 1973 | | |
1976 | | - | |
1977 | | - | |
1978 | | - | |
1979 | | - | |
1980 | | - | |
| 1974 | + | |
| 1975 | + | |
| 1976 | + | |
1981 | 1977 | | |
1982 | | - | |
1983 | | - | |
1984 | | - | |
1985 | | - | |
1986 | | - | |
1987 | | - | |
1988 | | - | |
1989 | | - | |
1990 | | - | |
1991 | | - | |
1992 | | - | |
1993 | | - | |
1994 | | - | |
1995 | | - | |
1996 | | - | |
1997 | | - | |
| 1978 | + | |
| 1979 | + | |
1998 | 1980 | | |
1999 | 1981 | | |
2000 | 1982 | | |
| 1983 | + | |
2001 | 1984 | | |
2002 | 1985 | | |
2003 | | - | |
2004 | 1986 | | |
2005 | 1987 | | |
2006 | 1988 | | |
| |||
2328 | 2310 | | |
2329 | 2311 | | |
2330 | 2312 | | |
2331 | | - | |
| 2313 | + | |
2332 | 2314 | | |
2333 | 2315 | | |
2334 | 2316 | | |
| |||
3649 | 3631 | | |
3650 | 3632 | | |
3651 | 3633 | | |
3652 | | - | |
3653 | | - | |
3654 | | - | |
3655 | | - | |
3656 | | - | |
3657 | | - | |
3658 | | - | |
3659 | | - | |
3660 | | - | |
3661 | | - | |
3662 | | - | |
3663 | | - | |
3664 | | - | |
3665 | | - | |
3666 | | - | |
3667 | | - | |
3668 | | - | |
3669 | | - | |
3670 | | - | |
3671 | | - | |
3672 | | - | |
| 3634 | + | |
| 3635 | + | |
| 3636 | + | |
3673 | 3637 | | |
3674 | | - | |
3675 | | - | |
3676 | | - | |
| 3638 | + | |
| 3639 | + | |
| 3640 | + | |
| 3641 | + | |
| 3642 | + | |
| 3643 | + | |
| 3644 | + | |
| 3645 | + | |
| 3646 | + | |
| 3647 | + | |
| 3648 | + | |
| 3649 | + | |
| 3650 | + | |
| 3651 | + | |
| 3652 | + | |
| 3653 | + | |
| 3654 | + | |
| 3655 | + | |
| 3656 | + | |
3677 | 3657 | | |
3678 | | - | |
3679 | | - | |
3680 | | - | |
3681 | | - | |
| 3658 | + | |
| 3659 | + | |
| 3660 | + | |
| 3661 | + | |
| 3662 | + | |
| 3663 | + | |
| 3664 | + | |
| 3665 | + | |
| 3666 | + | |
| 3667 | + | |
| 3668 | + | |
3682 | 3669 | | |
3683 | | - | |
| 3670 | + | |
| 3671 | + | |
| 3672 | + | |
| 3673 | + | |
| 3674 | + | |
| 3675 | + | |
| 3676 | + | |
| 3677 | + | |
| 3678 | + | |
| 3679 | + | |
| 3680 | + | |
| 3681 | + | |
| 3682 | + | |
| 3683 | + | |
| 3684 | + | |
| 3685 | + | |
| 3686 | + | |
| 3687 | + | |
| 3688 | + | |
| 3689 | + | |
| 3690 | + | |
| 3691 | + | |
| 3692 | + | |
| 3693 | + | |
| 3694 | + | |
| 3695 | + | |
| 3696 | + | |
3684 | 3697 | | |
3685 | 3698 | | |
3686 | 3699 | | |
| |||
Lines changed: 7 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
537 | 537 | | |
538 | 538 | | |
539 | 539 | | |
540 | | - | |
| 540 | + | |
541 | 541 | | |
542 | 542 | | |
543 | 543 | | |
| |||
566 | 566 | | |
567 | 567 | | |
568 | 568 | | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
569 | 575 | | |
570 | 576 | | |
571 | 577 | | |
| |||
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
18 | 25 | | |
19 | 26 | | |
20 | 27 | | |
| |||
0 commit comments