Como no especifica cuál sería el propósito de la base de datos de "escritura", supondré aquí que lo que quiere decir es esto: al registrar una nueva actualización en un agregado, en lugar de reconstruir el agregado desde el almacén de eventos, usted levantarlo de la base de datos "escribir", validar el cambio y emitir un evento.
Si esto es lo que quiere decir, entonces esta estrategia creará una condición para la inconsistencia: si una nueva actualización ocurre antes de que la última tuviera la oportunidad de ingresar a la base de datos de "escritura", la nueva actualización terminará validada contra datos obsoletos, potencialmente emitiendo un evento "imposible" (es decir, "no permitido") y corrompiendo el estado del sistema.
Por ejemplo, considere un ejemplo permanente de reservar asientos en un teatro. Para evitar la doble reserva, debe asegurarse de que el asiento que se está reservando no esté ocupado, esto es lo que llama "validación". Para hacer eso, almacena una lista de asientos ya reservados en la base de datos "escribir". Luego, cuando llega una solicitud de reserva, verifica si el asiento solicitado está en la lista y, si no, emite un evento "reservado", de lo contrario responde con un mensaje de error. Luego ejecuta un proceso de proyección, donde escucha los eventos "reservados" y agrega los asientos reservados a la lista en la base de datos "escribir".
Normalmente, el sistema funcionaría así:
1. Request to book seat #1
2. Check in the "already booked" list: the list is empty.
3. Issue a "booked seat #1" event.
4. Projection process catches the event, adds seat #1 to the "already booked" list.
5. Another request to book seat #1.
6. Check in the list: the list contains seat #1
7. Respond with an error message.
Sin embargo, ¿qué pasa si las solicitudes llegan demasiado rápido y el paso 5 ocurre antes del paso 4?
1. Request to book seat #1
2. Check in the "already booked" list: the list is empty.
3. Issue a "booked seat #1" event.
4. Another request to book seat #1.
5. Check in the list: the list is still empty.
6. Issue another "booked seat #1" event.
Ahora tiene dos eventos para reservar el mismo asiento. El estado del sistema está dañado.
Para evitar que esto suceda, nunca debe validar las actualizaciones contra una proyección. Para validar una actualización, reconstruye el agregado desde el almacén de eventos y luego valida la actualización contra él. Después de eso, emite un evento, pero utiliza la protección de marca de tiempo para asegurarse de que no se hayan emitido nuevos eventos desde la última vez que leyó en la tienda. Si esto falla, solo vuelve a intentarlo.
La reconstrucción de agregados de la tienda de eventos puede conllevar una penalización de rendimiento. Para mitigar esto, puede almacenar instantáneas agregadas directamente en la secuencia del evento, etiquetadas con el ID del evento desde el que se creó la instantánea. De esta manera, puede reconstruir el agregado cargando la instantánea más reciente y reproduciendo solo los eventos que vinieron después, en lugar de reproducir siempre todo el flujo de eventos desde el principio de los tiempos.