Buscar en la documentación

notifications

Avisos personales del centro de notificaciones y su catálogo de tipos.

Avisos de cada persona sobre lo que pasa en sus incidentes (ADR-0077). No copian textos: apuntan al mensaje o al registro del historial que los originó, y de ahí salen quién lo hizo y qué cambió.

notification_types

ColumnaTipoRestriccionesDescripción
idTINYINT UNSIGNEDPK
codeVARCHAR(40)UNIQUE, NOT NULLcomment_received, incident_assigned, status_changed, incident_reopened, reopen_rejected y los de coordinación unassigned_created, critical_created, reopen_requested, incident_overdue (ADR-0085)
nameVARCHAR(80)NOT NULLNombre visible
categoryVARCHAR(20)NOT NULL, CHECK IN ('conversations', 'activity')Pestaña del centro de notificaciones
created_at, updated_atTIMESTAMP

notifications

ColumnaTipoRestriccionesDescripción
idBIGINT UNSIGNEDPKClave interna; también ordena la lista
ulidCHAR(26)UNIQUE, NOT NULLIdentificador público (API)
user_idBIGINT UNSIGNEDFK → users, NOT NULLA quién va el aviso
notification_type_idTINYINT UNSIGNEDFK → notification_types, NOT NULLQué tipo de aviso es
incident_idBIGINT UNSIGNEDFK → incidents, NOT NULLIncidente del aviso
comment_idBIGINT UNSIGNEDFK → incident_comments, NULLEl último mensaje, en los avisos de conversación
activity_idBIGINT UNSIGNEDFK → incident_activities, NULLEl registro del historial, en los avisos de actividad
occurrencesSMALLINT UNSIGNEDNOT NULL, por defecto 1Mensajes agrupados en el aviso
read_atTIMESTAMPNULLCuándo lo leyó
created_atTIMESTAMPNOT NULLCuándo se creó (UTC)
pending_comment_incident_idBIGINT UNSIGNEDCalculada (STORED)incident_id mientras es un aviso de mensajes sin leer; NULL después

Restricciones

RestricciónRegla
chk_notifications_sourcecomment_id IS NULL OR activity_id IS NULL: un aviso sale de un mensaje o de un registro del historial, no de los dos
UNIQUE (user_id, pending_comment_incident_id)Un solo aviso de mensajes sin leer por persona e incidente (el índice único admite varios NULL)
FK user_idCASCADE: los avisos son de la persona y no tienen sentido sin ella
FK activity_idCASCADE: un aviso no tiene sentido sin el registro que lo originó (por ejemplo, si el historial se archiva)
FK incident_id, comment_idRESTRICT: incidentes y mensajes no se borran de verdad (borrado lógico), y MySQL no admite CASCADE en columnas de las que depende una columna calculada
FK notification_type_idRESTRICT: un tipo en uso no se borra

Índices

ÍndiceUso
ulid (único)Marcar uno como leído y pedir los anteriores a uno (before)
(user_id, id)La lista de una persona, de la más nueva a la más vieja, filtrada por los ids de los tipos de la pestaña
(user_id, read_at)Contar las sin leer de cada pestaña y marcarlas como leídas
(user_id, pending_comment_incident_id) (único)Encontrar el aviso de mensajes sin leer de un incidente para sumarle uno
created_atLa limpieza diaria

Validados con EXPLAIN ANALYZE sobre 60.000 avisos: la página de 20 tarda 0,8 ms y las sin leer menos de 0,1 ms.

Sin updated_at

Lo único que cambia es la lectura, que tiene su propia columna. Un aviso de mensajes que suma uno se reemplaza por uno nuevo (para que suba al primer lugar), no se actualiza.

Retención

Se borran a los 90 días de creados, leídos o no (notifications:prune, configurable con NOTIFICATIONS_RETENTION_DAYS).

Dónde está en el código