diff options
| author | leo <azuminha1@gmail.com> | 2025-09-27 14:31:52 -0300 | 
|---|---|---|
| committer | leo <azuminha1@gmail.com> | 2025-09-27 14:31:52 -0300 | 
| commit | 1a3a6f83cc9ef2af8fed16775dce209feb8391ab (patch) | |
| tree | b31220eeaa0f6519ab3c5e51eebe394a425cf06c /src/main/java/com/rinha/backend/service | |
Diffstat (limited to 'src/main/java/com/rinha/backend/service')
| -rw-r--r-- | src/main/java/com/rinha/backend/service/PaymentService.java | 116 | ||||
| -rw-r--r-- | src/main/java/com/rinha/backend/service/SummaryService.java | 41 | 
2 files changed, 157 insertions, 0 deletions
| diff --git a/src/main/java/com/rinha/backend/service/PaymentService.java b/src/main/java/com/rinha/backend/service/PaymentService.java new file mode 100644 index 0000000..bd283c3 --- /dev/null +++ b/src/main/java/com/rinha/backend/service/PaymentService.java @@ -0,0 +1,116 @@ +package com.rinha.backend.service; + +import com.rinha.backend.model.PaymentModel; +import com.rinha.backend.repository.PaymentRepository; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Random; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Service +public class PaymentService { +    private static String processorDefault  = "http://payment-processor-default:8080/payments"; +    private static String processorFallback = "http://payment-processor-fallback:8080/payments"; +    private final HttpClient httpClient = HttpClient.newHttpClient(); +    private static final Random random = new Random(); +    private final ExecutorService dbExecutor = Executors.newFixedThreadPool(2); + +    private final BlockingQueue<PaymentModel> paymentQueue = new ArrayBlockingQueue<PaymentModel>(65536); +    private final PaymentRepository paymentRepository; + +    public PaymentService(PaymentRepository paymentRepository) { +        this.paymentRepository = paymentRepository; +        this.startWorker(); +    } + +    public void addQueue(PaymentModel p) { +        p.setData(OffsetDateTime.now(ZoneOffset.UTC)); +        paymentQueue.add(p); +    } + +    public void startWorker() { +        for(int i = 1; i <= 4; ++i) { +            Thread worker = new Thread(() -> { +                while (true) { +                    try { +                        PaymentModel p = paymentQueue.take(); +                        processPayment(p); +                    } catch (InterruptedException e) { +                    } +                } +            }); + +            worker.setName("worker-" + i); +            worker.start(); +        } +    } + +    public void processPayment(PaymentModel p) { +        //System.out.println("Processando pagamento " + p.getCorrelationId() + +        //        " no valor de " + p.getAmount() + +        //        " às " + p.getData()); + +        int ok = sendToProcessor(p); +        if(ok > 0) { +            p.setProcessor(ok); +            saveDB(p); +        }else +            paymentQueue.add(p); +    } + +    public int sendToProcessor(PaymentModel p) { +        try { +            String body = String.format(""" +                    { +                      "correlationId": "%s", +                      "amount": %.2f, +                      "requestedAt": "%s" +                    } +                    """, p.getCorrelationId(), p.getAmount(), p.getData()); + +            int n = random.nextInt(100); +            String url; +            if(n < 60) url = processorDefault; +            else url = processorFallback; + +            HttpRequest request = HttpRequest.newBuilder() +                    .uri(URI.create(url)) +                    .header("Content-Type", "application/json") +                    .POST(HttpRequest.BodyPublishers.ofString(body)) +                    .build(); + +            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + +            //System.out.println("Resposta servidor: " + response.statusCode() + " - " + response.body()); +            if(response.statusCode() == 200 && url.equals(processorDefault)) +                return 1; +            if(response.statusCode() == 200 && url.equals(processorFallback)) +                return 2; +            return 0; +        } catch (Exception e) { +            throw new RuntimeException(e); +        } +    } + +    public void saveDB(PaymentModel p){ +        //paymentRepository.save(p); +        dbExecutor.submit(() -> { +            try { +                paymentRepository.save(p); +            } catch (Exception e) { +            } +        }); +    } +} diff --git a/src/main/java/com/rinha/backend/service/SummaryService.java b/src/main/java/com/rinha/backend/service/SummaryService.java new file mode 100644 index 0000000..d3fb32e --- /dev/null +++ b/src/main/java/com/rinha/backend/service/SummaryService.java @@ -0,0 +1,41 @@ +package com.rinha.backend.service; + +import com.rinha.backend.model.PaymentModel; +import com.rinha.backend.model.SummaryModel; +import com.rinha.backend.repository.PaymentRepository; +import org.springframework.stereotype.Service; + +import java.time.OffsetDateTime; +import java.util.List; + +@Service +public class SummaryService { + +    private final PaymentRepository paymentRepository; + +    public SummaryService(PaymentRepository paymentRepository) { +        this.paymentRepository = paymentRepository; +    } + +    public SummaryModel getSummary(OffsetDateTime from, OffsetDateTime to) { +        SummaryModel summary = new SummaryModel(); +        if (from == null) from = OffsetDateTime.MIN; +        if (to == null) to = OffsetDateTime.MAX; + +        List<PaymentModel> payments = paymentRepository.findAll(); + +        for (PaymentModel p : payments) { +            if(p.getData().isBefore(from) || p.getData().isAfter(to)) continue; + +            if (p.getProcessor() == 1) { +                summary.getProcessorDefault().addTotalRequests(1); +                summary.getProcessorDefault().addTotalAmount(p.getAmount()); +            } else if (p.getProcessor() == 2) { +                summary.getProcessorFallback().addTotalRequests(1); +                summary.getProcessorFallback().addTotalAmount(p.getAmount()); +            } +        } + +        return summary; +    } +} | 
