summaryrefslogtreecommitdiff
path: root/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt
diff options
context:
space:
mode:
Diffstat (limited to 'nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt')
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt48
1 files changed, 31 insertions, 17 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt
index efe98f82..4df7f0c9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt
@@ -22,6 +22,7 @@ package tech.libeufin.nexus.db
import tech.libeufin.nexus.*
import tech.libeufin.common.*
import java.time.Instant
+import java.sql.ResultSet
/** Data access logic for initiated outgoing payments */
class InitiatedDAO(private val db: Database) {
@@ -169,28 +170,15 @@ class InitiatedDAO(private val db: Database) {
stmt.execute()
}
- // TODO WIP
- suspend fun submittableGet(currency: String): List<InitiatedPayment> = db.conn { conn ->
- val stmt = conn.prepareStatement("""
- SELECT
- initiated_outgoing_transaction_id
- ,(amount).val as amount_val
- ,(amount).frac as amount_frac
- ,wire_transfer_subject
- ,credit_payto_uri
- ,initiation_time
- ,request_uid
- FROM initiated_outgoing_transactions
- WHERE (submitted='unsubmitted' OR submitted='transient_failure')
- AND ((amount).val != 0 OR (amount).frac != 0);
- """)
- stmt.all {
+ /** List every initiated payment pending submission in ther order they should be submitted */
+ suspend fun submittable(currency: String): List<InitiatedPayment> = db.conn { conn ->
+ fun extract(it: ResultSet): InitiatedPayment {
val rowId = it.getLong("initiated_outgoing_transaction_id")
val initiationTime = it.getLong("initiation_time").microsToJavaInstant()
if (initiationTime == null) { // nexus fault
throw Exception("Found invalid timestamp at initiated payment with ID: $rowId")
}
- InitiatedPayment(
+ return InitiatedPayment(
id = it.getLong("initiated_outgoing_transaction_id"),
amount = it.getAmount("amount", currency),
creditPaytoUri = it.getString("credit_payto_uri"),
@@ -199,5 +187,31 @@ class InitiatedDAO(private val db: Database) {
requestUid = it.getString("request_uid")
)
}
+ val selectPart = """
+ SELECT
+ initiated_outgoing_transaction_id
+ ,(amount).val as amount_val
+ ,(amount).frac as amount_frac
+ ,wire_transfer_subject
+ ,credit_payto_uri
+ ,initiation_time
+ ,request_uid
+ FROM initiated_outgoing_transactions
+ """
+ // We want to maximize the number of successfully submitted transactions in the event
+ // of a malformed transaction or a persistent error classified as transient. We send
+ // the unsubmitted transactions first, starting with the oldest by creation time.
+ // This is the happy path, giving every transaction a chance while being fair on the
+ // basis of creation date.
+ // Then we retry the failed transaction, starting with the oldest by submission time.
+ // This the bad path retrying each failed transaction applying a rotation based on
+ // resubmission time.
+ val unsubmitted = conn.prepareStatement(
+ "$selectPart WHERE submitted='unsubmitted' ORDER BY initiation_time"
+ ).all(::extract)
+ val failed = conn.prepareStatement(
+ "$selectPart WHERE submitted='transient_failure' ORDER BY last_submission_time"
+ ).all(::extract)
+ unsubmitted + failed
}
} \ No newline at end of file