Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
67 changes: 67 additions & 0 deletions API_TESTING_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# API Testing Guide

### Cómo probar las APIs del proyecto

Este documento describe paso a paso cómo probar los endpoints del microservicio **ms-transaction**, incluyendo la creación de transacciones, validación por el microservicio anti-fraud y la consulta de transacciones por su ID externo.

Se asume que ambos microservicios están levantados localmente y que Kafka está funcionando según la configuración provista.

---

# 1. Crear una transacción (caso aprobado)

Este endpoint crea una transacción con estado inicial **pending**, la envía a Kafka, y posteriormente el microservicio **ms-anti-fraud** actualizará su estado a **approved** si el valor es menor o igual a 1000.

### **Request:**

```bash
curl --location 'http://localhost:8081/transaction' \
--header 'Content-Type: application/json' \
--data '{
"accountExternalIdDebit": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
"accountExternalIdCredit": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"tranferTypeId": 1,
"value": 500.50
}'
```

### **Respuesta esperada (inmediata):**

```json
{
"transactionExternalId": "GENERATED-ID",
"transactionType": { "name": "transfer" },
"transactionStatus": { "name": "pending" },
"value": 500.50,
"createdAt": "2025-12-05T..."
}
```

> El estado cambiará a **approved** después de que ms-anti-fraud procese el mensaje Kafka.

---

# 2. Crear una transacción (caso rechazado)

Si el valor es **mayor a 1000**, el anti-fraud debe actualizar la transacción a **rejected**.

### **Request:**

```bash
curl --location 'http://localhost:8081/transaction' \
--header 'Content-Type: application/json' \
--data '{
"accountExternalIdDebit": "f0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22",
"accountExternalIdCredit": "c1d2e3f4-a5b6-c7d8-e9f0-1a2b3c4d5e6f",
"tranferTypeId": 1,
"value": 1500.00
}'
```

### **Respuesta inicial:**

```json
{
"transactionExternalId": "GENERATED-ID",
"transactionType": { "name": "transfer"
```
151 changes: 151 additions & 0 deletions HIGH_CONCURRENCY_STRATEGY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# High Concurrency Strategy

### Cómo escalar la solución en escenarios de alto volumen de transacciones

Este documento explica las estrategias recomendadas para soportar escenarios con **alto volumen de lectura y escritura simultánea**, manteniendo consistencia, resiliencia y buen rendimiento. Todas las propuestas están alineadas con la arquitectura actual del proyecto (Java, Kafka, microservicios con enfoque hexagonal).

---

## 1. Uso de Kafka para desacoplamiento y absorción de carga

Kafka actúa como **buffer natural** entre ms-transaction y ms-anti-fraud.

Beneficios en alta concurrencia:

* Maneja millones de mensajes por segundo.
* Garantiza procesamiento secuencial por partición.
* Permite escalar consumidores horizontalmente.
* Evita que la carga de validación impacte directamente al microservicio de creación.

**Estrategia propuesta:**

* Aumentar particiones en el topic `transaction-created`.
* Habilitar múltiples instancias del anti-fraud service como **consumer group**, cada una procesando particiones diferentes.
* Usar claves (key = `transactionExternalId`) para mantener orden en mensajes relacionados a una misma transacción.

---

## 2. Idempotencia en actualización de estado

En escenarios de alto volumen, pueden generarse eventos duplicados o llegados en desorden.

**Estrategia propuesta:**

* La actualización de transacción debe ser **idempotente**:
si llega un mensaje con el mismo `transactionExternalId` y el mismo estado, la operación no debe causar inconsistencias.
* El repositorio JPA debe buscar primero por `transactionExternalId` y solo actualizar si el estado cambió realmente.

Esto ya se cumple parcialmente en la solución implementada, pero se documenta como fundamento técnico.

---

## 3. Optimistic Locking en la base de datos

Para evitar condiciones de carrera al actualizar el estado de una transacción:

**Estrategia propuesta:**

* Agregar un campo `@Version` en la entidad JPA (`@Version Long version;`)
* Esto evita que dos consumidores actualicen simultáneamente la misma fila causando inconsistencias.
* Si ocurre un conflicto, JPA lanza exception y se puede reintentar (retry simple o backoff exponencial).

---

## 4. Índices en columnas críticas

Al aumentar la carga, el tiempo de consulta puede crecer si la base no está optimizada.

**Recomendación:**

* Crear índices en:

* `transactionExternalId`
* `createdAt`
* `transactionStatus`

Esto acelera:

* búsquedas puntuales (GET transaction)
* actualizaciones basadas en ID externo

---

## 5. Segmentación de carga por microservicios

La arquitectura ya contempla separación entre:

* microservicio de creación (**ms-transaction**)
* microservicio de validación (**ms-anti-fraud**)

Para escenarios de alta concurrencia:

* Escalar **independientemente** el ms-transaction cuando crecen las escrituras.
* Escalar **independientemente** el anti-fraud cuando crece la validación.
* Kafka absorbe el desacople sin saturar ninguno de los dos.

---

## 6. Cache para lecturas intensivas (opcional)

Si aumenta mucho el volumen de lecturas (GET transaction), la base de datos puede convertirse en cuello de botella.

**Solución sugerida (opcional):**

* Cache para transacciones recién creadas o consultadas (Redis)
* Expiración corta (TTL 30-60s)

Esto reduce hasta el 80% de lecturas a DB.

---

## 7. Failover y resiliencia de eventos

Para asegurar entrega confiable:

* Habilitar **retries** en el producer de Kafka.
* Configurar **dead-letter-topic** para eventos que no se puedan procesar.
* Asegurar que los consumidores sean **at-least-once delivery** (la solución actual ya lo cumple).

---

## 8. Consistencia eventual y diseño orientado a eventos

El sistema funciona bajo un patrón de **eventual consistency**:

* La transacción se crea como `pending`
* Anti-fraud responde asíncronamente
* ms-transaction actualiza estado cuando recibe el evento

Esto es ideal para alta concurrencia porque:

* No bloquea peticiones sincronamente
* Mantiene alto throughput
* Reduce latencia percibida por el usuario

---

## 9. Monitoreo y Observabilidad

Para ambientes productivos se recomienda:

* Métricas de Kafka (lag, throughput)
* Métricas de JPA (tiempos de consulta)
* Dashboards de estado de consumidores
* Alertas por retraso en procesamiento de particiones

Esto permite anticipar saturación y escalar antes de fallar.

---

# Conclusión

La solución propuesta soporta carga alta gracias al diseño basado en eventos, el desacoplamiento con Kafka, y la separación de responsabilidades entre microservicios.

Para escenarios extremos, las estrategias detalladas permiten:

* escalar horizontalmente ambos servicios,
* procesar millones de eventos de forma ordenada e idempotente,
* evitar condiciones de carrera,
* y optimizar las lecturas en tiempo real.

Este documento complementa la entrega técnica sin necesidad de modificar la implementación actual.
69 changes: 69 additions & 0 deletions ms-anti-fraud.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
openapi: 3.0.3
info:
title: Anti-Fraud Service (Event-Driven API)
description: >
Anti-Fraud microservice responsible for processing financial transactions received via Kafka,
validating fraud rules, and publishing updated transaction statuses.
version: 1.0.0

servers:
- url: kafka://localhost:9092
description: Local Kafka Broker

paths: {}

components:
schemas:
TransactionCreatedEvent:
type: object
required:
- transactionExternalId
- accountExternalIdDebit
- accountExternalIdCredit
- tranferTypeId
- value
- createdAt
properties:
transactionExternalId:
type: string
format: uuid
accountExternalIdDebit:
type: string
format: uuid
accountExternalIdCredit:
type: string
format: uuid
tranferTypeId:
type: integer
value:
type: number
format: double
createdAt:
type: string
format: date-time

TransactionStatusUpdatedEvent:
type: object
required:
- transactionExternalId
- transactionStatus
properties:
transactionExternalId:
type: string
format: uuid
transactionStatus:
type: string
enum:
- approved
- rejected

x-kafka-topics:
transaction-created:
description: Event published by ms-transaction when a new transaction is created.
message:
$ref: '#/components/schemas/TransactionCreatedEvent'

transaction-status-updated:
description: Event published by ms-anti-fraud after fraud evaluation.
message:
$ref: '#/components/schemas/TransactionStatusUpdatedEvent'
Binary file added ms-anti-fraud/.DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions ms-anti-fraud/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf
33 changes: 33 additions & 0 deletions ms-anti-fraud/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/
3 changes: 3 additions & 0 deletions ms-anti-fraud/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
Loading