diff options
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; + } +} |