nordabiz/docs/REFACTORING_STATUS.md
Maciej Pienczyn e116eeadc6 docs: Add safe deployment methodology after production incident
- Document incident 2026-01-31 (alias failure)
- New rule: Use full blueprint names, NOT aliases
- New procedure: Update templates BEFORE moving routes
- Enhanced checklist: Test page rendering, not just HTTP status

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 08:29:24 +01:00

8.2 KiB

Status Refaktoringu app.py

Ostatnia aktualizacja: 2026-01-31 Autor sesji: Claude Opus 4.5

Stan obecny

Faza 1 - WDROŻONA NA PRODUKCJĘ

Commit: 66856a6 Data wdrożenia: 2026-01-28

Blueprint URL Prefix Routes Status
reports /raporty 4 Przetestowane
contacts /kontakty 6 Przetestowane
classifieds /tablica 4 Przetestowane
calendar /kalendarz 3 Przetestowane
education /edukacja 2 Przetestowane

Faza 2a - WDROŻONA NA PRODUKCJĘ

Data wdrożenia: 2026-01-31 Strategia: Alias Bridge (bezpieczna migracja) Commity: d5adf02 (blueprinty), cdd050a (cleanup), 0ccb109 (docs)

Blueprint Routes Status
auth 20 Gotowy, aliasy aktywne
public 11 Gotowy, aliasy aktywne

Pliki utworzone:

  • blueprints/auth/__init__.py
  • blueprints/auth/routes.py (1,040 linii)
  • blueprints/public/__init__.py
  • blueprints/public/routes.py (862 linii)

Redukcja app.py:

  • Przed: 15,577 linii
  • Po: 13,820 linii
  • Usunięto: 1,757 linii (11.3%)

Testy (DEV):

  • Wszystkie endpointy działają
  • Aliasy: url_for('login') = url_for('auth.login')
  • Istniejące blueprinty działają

Metodologia Refaktoringu (Alias Bridge)

Dlaczego ta metoda?

Problem: 125+ wywołań url_for() w szablonach i kodzie używa starych nazw (url_for('login')). Rozwiązanie: Aliasy pozwalają na stopniową migrację bez "Big Bang".

Procedura dla każdej fazy

Krok 1: Utworzenie blueprintu

mkdir -p blueprints/<nazwa>
touch blueprints/<nazwa>/__init__.py
touch blueprints/<nazwa>/routes.py
# blueprints/<nazwa>/__init__.py
from flask import Blueprint
bp = Blueprint('<nazwa>', __name__)
from . import routes

Krok 2: Przeniesienie tras

  1. Skopiuj funkcje z app.py do blueprints/<nazwa>/routes.py
  2. Zmień @app.route na @bp.route
  3. Zaktualizuj importy (używaj from extensions import limiter)
  4. Wewnętrzne url_for: użyj .endpoint (z kropką)

Krok 3: Rejestracja + aliasy

# blueprints/__init__.py
from blueprints.<nazwa> import bp as <nazwa>_bp
app.register_blueprint(<nazwa>_bp)

_create_endpoint_aliases(app, <nazwa>_bp, {
    'stara_nazwa': '<nazwa>.nowa_nazwa',
    # ...
})

Krok 4: Dezaktywacja duplikatów w app.py

# PRZED:
@app.route('/endpoint')
def funkcja():

# PO:
# @app.route('/endpoint')  # MOVED TO <nazwa>.<endpoint>
def _old_funkcja():

Krok 5: Test

python3 -c "from app import app; print('OK')"
# Test wszystkich endpointów

Krok 6: Cleanup (po weryfikacji na PROD)

Usuń funkcje z prefiksem _old_ z app.py.


Harmonogram

Szczegółowy plan: docs/MODULAR_MONOLITH_PLAN.md

Podsumowanie faz

Faza Zakres Routes Status
1 reports, community, education 19 WDROŻONA
2a auth + public + cleanup 31 WDROŻONA
3 forum (10 routes) 10 WDROŻONA
4 messages + notifications (11 routes) 11 WDROŻONA
5 chat (9 routes) 9 WDROŻONA
6.1 admin Part 1 (recommendations, users, fees, calendar) 19 WDROŻONA
6.2 admin Part 2 (seo, analytics, ai-usage, status, etc.) ~41
7 audits (6 modułów) ~35
8 zopk (5 modułów) ~32
9 api misc, honeypot ~25
10 final cleanup -

Cel końcowy: Redukcja app.py z 15,570 → ~500 linii


Metryki optymalizacji

Po Fazie 1 (2026-01-28)

  • app.py: 15,570 → 13,699 linii (-12%)

Po Fazie 2a (2026-01-31)

  • app.py: 15,577 → 13,820 linii
  • Usunięto: 1,757 linii (11.3%)
  • Nowe pliki:
    • blueprints/auth/routes.py (1,040 linii)
    • blueprints/public/routes.py (862 linii)

Po Fazie 3 - Forum (2026-01-31)

  • app.py: 13,820 → 13,398 linii
  • Usunięto: 422 linie (3.1%)
  • Nowe pliki:
    • blueprints/forum/__init__.py
    • blueprints/forum/routes.py (450 linii)

Po Fazie 6.1 - Admin Part 1 (2026-01-31)

  • app.py: 12,600 → 11,774 linii (-826 linii)
  • Nowe pliki:
    • blueprints/admin/__init__.py (12 linii)
    • blueprints/admin/routes.py (828 linii)
  • Trasy przeniesione: 19 (recommendations: 3, users: 8, fees: 5, calendar: 3)
  • UWAGA: Trasy AI-parse pozostają w app.py

Łączna redukcja app.py

  • Start: 15,570 linii
  • Po Fazie 1: 13,699 linii (-12.0%)
  • Po Fazie 2a: 13,820 linii (-11.2% od startu)
  • Po Fazie 3: 13,398 linii (-13.9% od startu)
  • Po Fazie 4: 13,058 linii (-16.1% od startu)
  • Po Fazie 5: 12,600 linii (-19.1% od startu)
  • Po Fazie 6.1: 11,774 linii (-24.4% od startu)
  • Cel końcowy: ~500 linii

Weryfikacja przed wdrożeniem

Checklist DEV

# 1. Import aplikacji
python3 -c "from app import app; print('OK')"

# 2. Test endpointów
python3 -c "
from app import app
with app.test_client() as c:
    assert c.get('/').status_code == 200
    assert c.get('/login').status_code == 200
    assert c.get('/health').status_code == 200
print('All endpoints OK')
"

# 3. Test url_for (aliasy)
python3 -c "
from app import app
from flask import url_for
with app.test_request_context():
    assert url_for('login') == '/login'
    assert url_for('auth.login') == '/login'
    assert url_for('index') == '/'
    assert url_for('public.index') == '/'
print('Aliases OK')
"

Checklist PROD

# Po wdrożeniu
curl -sI https://nordabiznes.pl/health | head -1
curl -sI https://nordabiznes.pl/ | head -1
curl -sI https://nordabiznes.pl/login | head -1
curl -sI https://nordabiznes.pl/release-notes | head -1

Metodologia Bezpiecznego Wdrażania (OBOWIĄZKOWA)

INCYDENT 2026-01-31: Awaria produkcji spowodowana niedziałającymi aliasami. Szablony używały url_for('admin_seo') ale alias nie został utworzony.

Zasady PRZED przeniesieniem trasy do blueprintu

  1. NAJPIERW zaktualizuj szablony - zmień url_for('stara_nazwa') na url_for('blueprint.endpoint')
  2. Wdróż zmianę szablonów - przetestuj na produkcji
  3. DOPIERO POTEM przenieś trasę do blueprintu

Zasada: Pełne nazwy blueprintów (NIE aliasy)

# ❌ BŁĘDNIE - aliasy są zawodne
url_for('admin_seo')

# ✅ PRAWIDŁOWO - pełna nazwa blueprintu
url_for('admin.admin_seo')

Dlaczego: Aliasy mogą nie działać dla tras w oddzielnych plikach. Pełne nazwy są jawne i niezawodne.

Checklist PRZED każdym deploy

# 1. Test importu
python3 -c "from app import app; print('OK')"

# 2. Test renderowania strony głównej (NIE tylko status!)
curl -s https://localhost:5000/ | head -50

# 3. Test url_for dla przeniesionych endpointów
python3 -c "
from app import app
from flask import url_for
with app.test_request_context():
    print(url_for('admin.admin_seo'))  # Musi działać
"

# 4. Dopiero po pozytywnych testach - deploy na PROD

Procedura przenoszenia trasy (NOWA)

  1. Audit szablonów - znajdź wszystkie url_for('nazwa_trasy') w templates/
  2. Zaktualizuj szablony - zmień na url_for('blueprint.nazwa_trasy')
  3. Wdróż szablony - commit, push, deploy, test PROD
  4. Utwórz trasę w blueprincie - skopiuj kod do blueprints/
  5. Skomentuj trasę w app.py - prefix _old_
  6. Test lokalny - import + renderowanie stron
  7. Deploy - commit, push, deploy
  8. Test PROD - sprawdź czy strony się renderują
  9. Cleanup - usuń martwy kod z app.py

Lekcje na przyszłość

  1. url_for w szablonach:

    • ZAWSZE używaj pełnych nazw: url_for('blueprint.endpoint')
    • NIE polegaj na aliasach - są zawodne
    • Wewnątrz blueprintu: url_for('.endpoint') (z kropką)
  2. Kolejność operacji:

    • NAJPIERW szablony - zaktualizuj url_for
    • Potem blueprinty
    • Cleanup dopiero po teście PROD
  3. Bezpieczeństwo:

    • Zawsze testuj renderowanie stron, nie tylko status HTTP
    • Prefix _old_ dla zdezaktywowanych funkcji
    • Rollback: odkomentuj @app.route

Kontakt

W razie problemów z wdrożeniem sprawdź:

  • Logi: /var/log/nordabiznes/
  • Health check: curl https://nordabiznes.pl/health
  • Rollback: git revert HEAD && git push