add MPP sender with payment loop

This commit is contained in:
Carsten Otto
2022-05-14 14:19:21 +02:00
committed by Carsten Otto
parent 7bfcbf7333
commit 215e0bc23b
23 changed files with 1209 additions and 153 deletions

View File

@@ -0,0 +1,58 @@
package de.cotto.lndmanagej.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.cotto.lndmanagej.pickhardtpayments.model.PaymentStatus;
import de.cotto.lndmanagej.pickhardtpayments.model.PaymentStatus.InstantWithString;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Component
public class PaymentStatusStream {
private final ObjectMapper objectMapper;
public PaymentStatusStream() {
this.objectMapper = new ObjectMapper();
}
public StreamingResponseBody getFor(PaymentStatus paymentStatus) {
return response -> {
int seenMessages = 0;
do {
List<InstantWithString> messages = paymentStatus.getMessages();
int oldMessages = seenMessages;
seenMessages = messages.size();
for (int i = oldMessages; i < messages.size(); i++) {
InstantWithString instantWithString = messages.get(i);
Object messageToWrite = new Message(
instantWithString.instant().toString(),
instantWithString.string()
);
String json = objectMapper.writeValueAsString(messageToWrite);
response.write(json.getBytes(StandardCharsets.UTF_8));
response.write('\n');
response.flush();
}
} while (notDone(paymentStatus, seenMessages));
};
}
private boolean notDone(PaymentStatus paymentStatus, int seenMessages) {
sleep();
return paymentStatus.getMessages().size() > seenMessages || paymentStatus.isPending();
}
private void sleep() {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
// ignored
}
}
@SuppressWarnings("UnusedVariable")
private record Message(String timestamp, String message) {
}
}

View File

@@ -7,38 +7,51 @@ import de.cotto.lndmanagej.model.Pubkey;
import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSender;
import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSplitter;
import de.cotto.lndmanagej.pickhardtpayments.model.MultiPathPayment;
import de.cotto.lndmanagej.pickhardtpayments.model.PaymentStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import static de.cotto.lndmanagej.pickhardtpayments.PickhardtPaymentsConfiguration.DEFAULT_FEE_RATE_WEIGHT;
import static org.springframework.http.MediaType.APPLICATION_NDJSON;
@RestController
@RequestMapping("/beta/pickhardt-payments/")
public class PickhardtPaymentsController {
private final MultiPathPaymentSplitter multiPathPaymentSplitter;
private final MultiPathPaymentSender multiPathPaymentSender;
private final PaymentStatusStream paymentStatusStream;
public PickhardtPaymentsController(
MultiPathPaymentSplitter multiPathPaymentSplitter,
MultiPathPaymentSender multiPathPaymentSender
MultiPathPaymentSender multiPathPaymentSender,
PaymentStatusStream paymentStatusStream
) {
this.multiPathPaymentSplitter = multiPathPaymentSplitter;
this.multiPathPaymentSender = multiPathPaymentSender;
this.paymentStatusStream = paymentStatusStream;
}
@Timed
@GetMapping("/pay-payment-request/{paymentRequest}")
public MultiPathPaymentDto payPaymentRequest(@PathVariable String paymentRequest) {
public ResponseEntity<StreamingResponseBody> payPaymentRequest(@PathVariable String paymentRequest) {
return payPaymentRequest(paymentRequest, DEFAULT_FEE_RATE_WEIGHT);
}
@Timed
@GetMapping("/pay-payment-request/{paymentRequest}/fee-rate-weight/{feeRateWeight}")
public MultiPathPaymentDto payPaymentRequest(@PathVariable String paymentRequest, @PathVariable int feeRateWeight) {
MultiPathPayment multiPathPayment = multiPathPaymentSender.payPaymentRequest(paymentRequest, feeRateWeight);
return MultiPathPaymentDto.fromModel(multiPathPayment);
public ResponseEntity<StreamingResponseBody> payPaymentRequest(
@PathVariable String paymentRequest,
@PathVariable int feeRateWeight
) {
PaymentStatus paymentStatus = multiPathPaymentSender.payPaymentRequest(paymentRequest, feeRateWeight);
StreamingResponseBody streamingResponseBody = paymentStatusStream.getFor(paymentStatus);
return ResponseEntity.ok()
.contentType(APPLICATION_NDJSON)
.body(streamingResponseBody);
}
@Timed