Files
service-finder/plans/admin_crash_and_user_repair_blueprint.md
2026-07-27 08:39:18 +00:00

10 KiB

🔧 Admin OOM Crash Fix & User Relations Repair — Code Mode Hand-off

Author: Architect Mode
Date: 2026-07-26
Target Mode: code (Fast Coder)


📊 Diagnosztikai Összefoglaló

Issue 1: Admin Frontend OOM (admin.servicefinder.hu → 500)

Jelenlegi állapot:

  • A sf_admin_frontend konténer jelenleg FUT (742MiB RAM, 0.42%), az OOM korábban történt.
  • A Dockerfile.dev node:20-slim-et használ, a CMD npm run dev (Nuxt dev mode SSR + HMR).
  • A docker-compose.yml szekcióban nincs NODE_OPTIONS környezeti változó és nincs deploy.resources.limits.memory beállítva.
  • A bot-scanner forgalom (.env probing) csak Vue Router warningokat generál, nem ez okozza az OOM-t.

Root Cause: A Nuxt 3 dev módban az SSR (Server-Side Rendering) + HMR (Hot Module Replacement) + a dashboard oldal API hívása (/api/v1/admin/users/stats) együtt képes kimeríteni a Node.js default heap limitjét (~2GB). A node:20-slim image-nek nincs explicit --max-old-space-size beállítása.

Issue 2: User 86 Wallet Status & Missing User Relations

User 86 (zs.gyongyossy@gmail.com) státusza:

  • Wallet: RENDBENidentity.wallets id=12, earned=0, purchased=0, service_coins=0, currency=HUF, org_id=45
  • Subscription: RENDBENfinance.user_subscriptions id=9, tier_id=13 (private_free_v1), is_active=true

6 aktív user-nek NINCS walletje és subscription-je:

ID Email Wallet Subscription
1 superadmin@profibot.hu MISSING MISSING
136 no_perm_1782770270_8c9970@test.com MISSING MISSING
138 no_perm_1782778366_243628@test.com MISSING MISSING
153 commission_test_gen2@test.com MISSING MISSING
154 commission_test_gen1@test.com MISSING MISSING
155 commission_test_buyer@test.com MISSING MISSING

Végpont viselkedés: get_wallet_summary ValueError-t dob ha nincs wallet → a végpont 404-et ad. Ez helyes.


🛠️ Javítási Terv

FIX-1: Admin Frontend Memory Limit

Fájl: docker-compose.yml

Módosítás — a sf_admin_frontend szekcióban:

  1. Az environment blokkhoz add hozzá:

    - NODE_OPTIONS=--max-old-space-size=4096
    
  2. Adj hozzá egy deploy blokkot:

    deploy:
      resources:
        limits:
          memory: 8G
    

A módosított szekció:

  sf_admin_frontend:
    build:
      context: ./frontend_admin
      dockerfile: Dockerfile.dev
    container_name: sf_admin_frontend
    env_file: .env
    ports:
      - "8502:8502"
    environment:
      - NUXT_PORT=8502
      - NUXT_HOST=0.0.0.0
      - NUXT_PUBLIC_API_BASE_URL=https://dev.servicefinder.hu
      - NODE_OPTIONS=--max-old-space-size=4096      # ← NEW
    volumes:
      - ./frontend_admin:/app
      - /app/node_modules
    networks:
      - sf_net
      - shared_db_net
    restart: unless-stopped
    deploy:                                           # ← NEW
      resources:
        limits:
          memory: 8G

Futtatás:

docker compose up -d --force-recreate sf_admin_frontend
docker compose logs --tail=20 sf_admin_frontend

FIX-2: User Relations Repair Script

Fájl létrehozása: backend/scripts/repair_user_relations.py

Cél: Minden is_active = true user számára biztosítja:

  1. Personal Organization (fleet.organizations) — ha még nincs
  2. Wallet (identity.wallets) — ha még nincs
  3. User Subscription (finance.user_subscriptions, tier=private_free_v1) — ha még nincs

Adatbázis séma referencia:

Tábla Séma Kulcs mezők
wallets identity id (serial PK), user_id (FK), earned_credits, purchased_credits, service_coins, currency, organization_id
user_subscriptions finance id (serial PK), user_id (FK), tier_id (FK→system.subscription_tiers), valid_from, is_active
organizations fleet id (serial PK), name, full_name, display_name, folder_slug, owner_id (FK), org_type, status, is_active, ...

Alapértelmezett értékek:

  • Wallet: earned_credits=0, purchased_credits=0, service_coins=0, currency='HUF'
  • Subscription: tier_id=13 (private_free_v1), valid_from=now(), is_active=true
  • Organization: name="{user.email}'s Garage", org_type='individual', status='active', owner_id=user.id

Script pszeudokód:

#!/usr/bin/env python3
"""
User Relations Repair Script — Idempotens: csak hiányzó rekordokat hoz létre.
Futtatás: docker compose exec sf_api python3 /app/backend/scripts/repair_user_relations.py
"""
import asyncio, sys
sys.path.insert(0, '/app')
sys.path.insert(0, '/app/backend')

from app.core.database import async_session_factory
from sqlalchemy import select
from app.models.identity import User, Wallet
from app.models.finance import UserSubscription
from app.models.fleet import Organization
from datetime import datetime, timezone
from decimal import Decimal

DEFAULT_TIER_ID = 13
DEFAULT_CURRENCY = "HUF"

async def ensure_organization(db, user):
    result = await db.execute(select(Organization).where(Organization.owner_id == user.id))
    org = result.scalar_one_or_none()
    if org:
        return org.id
    folder_slug = f"user-{user.id}-{int(datetime.now(timezone.utc).timestamp())}"
    org = Organization(
        name=f"{user.email}'s Garage", full_name=f"{user.email}'s Personal Garage",
        display_name=f"{user.email}'s Garage", folder_slug=folder_slug,
        owner_id=user.id, org_type="individual", status="active",
        is_active=True, is_deleted=False, subscription_plan="FREE",
        base_asset_limit=5, purchased_extra_slots=0,
        notification_settings={}, external_integration_config={},
        is_verified=False, first_registered_at=datetime.now(timezone.utc),
        current_lifecycle_started_at=datetime.now(timezone.utc),
        lifecycle_index=1, is_anonymized=False, default_currency="HUF",
        country_code="HU", language="hu", is_ownership_transferable=False,
        visual_settings={}, is_affiliate_partner=False, aliases=[],
        tags=[], settings={}, custom_features={},
    )
    db.add(org)
    await db.flush()
    return org.id

async def ensure_wallet(db, user, org_id):
    result = await db.execute(select(Wallet).where(Wallet.user_id == user.id))
    if result.scalar_one_or_none():
        return False
    wallet = Wallet(user_id=user.id, earned_credits=Decimal('0'),
                    purchased_credits=Decimal('0'), service_coins=Decimal('0'),
                    currency=DEFAULT_CURRENCY, organization_id=org_id)
    db.add(wallet)
    await db.flush()
    return True

async def ensure_subscription(db, user):
    result = await db.execute(select(UserSubscription).where(UserSubscription.user_id == user.id))
    if result.scalar_one_or_none():
        return False
    sub = UserSubscription(user_id=user.id, tier_id=DEFAULT_TIER_ID,
                           valid_from=datetime.now(timezone.utc), is_active=True)
    db.add(sub)
    await db.flush()
    return True

async def repair_all_users():
    async with async_session_factory() as db:
        result = await db.execute(select(User).where(User.is_active == True))
        users = result.scalars().all()
        stats = {"total": len(users), "wallets_created": 0, "subs_created": 0, "errors": []}
        for user in users:
            try:
                org_id = await ensure_organization(db, user)
                if await ensure_wallet(db, user, org_id):
                    stats["wallets_created"] += 1
                if await ensure_subscription(db, user):
                    stats["subs_created"] += 1
            except Exception as e:
                stats["errors"].append(f"User {user.id}: {e}")
        await db.commit()
        print(f"=== REPAIR: total={stats['total']} wallets_new={stats['wallets_created']} subs_new={stats['subs_created']} errors={len(stats['errors'])}")
        for e in stats["errors"]: print(f"  ERR: {e}")

if __name__ == "__main__":
    asyncio.run(repair_all_users())

Futtatás:

docker compose exec sf_api python3 /app/backend/scripts/repair_user_relations.py

Ellenőrzés:

SELECT u.id, u.email, w.id as wallet_id, s.id as sub_id
FROM identity.users u
LEFT JOIN identity.wallets w ON u.id = w.user_id
LEFT JOIN finance.user_subscriptions s ON u.id = s.user_id
WHERE u.id IN (1, 136, 138, 153, 154, 155);

FIX-3 (OPTIONAL): get_wallet_summary Auto-Create

Architect döntés: NEM módosítjuk. A 404 helyes válasz. A repair script után a probléma megszűnik. A wallet auto-create a regisztrációs flow-ban garantálandó — külön feladat.


📋 Végrehajtási Sorrend (Code Mode)

# Feladat Fájl Parancs
1 NODE_OPTIONS + memory limit docker-compose.yml Szerkesztés
2 Admin restart docker compose up -d --force-recreate sf_admin_frontend
3 Repair script létrehozása backend/scripts/repair_user_relations.py Fájl létrehozása
4 Repair script futtatása docker compose exec sf_api python3 /app/backend/scripts/repair_user_relations.py
5 SQL ellenőrzés MCP Postgres query
6 Böngésző ellenőrzés https://admin.servicefinder.hu/

⚠️ Kockázatok

  1. superadmin (ID=1): Lehet hogy szándékosan nincs walletje. Ha nem kívánatos, skip-elni kell ID=1-et a scriptben.
  2. Organization folder_slug: Egyedi kell legyen. A user-{id}-{timestamp} minta garantálja.
  3. Tier ID=13: Ellenőrizve — létezik system.subscription_tiers-ben, tier_level=0.
  4. Docker restart: ~30-60 másodperc downtime a Nuxt újraépítése miatt.
  5. A repair script IDEMPOTENS: Többször futtatható, nem duplikál.