Alexei Rojas Quiroga
← Todos los proyectos

Proyecto corporativo · Presentado sin referencias a la empresa: solo arquitectura y decisiones.

Motor en Tiempo Real de Apuestas en Vivo

Workers multi-tenant de calificación, límites y liquidación en vivo

Estado
En producción
Rol
Ingeniero backend senior: arquitectura, workers de calificación y contabilidad, resiliencia en Kafka, procedimientos SQL de calificación, workers de reportes, UI administrativa en Blazor y CI/CD.

Arquitectura

  • Pipeline de calificación con cola en base de datos
  • Liquidación serializable
  • 50 apuestas por mensaje de Kafka
  • Reintentos escalonados y dead-letter
  • Escrituras idempotentes en el libro

Un juego finalizado se califica, las apuestas se liquidan, se agrupan por tenant y se aplican al libro.

Arquitectura · 10 nodos · 2 flujos
LO QUE CONSTRUÍ.NET worker se…Worker decalificación dejuegosEjecuta elprocedimiento de cali……SQL ServerBase de apuestas ycalificaciónApuestas, colas,resultados, hechos.NET worker se…Worker deliquidación deapuestasLiquida la contabilidadcon transacciones.NET worker se…Publicador outboxLotes de 50 apuestaspor mensajeKafkaTópicos deresultados portenantResultados calificadospor tenant.NET worker se…Worker desincronizaciónAplica calificación,reintenta, dead-letterASP.NET CoreAPI de integraciónde apuestasInserción ycalificaciónidempotentesSQL ServerBase del libro deapuestasApuestas, saldos,contabilidadKafkaTópicos dereintento y dead-letterBackoff y luego dead-letterChat webhookAlertas por chatAlertas de dead-lettery cuotas12345678
  • Servicio / cómputo
  • Almacén de datos
  • Cola / mensajería
  • Sistema externo
  • Síncrono
  • Asíncrono / bucle
Desplázate hacia los lados para ver todo el diagrama

Cómo fluye, paso a paso

Haz clic en un paso para saltar a él. Haz clic en un componente para ver detalles.

Qué hace

Motor multi-tenant de back-office y liquidación para el producto en vivo de un operador de apuestas deportivas en línea. Califica apuestas live simples y parlays al finalizar los juegos, publica la contabilidad en flujos Kafka por tenant, audita la integridad de las cuotas y sirve configuración de límites, reportes y una UI administrativa en Blazor.

El problema

Las apuestas en vivo generaban un alto volumen de apuestas efímeras que debían calificarse exactamente como en el libro heredado, sin doble liquidación, entre varios tenants y con estricta corrección financiera. El enfoque heredado era un flujo de calificación único y fuertemente acoplado, sin reintentos ni dead-letter y con poca visibilidad de discrepancias.

Qué construí

  • Construí un pipeline de calificación con cola en base de datos: un trigger de fin de juego ejecuta un procedimiento de calificación, encola apuestas y un worker liquida la contabilidad en transacciones SERIALIZABLE para proteger los saldos.
  • Añadí un worker estilo outbox que agrupa apuestas calificadas (50 por mensaje) en tópicos Kafka por tenant, reduciendo los viajes al broker en aproximadamente 98 por ciento frente a un mensaje por apuesta.
  • Implementé un modelo de consumo Kafka en tres niveles (tópico principal, tópico de reintento con backoff exponencial y tópico dead-letter con alertas por chat) tras una abstracción genérica de handlers.
  • Garanticé calificación idempotente mediante seguimiento único de grupos de apuestas y concurrencia optimista, y validé resultados contra el sistema heredado con una CLI de comparación que reveló variaciones de redondeo en parlays reducidos.
  • Entregué una familia de workers programados: ingesta de marcadores con dead-lettering, derivación y reconciliación de timelines, tablas de hechos semanales de mejores jugadores y hold percentage, y un auditor de integridad de líneas que compara cada apuesta aceptada con datos de mercado archivados.
  • Entregué una UI administrativa modular en Blazor (diez bibliotecas de componentes) con tema configurable por tenant y caché en Redis, además de endpoints de reportes que responden en menos de dos segundos desde hechos precalculados.

Decisiones clave y por qué

01

Cola en base de datos para calificación, Kafka para distribución

La calificación debe ser atómica con la actualización de saldos, por lo que la cola vive en el mismo almacén transaccional que las apuestas. Kafka se usa solo tras la liquidación para distribuir resultados a los tenants, donde basta entrega al menos una vez con consumidores idempotentes.

02

Tópico de reintento y dead-letter en lugar de bucles de reintento en sitio

Los mensajes fallidos salen de la ruta principal para que un mensaje venenoso no bloquee una partición. El backoff se aplica en el tópico de reintento y los fallos permanentes se comunican a operadores con contexto.

03

Agrupación en el worker outbox

Los mensajes de una sola apuesta saturaban el broker en picos. Agrupar 50 apuestas por mensaje y por tenant preservó el orden por tenant y multiplicó el rendimiento.

04

Los workers nunca tumban el host por datos malos

Los handlers devuelven una disposición explícita (confirmar, reintentar, dead-letter). Los errores permanentes de datos se envían a dead-letter y se confirman, los de infraestructura se reintentan y un endpoint de salud expone la última marca de éxito para que el monitoreo decida reinicios.

05

Hechos semanales precalculados para reportes

Agregar apuestas liquidadas bajo demanda era demasiado lento. Workers programados recalculan una ventana móvil para absorber calificaciones tardías, de modo que la API de reportes sirve tablas de hechos indexadas en segundos.

06

Clean Architecture con tipos Result

Las capas de dominio, aplicación, infraestructura y API se registran mediante métodos de extensión y las operaciones de negocio devuelven valores Result en lugar de excepciones, manteniendo explícito el mapeo de errores y simples las pruebas unitarias.

Stack tecnológico

Lenguajes
C#
Backend
.NET 10ASP.NET Core Minimal APIsPollyFluentValidation
Datos
Entity Framework CoreDapperSQL ServerRedis
Mensajería
Kafka
Frontend
Blazor WebAssemblyMudBlazor
Pruebas
xUnit
DevOps
Windows Services / IISGitLab CI
Otros
Slack webhooks