Borrar el registro principal y perder la capacidad de responder «cuánto tráfico generó esta cuenta antes de irse» son dos resultados distintos, y confundirlos es cómo los tickets de soporte se convierten en incidentes. El archivado evita que lo segundo desaparezca con lo primero.
// app/Listeners/SiteDeletedListener.php
class SiteDeletedListener
{
public function handle(SiteDeletedEvent $event): void
{
Archive::create([
'analytics_id' => $event->site->id,
'url' => $event->site->name,
'data' => $event->aggregations->toArray(),
'deleted_at' => now(),
]);
}
}
Archive: una tabla pequeña y deliberadamente genérica. No preserva el esquema original: preserva una instantánea JSON de lo que importaba en el momento del borrado.
SiteDeletedEvent: lleva el sitio y sus agregaciones ya calculadas, no filas en crudo. Archivar el resumen y no los datos de origen es lo que mantiene la tabla de archivo barata para siempre en lugar de convertirse en una segunda copia del mismo problema de crecimiento que intentabas resolver.
El listener, no el código de borrado: la escritura de archivo está desacoplada de lo que disparó el borrado, así que cualquier cosa que emita el evento obtiene la misma garantía sin duplicar la lógica en cada punto de llamada.
Por eso también existe una herramienta de operaciones que muestra los metadatos de un sitio borrado y su archivo de analítica lado a lado. Archivar no sirve de nada si nadie puede encontrar lo archivado seis meses después. Si no puedes volver a consultar un registro borrado, no lo archivaste: sólo retrasaste el borrado.
Demostrar que guardas y por que
Las reglas de retención y las tablas de archivo sólo hacen su trabajo si alguien puede señalarlas y decir «aquí está por qué guardamos esto, y aquí está la prueba de que ocurre». Una política que nadie puede verificar es una política en la que nadie confía, incluido el equipo que la escribió.
Dos cosas hacen que una política sea demostrable en lugar de aspiracional. Primero, los umbrales viven en configuración, no en un comentario ni en la memoria de alguien. Cambia la política, cambia la configuración, y todos los que la aplican la recogen igual. Segundo, la evidencia de que una política se ejecutó tiene que ser inspeccionable a posteriori: puedes abrir una cuenta borrada y ver, concretamente, qué sobrevivió en el archivo y qué no.
Ninguna de las dos es glamurosa. Ambas son la diferencia entre «tenemos una política de retención» como frase en un documento y una política de retención que puedes defender de verdad cuando alguien pregunte.
Resumen
Propiedad y coste:
- [X] Cada tabla y cada blob JSON tiene un dueño con nombre y una razón de una línea para existir
- [X] «No sé por qué guardamos esto» se trata como un fallo, no como un encogimiento de hombros
Retención:
- [X] La retención vive en el modelo (
Prunable,prunable()), no enterrada en un comando suelto - [X] Un único barrido programado cubre todos los modelos podables, no un comando por tabla
Migraciones y rellenos:
- [X] Las migraciones sobre tablas vivas usan
cursor(), nunca paginan escrituras conchunk()por desplazamiento - [X] Los comandos de relleno llevan
--dry-run, lecturas por lotes y una comprobación de «saltar si no cambia» para poder reanudarse - [X] Los cambios de esquema aditivos comprueban la existencia primero, para sobrevivir a ejecutarse dos veces
Borrado y archivado:
- [X] Una petición de borrado se particiona por propiedad antes de desmantelar nada
- [X] Borra de forma dura lo que sólo tenía sentido por esa identidad; conserva o archiva lo que aún tiene valor
- [X] Los datos fríos se archivan como una instantánea deliberada, desacoplada del disparador del borrado, y siguen siendo inspeccionables después
Los datos no se gestionan solos, y fingir que lo harán es cómo un script de limpieza de directorios se convierte en toda tu estrategia de datos. Decide quién los posee, decide cuánto los guardas y decide qué les pasa al salir. Hazlo una vez, a propósito, y dejarás de descubrir tu política de datos por accidente.