fix(halacha): שחזור-עצמי לנעילת-advisory דלופה — לא לחסום חילוץ-הלכות (#142) #258

Merged
chaim merged 2 commits from worktree-halacha-lock-leak into main 2026-06-15 02:57:45 +00:00
Owner

הבעיה (#142)

כשה-legal-halacha-drain קרס עם RuntimeError: Event loop is closed, ה-finally ב-halacha_extractor.extract() שמריץ pg_advisory_unlock + pool.release לא רץ. חיבור-הנעילה הייעודי (lock_conn) נשאר חי, idle, ומחזיק את הנעילה הגלובלית — וכך כל precedent_extract_halachot עתידי החזיר status='busy' לצמיתות, עד pg_terminate_backend ידני (~4.5 דק', CMP-174, 2026-06-14, objid 1212238913).

התיקון

נעילת-session נשמרת, אך הופכת משחזרת-עצמית:

  1. KEEPALIVE — משימת-רקע נוגעת ב-lock_conn כל 30ש' (SELECT 1), כך ש-pg_stat_activity.state_change נשאר טרי. חילוץ חי לעולם לא נראה תקוע; קריסה מקפיאה את ה-keepalive (ואת state_change) יחד עם ה-loop.
  2. שחזור-עצמי בכניסה (_acquire_global_lock) — כש-pg_try_advisory_lock נכשל, בודקים את ה-holder ב-pg_lockspg_stat_activity. רק backend idle עם state_change ישן מ-_LOCK_STALE_AFTER (150ש' = 5× keepalive) מזוהה כ-orphan דלוף → pg_terminate_backend ואז pg_try_advisory_lock מחדש (עד 10 פולים). backend active או idle-טרי = חילוץ חי → לעולם לא נהרג (כדי לא להחזיר את ה-box-freeze שהנעילה מונעת).

נדחתה אופציה (ג) pg_advisory_xact_lock: הייתה כופה transaction פתוח לאורך דקות (idle-in-transaction bloat) ועדיין לא משחררת מיידית חיבור-orphan חי.

הערה: השתמשתי במונח ה-DB הסטנדרטי keepalive (לא "heartbeat") כי leak_guard מסמן את heartbeat כסמל ספציפי-Paperclip (G12).

בדיקות

  • חדש: tests/test_halacha_lock_selfheal.py — 7 בדיקות offline: lock-free, live-holder (לא נהרג), active-holder (לא נהרג), stale-orphan (terminate+reclaim), no-holder-row, keepalive-stop, extract מחזיר busy.
  • כל 332 בדיקות mcp-server עוברות. leak_guard נקי.

Invariants

  • G1 — תיקון-במקור (הנעילה משחזרת את עצמה, לא workaround בקריאה)
  • G2 — אותה נעילה גלובלית, ללא מסלול-תור מקביל
  • INV-G3 / X16 — עמידות-פייפליין (התאוששות מקריסה)
  • G12 — leak-guard נקי (intelligence layer platform-clean)

🤖 Generated with Claude Code

## הבעיה (#142) כשה-`legal-halacha-drain` קרס עם `RuntimeError: Event loop is closed`, ה-`finally` ב-`halacha_extractor.extract()` שמריץ `pg_advisory_unlock` + `pool.release` **לא רץ**. חיבור-הנעילה הייעודי (`lock_conn`) נשאר חי, idle, ומחזיק את הנעילה הגלובלית — וכך **כל** `precedent_extract_halachot` עתידי החזיר `status='busy'` לצמיתות, עד `pg_terminate_backend` ידני (~4.5 דק', CMP-174, 2026-06-14, objid 1212238913). ## התיקון נעילת-session נשמרת, אך הופכת **משחזרת-עצמית**: 1. **KEEPALIVE** — משימת-רקע נוגעת ב-`lock_conn` כל 30ש' (`SELECT 1`), כך ש-`pg_stat_activity.state_change` נשאר טרי. חילוץ **חי** לעולם לא נראה תקוע; קריסה מקפיאה את ה-keepalive (ואת `state_change`) יחד עם ה-loop. 2. **שחזור-עצמי בכניסה** (`_acquire_global_lock`) — כש-`pg_try_advisory_lock` נכשל, בודקים את ה-holder ב-`pg_locks`⋈`pg_stat_activity`. **רק** backend `idle` עם `state_change` ישן מ-`_LOCK_STALE_AFTER` (150ש' = 5× keepalive) מזוהה כ-orphan דלוף → `pg_terminate_backend` ואז `pg_try_advisory_lock` מחדש (עד 10 פולים). backend `active` או `idle`-טרי = חילוץ חי → **לעולם לא נהרג** (כדי לא להחזיר את ה-box-freeze שהנעילה מונעת). נדחתה אופציה (ג) `pg_advisory_xact_lock`: הייתה כופה transaction פתוח לאורך דקות (idle-in-transaction bloat) **ועדיין** לא משחררת מיידית חיבור-orphan חי. > הערה: השתמשתי במונח ה-DB הסטנדרטי **keepalive** (לא "heartbeat") כי `leak_guard` מסמן את `heartbeat` כסמל ספציפי-Paperclip (G12). ## בדיקות - חדש: `tests/test_halacha_lock_selfheal.py` — 7 בדיקות offline: lock-free, live-holder (לא נהרג), active-holder (לא נהרג), stale-orphan (terminate+reclaim), no-holder-row, keepalive-stop, `extract` מחזיר `busy`. - כל **332** בדיקות mcp-server עוברות. `leak_guard` נקי. ## Invariants - ✅ **G1** — תיקון-במקור (הנעילה משחזרת את עצמה, לא workaround בקריאה) - ✅ **G2** — אותה נעילה גלובלית, ללא מסלול-תור מקביל - ✅ **INV-G3 / X16** — עמידות-פייפליין (התאוששות מקריסה) - ✅ **G12** — leak-guard נקי (intelligence layer platform-clean) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chaim added 1 commit 2026-06-15 02:55:37 +00:00
fix(halacha): שחזור-עצמי לנעילת-advisory דלופה — לא לחסום חילוץ-הלכות (#142)
Some checks failed
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
Lint — undefined names / undefined-names (pull_request) Failing after 13s
b7ffc0387c
כשה-legal-halacha-drain קרס עם "RuntimeError: Event loop is closed", ה-finally
שמריץ pg_advisory_unlock + pool.release לא רץ, וחיבור-הנעילה הייעודי נשאר חי,
idle, מחזיק את הנעילה הגלובלית — כל extract עתידי החזיר status='busy' לצמיתות
עד pg_terminate_backend ידני (~4.5 דק', CMP-174, 2026-06-14).

תיקון (G1 — נרמול-במקור, G2 — אותה נעילה, בלי מסלול מקביל):
- KEEPALIVE: משימת-רקע נוגעת בחיבור-הנעילה כל 30ש' → state_change נשאר טרי.
  חילוץ חי לעולם לא נראה "תקוע"; קריסה מקפיאה את ה-keepalive ואת state_change.
- שחזור-עצמי בכניסה (_acquire_global_lock): כש-pg_try_advisory_lock נכשל, בודקים
  את ה-holder; רק backend idle עם state_change ישן מ-_LOCK_STALE_AFTER (150ש',
  5× keepalive) הוא orphan דלוף → pg_terminate_backend ואז acquire מחדש.
  backend 'active' או idle-טרי = חילוץ חי, לעולם לא נהרג (מניעת ה-box-freeze).
- נדחתה אופציית pg_advisory_xact_lock: הייתה כופה transaction פתוח לאורך דקות
  (idle-in-transaction bloat) ועדיין לא משחררת מיידית חיבור-orphan חי.

הערה: השתמשתי במונח DB-סטנדרטי "keepalive" (לא "heartbeat") כי leak_guard מסמן
את "heartbeat" כסמל ספציפי-Paperclip (G12).

בדיקות: tests/test_halacha_lock_selfheal.py (7) — free/live-holder/active-holder/
stale-orphan-reclaim/no-holder/keepalive-stop/extract-busy. כל 332 בדיקות mcp עוברות.

Invariants: G1 (תיקון-במקור), G2 (אותה נעילה), G3/X16 (עמידות-פייפליין), G12 (leak-guard נקי).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chaim added 1 commit 2026-06-15 02:56:52 +00:00
fix(halacha): import asyncpg — undefined-name guard (annotation ב-_acquire_global_lock)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 6s
Lint — undefined names / undefined-names (pull_request) Successful in 14s
eb86e475c3
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chaim merged commit 76a29756c5 into main 2026-06-15 02:57:45 +00:00
chaim deleted branch worktree-halacha-lock-leak 2026-06-15 02:57:45 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ezer-mishpati/legal-ai#258