Skip to content

[STAŁA GAŁĄŹ WERYFIKACYJNA — nie mergować] LEAK-GUARD: twardy gate + tracer, na kodzie z fixem #638#639

Draft
mpasternak wants to merge 4 commits into
devfrom
diag/leak-guard-strict-ci
Draft

[STAŁA GAŁĄŹ WERYFIKACYJNA — nie mergować] LEAK-GUARD: twardy gate + tracer, na kodzie z fixem #638#639
mpasternak wants to merge 4 commits into
devfrom
diag/leak-guard-strict-ci

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Zastępuje zamknięty #636 (force-push odciął stary head, GitHub odmówił reopen).

Czym jest

Stała gałąź weryfikacyjna, nie do merge'a. Odpala twardy gate BPP_LEAK_GUARD_STRICT=1 na wszystkich shardach — wykrycie scommitowanych danych po teardownie testu = twardy błąd. Rebase na dev + push, kiedy chcemy świeży pomiar.

Co się zmieniło od poprzedniego przebiegu

Poprzedni run tej gałęzi (na dev sprzed poprawki) dał 79 wykryć wycieku. Teraz stoi na dev z zmergowanym #638 (przyczyna naprawiona: liveops raportuje w testach przez MockProgress, koniec przełączania wskaźnika pętli przy żywej bazie).

Ten przebieg jest definitywnym testem poprawki. Oczekiwanie: shardy zielone, zero [LEAK-GUARD/teardown] w logach, zero WykrytoWyciekDanych.

Zawartość gałęzi (2 commity nad dev)

  • tracer połączeń — notuje CONNECT spoza MainThread i CLOSE w atomic bloku ze stosem; gdyby jakiś NOWY wyciek się pojawił, od razu wskaże mechanizm;
  • flaga strict w tests.yml.

Jak czytać wynik

🤖 Generated with Claude Code

https://claude.ai/code/session_0134fYqFag9EXfHXEuC6nTjZ

mpasternak and others added 4 commits July 20, 2026 17:24
…akcję

Pomiar z CI zawęził sprawę: wyciekają zwykłe django_db (tx=False), a wiersze
to WŁASNE dane testu ("Nowak", "Kat.", "brygadier"). Osobne połączenie sondy
je widzi, więc są scommitowane — sesja PG na READ COMMITTED nie zobaczy
cudzych niescommitowanych. Rollback pytest-django jest niemal na pewno
sprawny; zapis musiał ominąć transakcję testu.

Są na to dwa sposoby i tracer je rozróżnia:
  A. zapis z innego wątku — connections jest thread-local, wątek dostaje
     własne połączenie w autocommit poza atomic blokiem,
  B. podmiana połączenia w trakcie testu — close() w atomic bloku, Django
     otwiera nowe, rollback działa na obiekcie bez czego cofać.

Wcześniejszy pomiar closed_in_tx=False NIE wyklucza (B): flaga siedzi na
obiekcie połączenia, po podmianie nowy ma ją czystą. Moje niedopatrzenie.

Tracer notuje CONNECT spoza MainThread i CLOSE w atomic bloku, ze stosem,
i dokleja je do raportu wycieku. Włączany przez BPP_LEAK_GUARD_TRACE=1 lub
BPP_LEAK_GUARD_STRICT=1 — domyślnie nieaktywny, bo monkey-patch na warstwie
połączeń nie ma prawa działać w zwykłym przebiegu.

Plus test_leak_guard_tracer.py: guard dla guarda. Bez niego milczenie na CI
czytalibyśmy jako "zapisów spoza wątku nie ma" zamiast "nie mierzymy".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134fYqFag9EXfHXEuC6nTjZ
NIE MERGOWAĆ DO dev. Strict zamienia wykrycie wycieku w twardy błąd testu
zamiast cichego TRUNCATE + raportu na sessionfinish. Na dev zablokowałoby
to merge'e (przyczyna wycieku nieznana), więc siedzi osobno — żeby zobaczyć
pełny obraz: przy którym teście następuje wykrycie, czyje są wiersze
i jaki jest wtedy stan izolacji połączenia.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134fYqFag9EXfHXEuC6nTjZ
…conftest"

Gołe "import conftest" rozstrzyga się pod pytestem na pierwszy conftest.py
na sys.path; przy shardowaniu xdista bywa to conftest aplikacyjny bez
tracera → AttributeError na shardzie 1 (zielono lokalnie, czerwono na CI).

Świeży importlib też nie wystarcza: dałby osobną instancję z własnym
_LEAK_GUARD, a tracer dopisuje zdarzenia do instancji, którą załadował
pytest. Test sięga więc po TĘ instancję przez sys.modules (po __file__
kończącym się /src/conftest.py + obecności _zainstaluj_tracer_polaczen).

Zweryfikowane w obu trybach: BPP_LEAK_GUARD_STRICT=1 (jak CI) i bez.

To była JEDYNA czerwień na przebiegu gate'a — awaria harnessu testu, NIE
wyciek: 12/12 shardów zero LEAK-GUARD, zero WykrytoWyciek, zero AsyncToSync.
Poprawka #638 potwierdzona pod twardym gate'em.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134fYqFag9EXfHXEuC6nTjZ
…ookup

Druga próba (filtr po __file__ w sys.modules) padła znów na shardzie 1:
na CI __file__ conftestu bywa WZGLĘDNY ("src/conftest.py"), więc
endswith("/src/conftest.py") nie łapał → pusta lista kandydatów.

Koniec zgadywania po ścieżce. Pytest rejestruje każdy conftest.py jako
plugin — bierzemy z request.config.pluginmanager.get_plugins() ten
z _zainstaluj_tracer_polaczen. To ta sama instancja, której używa runtime,
niezależnie od formatu ścieżki i kolejności sys.path.

Zweryfikowane: strict ON, strict OFF ORAZ pod xdist -n2 (13 passed) —
czego dwie poprzednie wersje nie wytrzymywały.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134fYqFag9EXfHXEuC6nTjZ
@mpasternak
mpasternak marked this pull request as draft July 20, 2026 16:12
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.

1 participant