Detalls tècnics de la implementació de cada servei. Per a la visió general, els fluxos de la Saga i les decisions de disseny, vegeu architecture.md.
Classes principals:
CreateOrder— valida els ítems, calcula eltotal_amounti persisteix l'ordre i els seus ítems en una sola transacció; publicaReserveStockRequestedSagaOrchestrator— rep cada esdeveniment i aplica la transició d'estat corresponent; comprova l'estat actual abans de transicionar per evitar processament duplicatInventoryEventsConsumer,PaymentEventsConsumer— consumidors Kafka que deleguen aSagaOrchestrator
Simplificacions:
- El
total_amountes calcula al service d'aplicació a partir dels preus enviats pel client, sense validació de preus al servidor. - No s'aplica CQRS; el mateix model serveix per a escriptura i lectura.
Classes principals:
ReserveStock— obre una transacció, bloqueja la fila deProductStockambFOR UPDATE, comprova l'estoc disponible i crea laStockReservation; comprova idempotència perorder_idabans d'executarReleaseReservation— restaura la quantitat aProductStocki marca la reserva comreleasedexpire_reservations(rake task) — detecta reservespendingambexpires_atpassat, restaura l'estoc i publicaReservationExpired
Simplificacions:
- L'expiració de reserves requereix execució manual o via cron extern; no hi ha cap mecanisme automàtic.
- No es valida l'existència del
product_idabans de fer la reserva; si no existeix, falla amb una excepció.
Classes principals:
ProcessPayment— comprova idempotència perorder_id; si ja existeix unPayment, re-publica el resultat sense re-processar; si no, crea elPaymenti simula el resultat ambrand < SUCCESS_RATE
Simplificacions:
- Simulació probabilística amb 80% d'èxit (
SUCCESS_RATE = 0.8). Per forçar fallades en proves, canviar temporalment a0.0i recrcar el contenidor. - No hi ha integració amb cap passarel·la de pagament real.
- No s'implementen reintents en cas d'error tècnic.
Configuració rellevant:
- Client: Karafka 2.5 amb WaterDrop per la publicació síncrona (
produce_sync) initial_offset: earliesta tots els consumidors — necessari per no perdre missatges en tòpics nous quan el consumidor s'inicia després de la publicacióorder_idcom a clau de partició — garanteix l'ordre dels missatges per a una mateixa comanda
Problema trobat durant el desenvolupament:
Amb initial_offset: latest (valor per defecte), els consumidors ignoraven tots els missatges publicats abans del seu arrencada. En un entorn de prototip on els serveis no sempre arrenquen en ordre, això provocava que les comandes quedessin encallades en CREATED. Canviar a earliest va resoldre el problema, tot i que en producció caldria una estratègia més acurada de gestió d'offsets.