Ubicación
racks/tasks.py (línea ~241)
Task periódica de Huey (job queue de background).
Definición
@db_periodic_task(crontab(hour="4", minute="15"))
@lock_task("rack-integrity-snapshots")
def compute_integrity_snapshots():
"""
Computa y persiste la foto de integridad plano↔realidad de cada org.
Recolección interna para calibración del gate #202 — no alimenta UI todavía.
Corre con bypass GUC ('0') + scoping manual ORM, patrón core-0029.
"""
from core.models import Organization
from racks.services import integrity
orgs = 0
rows = 0
for org in Organization.objects.all():
try:
result = integrity.compute_integrity(org)
rows += integrity.persist_snapshots(org, result)
orgs += 1
except Exception as e:
logger.error(f"Integrity snapshot failed for org {org.id}: {e}")
logger.info(f"Integrity snapshots: {orgs} orgs, {rows} filas")
return {"orgs": orgs, "rows": rows}
Semántica
Cuándo Corre
Diariamente a las 04:15 UTC (tras backups nocturnos a las 03:30).
Decoradores:
@db_periodic_task(crontab(...))— registro automático con Huey@lock_task("rack-integrity-snapshots")— solo 1 instancia simultáneamente (evita race conditions)
Qué Hace
- Itera todas las Organization (sin filtro)
- Para cada org: llama a
integrity.compute_integrity(org)(parámetros default: 7 días, 30 min) - Persiste el resultado con
integrity.persist_snapshots(org, result) - Registra en logger: org exitosas y total de filas (racks + resúmenes)
- Si falla una org: registra error, continúa con la siguiente
Retorno: dict con {"orgs": count, "rows": count}
RLS y Seguridad
La task corre con GUC app.current_org_id = '0' (bypass admin admin) porque:
- Huey no tiene request HTTP → no hay middleware que setee GUC automáticamente
- El bypass ‘0’ es estándar en tasks de background (ver
TenantRLSMiddleware) - Scoping manual ORM: itera
Organization.objects.all()explícitamente - Cada snapshot escrito con
organization=orgfijo → RLS lo aisla automáticamente
Patrón idéntico a purge_deleted_organizations (core/tasks.py) y run_full_backup (racks/tasks.py).
Idempotencia
Llamar 2 veces el mismo día no duplica filas:
- Constraint único por (org, rack, date) con
nulls_distinct=False persist_snapshots()usaupdate_or_create()- 2ª llamada actualiza counts/findings/métricas, no crea nuevas filas
Útil si:
- La task falla a mitad y se reintenta
- Un admin corre
rack_integrity_probe --org X --saveel mismo día - El schedule cambia (ejemplo: 04:15 pasa a 06:00 en DST)
Logging
Info (Éxito Normal)
Integrity snapshots: 47 orgs, 204 filas
Significa: procesadas 47 organizaciones, escritas 204 filas (racks + resúmenes).
Error (Org Individual Falla)
Integrity snapshot failed for org 15: [ErrorMessage]
Registra el error pero sigue procesando otras orgs — no interrumpe.
Ejemplos de fallos capturados:
Organization.DoesNotExist(data inconsistency)DeviceProfile.MultipleObjectsReturned(datos corruptos)IntegrityErroren persistencia (constraints violados)
Requisitos Previos
- Huey configurado en
settings/ - Worker de Huey corriendo (servicio
hueyen Docker o systemd) - Database accesible desde worker
- Migraciones 0014 + 0015 aplicadas (tabla + RLS)
- Services/integrity.py presente (código nuevo)
Rendimiento
Orden de complejidad: O(n*m) donde n=orgs, m=dispositivos/org.
Benchmarks (estimados):
- Org con 1 rack + 40 devices: ~100ms
- Org con 10 racks + 400 devices: ~1s
- 47 orgs (escala actual): ~30-45 segundos total
Timeout de Huey: por defecto 10 min (suficiente). Ajustable en settings si es necesario.
Configuración en settings
# config/settings/production.py
HUEY = {
'huey_class': 'huey.PriorityQueue',
'name': 'crearack-huey',
'immediate': False, # False = async en production
'utc': True,
'scheduler_interval': 60, # poll cada 60 sec para tareas periódicas
'db_table': 'huey_task', # tabla de storage
# ...más config
}
La tarea aparecerá automáticamente en la lista de periódicas de Huey.
Integración con Huey CLI
Listar tareas:
python manage.py huey_status
Verá compute_integrity_snapshots con schedule 04:15 UTC.
Forzar ejecución manual:
python manage.py huey_consumer --immediate # en dev, corre sincrónico
# → inmediatamente ejecuta todas las periódicas
O desde shell:
from racks.tasks import compute_integrity_snapshots
result = compute_integrity_snapshots()
print(result) # {"orgs": 47, "rows": 204}
Ejemplos de Query Post-Task
Tras la task, analizar snapshots:
# Snapshots de hoy
today = timezone.localdate()
snapshots = RackIntegritySnapshot.objects.filter(date=today, rack__isnull=False)
# Por org
org = Organization.objects.get(id=1)
org_summary = RackIntegritySnapshot.objects.get(
organization=org, rack=None, date=today
)
print(f"Org {org.name}: fidelity {org_summary.fidelity_pct}%")
# Racks con fidelidad baja
low_fidelity = snapshots.filter(fidelity_pct__lt=80)
for snap in low_fidelity:
print(f"{snap.rack.name}: {snap.fidelity_pct}%")
Monitoreo y Alertas (Futuro)
Cuando F2/F3 añadan dashboards:
- Degradación de fidelity: si cae >10% día-a-día → alertar
- Aumento de undocumented: si >X equipos nuevos/día → revisar
- Task falla: Huey registra si
compute_integrity_snapshotsfalla → healthcheck
Hoy, sin UI, solo monitoreamos logs (ver logging arriba).
Relación con Otros Components
compute_integrity_snapshots (task Huey, diaria)
↓
├─ integrity.compute_integrity(org) ← quién computa
│ ├─ Device.objects.filter(rack__organization=org)
│ ├─ DeviceProfile.objects.filter(organization=org)
│ └─ MonitoringTarget.objects.filter(organization=org)
│
└─ integrity.persist_snapshots(org, result) ← quién guarda
└─ RackIntegritySnapshot.objects.update_or_create()
rack_integrity_probe (comando, manual)
├─ compute_integrity() ← reutiliza
└─ persist_snapshots() ← reutiliza (si --save)
Notas de Operación
- Timezone: toda la computación en UTC;
datees DateField (sin hora) - Datos históricos: snapshots se acumulan → base de datos crece ~50 filas/día (47 orgs)
- Retention: sin política de purga hoy; considerar en F2/F3 si ocupan espacio
- Frescura de datos: corre a 04:15, datos de “ayer” se persisten (patrón estándar de batch nightly)
Debugging
Si la task falla silenciosamente:
- Chequear logs de Huey:
docker logs crearack-huey - Verificar DB de Huey:
SELECT COUNT(*) FROM huey_task(verificar queue limpia) - Verificar RLS en la tabla:
SELECT COUNT(*) FROM racks_rackintegritysnapshot - Ejecutar manualmente en shell para ver el traceback completo
Véase también
- [[feature—racks—motor-integridad-f1]]
- [[entity—racks—service—integrity]]
- [[entity—racks—model—rack-integrity-snapshot]]
- [[entity—racks—command—rack-integrity-probe]]