---
phase: 01-mutation-safety
plan: 01
subsystem: database
tags: [clickhouse, threading, mutation-safety, partition-scoped-delete]

requires: []
provides:
  - "Per-partition lock dict (_get_partition_lock) for concurrent kintsugi workers"
  - "Partition-scoped DELETE IN PARTITION loop in sidecar pre-fill"
  - "Dead code removal (if False: block in maintenance.py)"
affects: [01-02, sidecar, kintsugi]

tech-stack:
  added: []
  patterns:
    - "Per-partition lock via dict.setdefault + guard lock"
    - "DELETE IN PARTITION per (symbol, threshold) pair loop"

key-files:
  created:
    - tests/test_mutation_safety.py
  modified:
    - python/opendeviationbar/clickhouse/maintenance.py
    - python/opendeviationbar/sidecar/__init__.py

key-decisions:
  - "Used dict.setdefault + guard lock pattern (not defaultdict) for thread-safe per-partition lock creation"
  - "Sequential per-pair DELETE IN PARTITION loop (not parallel ThreadPoolExecutor) for sidecar pre-fill -- startup runs once, simplicity over speed"

patterns-established:
  - "_get_partition_lock(symbol, threshold_decimal_bps): canonical way to serialize same-partition mutations while allowing cross-partition concurrency"

requirements-completed: [MUT-01, MUT-02]

duration: 2min
completed: 2026-03-24
---

# Phase 01 Plan 01: Mutation Safety Summary

**Per-partition lock replaces global \_replace_lock enabling concurrent kintsugi workers; sidecar pre-fill migrated to O(1) DELETE IN PARTITION per pair**

## Performance

- **Duration:** 2 min
- **Started:** 2026-03-24T19:10:55Z
- **Completed:** 2026-03-24T19:13:10Z
- **Tasks:** 2
- **Files modified:** 3

## Accomplishments

- Replaced global `_replace_lock` with per-partition lock dict keyed by `(symbol, threshold_decimal_bps)` -- different partitions now mutate concurrently
- Migrated sidecar compound DELETE to per-pair DELETE IN PARTITION loop -- each DELETE scans O(1 partition) not O(all parts)
- Removed dead code (`if False:` block with old unscoped DELETE fallback)
- 4 tests pass: concurrency, serialization, identity, dead code removal

## Task Commits

Each task was committed atomically:

1. **Task 1: Per-partition lock and maintenance.py cleanup (TDD)**
   - `93e6f92` (test: failing tests for per-partition lock)
   - `542afd1` (feat: per-partition lock implementation + dead code removal)
2. **Task 2: Sidecar compound DELETE to partition-scoped loop** - `82c125b` (feat)

## Files Created/Modified

- `python/opendeviationbar/clickhouse/maintenance.py` - Per-partition lock dict, \_get_partition_lock(), dead code removed
- `python/opendeviationbar/sidecar/__init__.py` - Per-pair DELETE IN PARTITION loop replacing compound DELETE
- `tests/test_mutation_safety.py` - 4 tests: concurrency, serialization, identity, dead code

## Decisions Made

- Used `dict.setdefault` + guard lock pattern (not `defaultdict`) -- thread-safe creation with double-check, standard Python pattern
- Sequential DELETE loop for sidecar (not parallel) -- sidecar pre-fill runs once at startup, simplicity preferred over marginal speedup

## Deviations from Plan

None - plan executed exactly as written.

## Issues Encountered

None.

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness

- Per-partition lock is live -- Plan 02 (remaining DELETE site audit across rectify, scripts) can proceed
- Production verification on bigblack (24-worker kintsugi pass + system.mutations query) needed at phase gate

---

_Phase: 01-mutation-safety_
_Completed: 2026-03-24_
