diff options
author | MS <ms@taler.net> | 2020-06-03 18:59:58 +0200 |
---|---|---|
committer | MS <ms@taler.net> | 2020-06-03 19:09:40 +0200 |
commit | 1c89426792953a838491b4592a14cc38849e43ed (patch) | |
tree | eca1f3be69cbedf410db408133597714064f0a8c /nexus/src/main/kotlin/tech/libeufin | |
parent | 088c518e0ed7d9e5f448035fdc41426c6887b405 (diff) | |
download | libeufin-1c89426792953a838491b4592a14cc38849e43ed.tar.gz libeufin-1c89426792953a838491b4592a14cc38849e43ed.tar.bz2 libeufin-1c89426792953a838491b4592a14cc38849e43ed.zip |
Advancing for the exchange-nexus test.
Sandbox: fill CAMT values according to actual data received in payments.
Nexus: fix the launching of HTTP requests (namely to obtain C53) in the background.
Diffstat (limited to 'nexus/src/main/kotlin/tech/libeufin')
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt | 40 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt | 63 |
2 files changed, 65 insertions, 38 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt index fb4d0bae..0ed44db9 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt @@ -56,8 +56,7 @@ import io.ktor.server.netty.Netty import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.jvm.javaio.toByteReadChannel import io.ktor.utils.io.jvm.javaio.toInputStream -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch +import kotlinx.coroutines.* import kotlinx.coroutines.time.delay import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.statements.api.ExposedBlob @@ -75,6 +74,7 @@ import java.util.* import java.util.zip.InflaterInputStream import javax.crypto.EncryptedPrivateKeyInfo import java.time.LocalDateTime +import kotlin.coroutines.CoroutineContext data class NexusError(val statusCode: HttpStatusCode, val reason: String) : Exception("${reason} (HTTP status $statusCode)") @@ -258,21 +258,37 @@ fun ApplicationRequest.hasBody(): Boolean { } return false } -suspend fun schedulePeriodicWork(coroutineScope: CoroutineScope) { - while (true) { - delay(Duration.ofMillis(100)) - downloadFacadesTransactions(coroutineScope) - ingestTalerTransactions() + +fun schedulePeriodicWork() { + GlobalScope.launch { + while (true) { + logger.debug("Outer background job") + try { + delay(Duration.ofSeconds(1)) + downloadFacadesTransactions(this) + ingestTalerTransactions() + } catch (e: Exception) { + logger.info("==== Background job exception ====\n${e.message}======") + } + } } } /** Crawls all the facades, and requests history for each of its creators. */ -suspend fun downloadFacadesTransactions(coroutineScope: CoroutineScope) { +suspend fun downloadFacadesTransactions(myScope: CoroutineScope) { val httpClient = HttpClient() transaction { FacadeEntity.all().forEach { - coroutineScope.launch { - fetchTransactionsInternal(httpClient, it.creator, it.config.bankAccount, CollectedTransaction()) + logger.debug( + "Fetching history for facade: ${it.id.value}, bank account: ${it.config.bankAccount}" + ) + runBlocking { + fetchTransactionsInternal( + httpClient, + it.creator, + it.config.bankAccount, + CollectedTransaction(null, null, null) + ) } } } @@ -344,9 +360,6 @@ fun serverMain(dbName: String) { expectSuccess = false // this way, it does not throw exceptions on != 200 responses. } val server = embeddedServer(Netty, port = 5001) { - launch { - schedulePeriodicWork(this) - } install(CallLogging) { this.level = Level.DEBUG this.logger = tech.libeufin.nexus.logger @@ -413,6 +426,7 @@ fun serverMain(dbName: String) { return@intercept } + schedulePeriodicWork() routing { /** * Shows information about the requesting user. diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt index de7ea140..499743e3 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt @@ -3,9 +3,12 @@ package tech.libeufin.nexus import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import io.ktor.application.ApplicationCall import io.ktor.application.call +import io.ktor.client.HttpClient +import io.ktor.client.request.post import io.ktor.content.TextContent import io.ktor.http.ContentType import io.ktor.http.HttpStatusCode +import io.ktor.http.contentType import io.ktor.request.receive import io.ktor.response.respond import io.ktor.response.respondText @@ -226,7 +229,7 @@ fun getFacadeBankAccount(nexusUser: NexusUserEntity): NexusBankAccountEntity { } // /taler/transfer -suspend fun talerTransfer(call: ApplicationCall): Unit { +suspend fun talerTransfer(call: ApplicationCall) { val transferRequest = call.receive<TalerTransferRequest>() val amountObj = parseAmount(transferRequest.amount) val creditorObj = parsePayto(transferRequest.credit_account) @@ -260,20 +263,6 @@ suspend fun talerTransfer(call: ApplicationCall): Unit { ), exchangeBankAccount ) - val rawEbics = if (!isProduction()) { - RawBankTransactionEntity.new { - unstructuredRemittanceInformation = transferRequest.wtid - transactionType = "DBIT" - currency = amountObj.currency - this.amount = amountObj.amount.toPlainString() - counterpartBic = creditorObj.bic - counterpartIban = creditorObj.iban - counterpartName = creditorObj.name - bankAccount = exchangeBankAccount - bookingDate = System.currentTimeMillis() - status = "BOOK" - } - } else null val row = TalerRequestedPaymentEntity.new { preparedPayment = pain001 // not really used/needed, just here to silence warnings exchangeBaseUrl = transferRequest.exchange_base_url @@ -281,7 +270,6 @@ suspend fun talerTransfer(call: ApplicationCall): Unit { amount = transferRequest.amount wtid = transferRequest.wtid creditAccount = transferRequest.credit_account - rawConfirmed = rawEbics } row.id.value } @@ -307,25 +295,49 @@ suspend fun talerTransfer(call: ApplicationCall): Unit { suspend fun talerAddIncoming(call: ApplicationCall): Unit { val addIncomingData = call.receive<TalerAdminAddIncoming>() val debtor = parsePayto(addIncomingData.debit_account) - val amount = parseAmount(addIncomingData.amount) - - val myLastSeenRawPayment = transaction { + val res = transaction { val facadeID = expectNonNull(call.parameters["fcid"]) val facade = FacadeEntity.findById(facadeID) ?: throw NexusError( - HttpStatusCode.NotFound, "Could not find facade" + HttpStatusCode.NotFound, "Could not find facade '$facadeID'" + ) + val facadeBankAccount = NexusBankAccountEntity.findById(facade.config.bankAccount) ?: throw NexusError( + HttpStatusCode.NotFound, + "Such bank account '${facade.config.bankAccount}' wasn't found for facade '$facadeID'" ) - facade.highestSeenMsgID + return@transaction object { + val facadeLastSeen = facade.highestSeenMsgID + val facadeIban = facadeBankAccount.iban + val facadeBic = facadeBankAccount.bankCode + val facadeHolderName = facadeBankAccount.accountHolder + } } + val httpClient = HttpClient() + /** forward the payment information to the sandbox. */ + httpClient.post<String>( + urlString = "http://localhost:5000/admin/payments", + block = { + /** FIXME: ideally Jackson should define such request body. */ + this.body = """{ + "creditorIban": "${res.facadeIban}", + "creditorBic": "${res.facadeBic}", + "creditorName": "${res.facadeHolderName}", + "debitorIban": "${debtor.iban}", + "debitorBic": "${debtor.bic}", + "debitorName": "${debtor.name}", + "amount": "${addIncomingData.amount}", + "subject": "${addIncomingData.reserve_pub}" + }""".trimIndent() + contentType(ContentType.Application.Json) + } + ) return call.respond( TextContent( customConverter( TalerAddIncomingResponse( timestamp = GnunetTimestamp( - // warning: this value might need to come from a real last-seen payment. - // FIXME(dold): I don't understand the comment above ^^. System.currentTimeMillis() ), - row_id = myLastSeenRawPayment + row_id = res.facadeLastSeen ) ), ContentType.Application.Json @@ -343,6 +355,7 @@ suspend fun talerAddIncoming(call: ApplicationCall): Unit { */ fun ingestTalerTransactions() { fun ingest(subscriberAccount: NexusBankAccountEntity, facade: FacadeEntity) { + logger.debug("Ingesting transactions for Taler facade: ${facade.id.value}") var lastId = facade.highestSeenMsgID RawBankTransactionEntity.find { /** Those with exchange bank account involved */ @@ -510,4 +523,4 @@ fun talerFacadeRoutes(route: Route) { call.respondText("Hello, this is Taler Facade") return@get } -}
\ No newline at end of file +} |