feat(raport_slotow): migracja z long_running na django-liveops#618
Open
mpasternak wants to merge 3 commits into
Open
feat(raport_slotow): migracja z long_running na django-liveops#618mpasternak wants to merge 3 commits into
mpasternak wants to merge 3 commits into
Conversation
…veops Faza 2 (cutover bazy): RaportSlotowUczelnia dziedziczy teraz po liveops.LiveOperation zamiast long_running.Report. - create_report() -> run(self, p); ciało owinięte w transaction.atomic() (liveops.task_run nie owija; long_running owijało — zachowujemy all-or-nothing generacji). Postęp przez p.percent() zamiast send_progress. - on_reset() -> on_restart(); dodano get_success_url() (Ścieżka A: po FINISHED_OK przejście na tabelę -results). Jawne host/result_template_name (kolizja class_to_snake z istniejącym szablonem wyników). - Scoping per-uczelnia bez zmian: filtr jednostka__uczelnia_id + przekazanie uczelnia_id/uczelnia do zbieraj_sloty/autorzy_zerowi. - Nowa migracja 0022_liveops (delta pól stanu liveops, usunięcie last_updated_on, owner related_name="+"). pk pozostaje UUID. - API v1 (druga powierzchnia, pękała razem z modelem): usunięto last_updated_on z serializera; create() enqueue przez transaction.on_commit(inst.enqueue) zamiast martwego perform_generic_long_running_task -> task_perform. - Testy modelu/guardy per-uczelnia: run(MockProgress(...)); nowy test_liveops_uczelnia; test create-enqueue w API. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iveops Faza 3+4 (cutover UI + sprzątanie): - UtworzRaportSlotowUczelnia na CreateLiveOperationView; form_valid nadal ustawia uczelnia=uczelnia_dla_odczytu(request) PRZED save() (scoping per-uczelnia §8.1), owner + enqueue() bezpośrednio, redirect na live. - ListaRaportSlotowUczelnia: zwykły owner-scoped ListView (bez auto-delete starych operacji — housekeeping to nie zadanie list-view). - WygenerujPonownieRaportSlotowUczelnia: RestartView POST-only + owner-scope + bramka BaseRaportAuthMixin. Guard §8.4: reset/re-enqueue TYLKO gdy stan terminalny (chroni przed wyścigiem regen-w-trakcie-runu z workerem). - SzczegolyRaportSlotowUczelniaListaRekordow: odcięte od LongRunningResultsView; własne parent_object (owner-scope + superuser-exempt) i get_queryset; zachowany django_tables2 + eksport XLSX; kontekst nadal niesie object. - Usunięto widoki/URL-e router i details (rolę przejął centralny liveops:live); usunięto martwe szablony detail/wiersz_list. - Nowe szablony: host (raport_slotow_uczelnia_live.html) z wrapperem hx-headers X-CSRFToken (CSRF_COOKIE_HTTPONLY) + minimalny result-fragment. Link listy → get_absolute_url; regen w tabeli wyników → formularz POST. - _LiveopsNoPermissionCompatMixin: godzi braces AccessMixin (wymaga request) z liveops BaseLiveOperationMixin (Django-style bez request) — anonim dostaje 302 na login zamiast 500. - Testy widoków przepięte na nowy kontrakt (regen POST, lista bez kasowania, strona live, guard nie-skończonego, anon 302 bez efektu). Newsfragment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review PR #618: - _generuj() wołało tylko p.percent() (bez check_cancelled), więc przycisk „Anuluj" był no-op mid-run, a newsfragment obiecywał anulowanie. Dodane p.check_cancelled() na szczycie pętli → OperationCancelled leci z bloku atomic w run() → rollback już-zapisanych wierszy (all-or-nothing). Test test_run_anulowanie_rollback to weryfikuje. - Dodany test anon→302 dla UtworzRaportSlotowUczelnia (luka pokrycia — dotąd tylko Regen miał test compat-mixinu handle_no_permission). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cel
Przeniesienie
RaportSlotowUczelnia(jedynej long-running operacji wraport_slotow) zlong_running.Report(+ASGINotificationMixin) nadjango-liveops0.4 (LiveOperation+run(self, p)+WebProgresspoWebSocket/HTMX), analogicznie do zmigrowanego
import_pracownikow. To jestReport (generuje wiersze do bazy), więc wynik to osobna tabela (
-results),a nie panel inline — Ścieżka A (
get_success_url()).Co się zmieniło
Model / migracja (Faza 2)
RaportSlotowUczelnia(LiveOperation);create_report()→run(self, p)owinięte w
transaction.atomic()(liveopstask_runnie owija; long_runningowijało — zachowujemy all-or-nothing generacji). Postęp przez
p.percent().on_reset()→on_restart(); dodanoget_success_url()(poFINISHED_OKprzejście na tabelę wyników). Jawne
host_template_name/result_template_name(kolizja
class_to_snakez istniejącymraport_slotow_uczelnia.html).0022_liveops— delta pól stanu liveops +RemoveField last_updated_on+owner related_name="+". pk pozostaje UUID (bezmigracji pk), URL-e już
<uuid:pk>.API v1 (druga powierzchnia — pękała razem z modelem)
last_updated_onz serializera (poRemoveFieldkażde żądanie doviewsetu →
ImproperlyConfigured).create()(@transaction.atomic) kolejkuje teraz przeztransaction.on_commit(inst.enqueue)zamiast martwegoperform_generic_long_running_task→task_perform(któregoLiveOperationnie ma). Enqueue MUSI iść przez
on_commit(create jest atomic).Widoki / URL-e / szablony (Faza 3)
Utworz→CreateLiveOperationView(owner +uczelniaz requestu + enqueue).Lista→ owner-scopedListView(bez auto-kasowania starych operacji).Regen→RestartViewPOST-only + owner-scope + bramkaBaseRaportAuthMixin;guard „reset tylko gdy stan terminalny" (chroni przed wyścigiem regenu
w połowie runu z workerem — raport slotów nie ma maszyny stanów).
Resultsodcięte odLongRunningResultsView— własneparent_object(owner-scope + superuser-exempt) i
get_queryset; zachowany django_tables2 +eksport XLSX; kontekst nadal niesie
object.-routeri-details(rolę przejął centralnyliveops:live) oraz martwe szablony. Nowy host-template z wrapperemhx-headersX-CSRFToken(boCSRF_COOKIE_HTTPONLY=True) + minimalnyresult-fragment fallback. Regen w tabeli wyników → formularz POST.
_LiveopsNoPermissionCompatMixingodzi bracesAccessMixin(wymagarequest) z liveopsBaseLiveOperationMixin(Django-style bezrequest) —anonim dostaje 302 na login zamiast 500.
Zachowany scoping per-uczelnia
uczelniaFK zostaje na modelu;form_validnadal ustawiauczelnia = uczelnia_dla_odczytu(request)PRZEDsave().run()zachowuje filtrjednostka__uczelnia_idoraz przekazanieuczelnia_id/uczelniadozbieraj_sloty/autorzy_zerowi— bez zmian.create()NIE ustawiauczelnia(raport z API jest nie-zawężony) — to stan OBECNY sprzed migracji; owner-scope
i tak izoluje odczyt. Udokumentowane w komentarzu serializera.
test_uczelnia_helper,test_per_uczelnia_uczelnia,tests_models/test_uczelnia(przepięte narun(MockProgress(...))).Testy
uv run pytest src/raport_slotow src/api_v1/tests/test_raport_slotow_uczelnia.py→ 98 passed (świeża baza, bez REUSE).
long_running+import_pracownikow+api_v1→ 843passed (2 „failures" w
test_wydawnictwo_*_no_queriesto artefaktPYTEST_TESTCONTAINERS_REUSE— przechodzą na świeżej bazie).test_liveops_uczelnia), guard restartu„nie-skończony nie resetuje", regen POST, anon 302 bez efektu ubocznego,
API create-enqueue.
makemigrations --check --dry-run raport_slotow api_v1→ No changesdetected (czysto).
Baseline
Baseline NIE był odświeżany w tym branchu (reguła: raz, przy scalaniu) —
wymaga
make baseline-updateprzy merge (dodano migrację 0022 zmieniającąschemat).
🤖 Generated with Claude Code