Skip to content

challenge/josue-mapelli#13

Open
doneus wants to merge 1 commit intoyaperos:mainfrom
doneus:challenge/josue-mapelli
Open

challenge/josue-mapelli#13
doneus wants to merge 1 commit intoyaperos:mainfrom
doneus:challenge/josue-mapelli

Conversation

@doneus
Copy link
Copy Markdown

@doneus doneus commented Apr 13, 2026

Challenge Elegido y Por Qué

Elegí Challenge 1 — Payment settlement pipeline.

Este challenge es el que mejor se alinea con las expectativas de un rol tech-lead/staff porque estresa fundamentos de sistemas distribuidos de punta a punta: límites transaccionales, confiabilidad del outbox, idempotencia ante redelivery y recuperación frente a fallas de broker/runtime.

Decisiones Arquitectónicas Clave y Alternativas Rechazadas

  1. Transactional outbox por encima de publicación directa al broker dentro de la transacción DB
  • Decisión: PaymentService persiste payments + outbox_events de forma atómica en una sola transacción local.
  • Rechazado: publicar a Kafka dentro de la transacción.
  • Motivo del rechazo: no existe atomicidad real entre COMMIT de base de datos y send al broker (son dos sistemas distintos). Eso abre estados inconsistentes: pago confirmado sin evento publicado o evento publicado sin estado durable ante fallos intermedios/reintentos. Además, viola una restricción explícita del challenge.
  1. Boundary de runtime separado para relay por encima de scheduler en proceso
  • Decisión: proceso dedicado apps/relay que hace polling del outbox y publica en Kafka.
  • Rechazado: relay con setInterval dentro del proceso API.
  • Motivo del rechazo: mezclar relay con API acopla el plano sincrónico (HTTP intake) con el asíncrono (entrega de eventos), degradando ambos bajo carga o incidentes. Mantener el relay separado permite escalar independientemente, aplicar deploy/restart sin afectar intake, aislar fallas del broker y operar con ownership/observabilidad clara por runtime.
  1. Idempotencia del lado consumidor, claveada por eventId
  • Decisión: deduplicación con receipts sobre consumerName + eventId y persistencia de acknowledgements por consumidor.
  • Rechazado: depender de idempotencia del productor/API como control principal de redelivery.
  • Motivo del rechazo: el challenge espera que la idempotencia viva en el lado consumidor.
  1. Status query derivado de acknowledgements (eventual consistency)
  • Decisión: la finalización requiere resultados de consumidores obligatorios (fraud, ledger); notify es informativo.
  • Rechazado: estado settled sincrónico en el intake del pago.
  • Motivo del rechazo: inconsistente con el flujo asíncrono de eventos y garantías reales de entrega.
  1. Bootstrap explícito de topics por encima de auto-create del broker
  • Decisión: compose inicializa payment.created.v1 y payment.failed.v1; auto-create deshabilitado.
  • Rechazado: creación implícita de topics.
  • Motivo del rechazo: comportamiento de arranque no determinista entre entornos.
  1. Consumer runner autorecuperable por encima de startup de un solo intento
  • Decisión: el runner de consumidores del API reintenta cuando Kafka/topic no está disponible y reinicia tras fallas en runtime.
  • Rechazado: intento único de arranque.
  • Motivo del rechazo: tras caídas transitorias del broker, el arranque de un solo intento deja al sistema degradado indefinidamente.

Qué Haría Distinto Con Más Tiempo

  1. Construir tests de integración E2E completos (API + relay + Kafka + Postgres) para escenarios de caída/recuperación/replay.
  2. Agregar observabilidad de producción: profundidad de outbox, consumer lag, correlation IDs e indicadores de readiness/health por runtime.
  3. Incorporar política formal de retry/backoff con jitter y límites configurables para relay y consumidores.
  4. Mejorar gobernanza de eventos con política de versionado y chequeos de compatibilidad de contratos.
  5. Agregar flujo operativo de DLT (herramientas de triage/replay) y runbooks para incidentes de broker/topic.

Limitaciones / Atajos Conocidos

  1. Los side effects de Fraud/Ledger/Notify están scaffolded (basados en logs), sin integración con servicios downstream reales.
  2. La emisión de payment.settled.v1 no está implementada; el settlement actualmente se deriva por query desde acknowledgements.
  3. La publicación a DLT está implementada, pero no la automatización de consumo/triage de DLT.
  4. La infraestructura local es Redpanda/Postgres de un solo nodo; sin validación de HA ni fallas por partición.
  5. Authn/authz del API y aislamiento multi-tenant quedaron fuera de alcance en esta implementación.

Run Locally

  1. Install dependencies:

    npm install
  2. Start infrastructure:

    npm run infra:up
  3. Run API and relay in separate terminals:

    npm run start:api
    npm run start:relay
  4. Run tests:

    npm test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant