/proyectos/prereservas-rabbitmq
Retención de cupos con expiración asíncrona
Prereservas con un hold de 15 minutos que se liberan solas mediante colas durables con TTL y Dead Letter Exchange, sin tocar el tiempo de respuesta de la compra.
15 minhold por prereserva, liberado sin jobs programados
- Java
- Spring Boot 3
- RabbitMQ
- PostgreSQL
Contexto
En una plataforma de venta de entradas para sitios patrimoniales, el aforo diario es limitado y la demanda llega en picos. Cuando un visitante o una agencia inicia una compra, el cupo debe quedar retenido mientras completa el registro y el pago; si no termina, el cupo tiene que volver al inventario.
Problema
La versión inicial liberaba cupos con un proceso programado que recorría las prereservas vencidas. Eso generaba dos efectos: cupos “fantasma” bloqueados hasta la siguiente ejecución y consultas pesadas sobre la tabla de reservas justo en las horas de mayor tráfico.
Restricciones
- El flujo de compra no podía volverse más lento: la expiración tenía que ocurrir fuera de la petición del usuario.
- Los pagos con la pasarela pueden confirmarse unos segundos después del vencimiento, así que hacía falta un periodo de gracia.
- La liberación debía ser idempotente: un mensaje repetido no puede devolver dos veces el mismo cupo.
Solución
Cada prereserva publica un mensaje en una cola durable con TTL igual al tiempo de hold. La cola no tiene consumidores; cuando el mensaje vence, RabbitMQ lo enruta al Dead Letter Exchange, cuyo consumidor verifica el estado y libera el cupo solo si la reserva sigue pendiente.
Puntos clave del diseño:
- Colas y mensajes durables para no perder holds si el broker se reinicia.
- Verificación de estado antes de liberar: el consumidor actualiza solo si la reserva sigue pendiente, con lo que los reintentos son seguros.
- Periodo de gracia configurable para confirmar pagos tardíos antes de devolver el cupo.
Resultado medido
- Los cupos vuelven al inventario en cuanto vence el hold, sin esperar a un job.
- Desaparecieron las consultas de barrido sobre reservas en horas pico.
- El tiempo de respuesta del flujo de compra no aumentó: publicar el mensaje cuesta milisegundos.
Aprendizajes
TTL + DLX es una forma simple de tener “temporizadores distribuidos” sin infraestructura extra. Lo importante no es la cola, sino que el consumidor sea idempotente y que el estado de la base de datos sea la fuente de verdad.