OPCIÓN A: A2 Virtual Scroll + A3 Celery + A4 asyncpg PoC + A5 particionamiento

A2 — Virtual scroll en tablas grandes:
- Nuevo helper VirtualScroll en pos/static/js/virtual-scroll.js
- inventory.js: tabla de productos con virtual scroll
- customers.js: tabla de clientes con virtual scroll
- fleet.js: renderMaintenance() y renderHistory() con virtual scroll
- Templates envueltos en .vs-container para scroll

A3 — Celery worker queue:
- pos/celery_app.py + pos/tasks.py (warm cache, bulk import, reports)
- Blueprint tasks_bp.py con endpoints /pos/api/tasks/*
- Script scripts/start_celery.sh

A4 — asyncpg + Quart PoC:
- pos/async_catalog.py: endpoint /pos/api/catalog/async-search
- scripts/benchmark_async_catalog.py: benchmark Flask vs Quart

A5 — Particionar vehicle_parts:
- scripts/partition_vehicle_parts.py: migración segura por hash (16 particiones)
- Soporta --dry-run, --skip-swap, --skip-drop

Tests: 36/36 pasando
This commit is contained in:
2026-04-27 09:53:36 +00:00
parent 042acd6207
commit a1be8dd0ea
15 changed files with 998 additions and 145 deletions

29
pos/celery_app.py Normal file
View File

@@ -0,0 +1,29 @@
"""Celery application configuration for Nexus POS background tasks."""
import os
from celery import Celery
REDIS_URL = os.environ.get('REDIS_URL', 'redis://localhost:6379/0')
# Use Redis DB 1 for Celery to avoid clashing with app cache (DB 0)
BROKER_URL = os.environ.get('CELERY_BROKER_URL', REDIS_URL.replace('/0', '/1'))
BACKEND_URL = os.environ.get('CELERY_RESULT_BACKEND', REDIS_URL.replace('/0', '/1'))
celery = Celery(
'nexus',
broker=BROKER_URL,
backend=BACKEND_URL,
include=['tasks'],
)
celery.conf.update(
task_serializer='json',
accept_content=['json'],
result_serializer='json',
timezone='America/Mexico_City',
enable_utc=True,
task_track_started=True,
task_time_limit=3600, # 1 hour hard limit
task_soft_time_limit=3300, # 55 min soft limit
worker_prefetch_multiplier=1,
result_expires=86400, # Results expire after 24h
)