summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-03-20 18:33:45 +0100
committerAntoine A <>2024-03-20 18:33:45 +0100
commita46b61bec3e670422fe8e84db44c07f80272495b (patch)
treea12c8b7a2ac2c9d5f50668a57a95a37db0bb5548
parenta047fb5c1076c0afe2c04c8beb2edd6026f595b3 (diff)
downloadlibeufin-a46b61bec3e670422fe8e84db44c07f80272495b.tar.gz
libeufin-a46b61bec3e670422fe8e84db44c07f80272495b.tar.bz2
libeufin-a46b61bec3e670422fe8e84db44c07f80272495b.zip
Share duration parsing with libeufin-nexus
-rw-r--r--common/src/main/kotlin/TalerConfig.kt2
-rw-r--r--common/src/test/kotlin/ConfigTest.kt47
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt18
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt22
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt74
-rw-r--r--nexus/src/test/kotlin/ConfigLoading.kt43
6 files changed, 66 insertions, 140 deletions
diff --git a/common/src/main/kotlin/TalerConfig.kt b/common/src/main/kotlin/TalerConfig.kt
index edcc2faa..c0148278 100644
--- a/common/src/main/kotlin/TalerConfig.kt
+++ b/common/src/main/kotlin/TalerConfig.kt
@@ -100,7 +100,7 @@ fun ConfigSource.fromFile(file: Path?): TalerConfig {
* @param configSource information about where to load configuration defaults from
*/
class TalerConfig internal constructor(
- val configSource: ConfigSource,
+ val configSource: ConfigSource
) {
private val sectionMap: MutableMap<String, Section> = mutableMapOf()
diff --git a/common/src/test/kotlin/ConfigTest.kt b/common/src/test/kotlin/ConfigTest.kt
new file mode 100644
index 00000000..cb573501
--- /dev/null
+++ b/common/src/test/kotlin/ConfigTest.kt
@@ -0,0 +1,47 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
+ * Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+import org.junit.Test
+import java.time.Duration
+import tech.libeufin.common.*
+import kotlin.test.*
+
+class ConfigTest {
+ @Test
+ fun timeParsing() {
+ fun parseTime(raw: String): Duration {
+ val cfg = TalerConfig(ConfigSource("test", "test", "test"))
+ cfg.loadFromMem("""
+ [test]
+ time = "$raw"
+ """, null)
+ return cfg.requireDuration("test", "time")
+ }
+ assertEquals(Duration.ofSeconds(1), parseTime("1s"))
+ assertEquals(parseTime("1 s"), parseTime("1s"))
+ assertEquals(Duration.ofMinutes(10), parseTime("10m"))
+ assertEquals(parseTime("10 m"), parseTime("10m"))
+ assertEquals(Duration.ofHours(1), parseTime("01h"))
+ assertEquals(
+ Duration.ofHours(1).plus(Duration.ofMinutes(10)).plus(Duration.ofSeconds(12)),
+ parseTime("1h10m12s")
+ )
+ assertEquals(parseTime("1h10m12s"), parseTime("1h10'12\""))
+ }
+} \ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
index 47c021cd..298d84b4 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
@@ -32,10 +32,12 @@ import tech.libeufin.nexus.db.*
import java.io.IOException
import java.io.InputStream
import java.time.Instant
+import java.time.Duration
import java.time.LocalDate
import java.time.ZoneId
import kotlin.io.*
import kotlin.io.path.*
+import kotlin.time.toKotlinDuration
/**
* Necessary data to perform a download.
@@ -389,20 +391,16 @@ class EbicsFetch: CliktCommand("Fetches EBICS files") {
throw Exception("Failed to fetch documents")
}
} else {
- val configValue = cfg.config.requireString("nexus-fetch", "frequency")
- val frequencySeconds = checkFrequency(configValue)
- val cfgFrequency: NexusFrequency = NexusFrequency(frequencySeconds, configValue)
- logger.debug("Running with a frequency of ${cfgFrequency.fromConfig}")
- val frequency: NexusFrequency? = if (cfgFrequency.inSeconds == 0) {
+ var frequency: Duration = cfg.config.requireDuration("nexus-fetch", "frequency")
+ val raw = cfg.config.requireString("nexus-fetch", "frequency")
+ logger.debug("Running with a frequency of $raw")
+ if (frequency == Duration.ZERO) {
logger.warn("Long-polling not implemented, running therefore in transient mode")
- null
- } else {
- cfgFrequency
}
do {
fetchDocuments(db, ctx, docs)
- delay(((frequency?.inSeconds ?: 0) * 1000).toLong())
- } while (frequency != null)
+ delay(frequency.toKotlinDuration())
+ } while (frequency != Duration.ZERO)
}
}
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
index 8366f064..cf206380 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
@@ -29,6 +29,7 @@ import tech.libeufin.nexus.ebics.*
import tech.libeufin.nexus.db.*
import java.time.*
import java.util.*
+import kotlin.time.toKotlinDuration
/**
* Groups useful parameters to submit pain.001 via EBICS.
@@ -156,20 +157,17 @@ class EbicsSubmit : CliktCommand("Submits any initiated payment found in the dat
fileLogger = FileLogger(ebicsLog)
)
Database(dbCfg.dbConnStr).use { db ->
- val frequency = if (transient) {
+ val frequency: Duration = if (transient) {
logger.info("Transient mode: submitting what found and returning.")
- null
+ Duration.ZERO
} else {
- val configValue = cfg.config.requireString("nexus-submit", "frequency")
- val frequencySeconds = checkFrequency(configValue)
- val frequency: NexusFrequency = NexusFrequency(frequencySeconds, configValue)
- logger.debug("Running with a frequency of ${frequency.fromConfig}")
- if (frequency.inSeconds == 0) {
+ var frequency = cfg.config.requireDuration("nexus-submit", "frequency")
+ val raw = cfg.config.requireString("nexus-submit", "frequency")
+ logger.debug("Running with a frequency of $raw")
+ if (frequency == Duration.ZERO) {
logger.warn("Long-polling not implemented, running therefore in transient mode")
- null
- } else {
- frequency
}
+ frequency
}
do {
try {
@@ -178,8 +176,8 @@ class EbicsSubmit : CliktCommand("Submits any initiated payment found in the dat
throw Exception("Failed to submit payments")
}
// TODO take submitBatch taken time in the delay
- delay(((frequency?.inSeconds ?: 0) * 1000).toLong())
- } while (frequency != null)
+ delay(frequency.toKotlinDuration())
+ } while (frequency != Duration.ZERO)
}
}
} \ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 8a51c766..b9582976 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -55,80 +55,6 @@ data class IbanAccountMetadata(
val name: String
)
-/**
- * Contains the frequency of submit or fetch iterations.
- */
-data class NexusFrequency(
- /**
- * Value in seconds of the FREQUENCY configuration
- * value, found either under [nexus-fetch] or [nexus-submit]
- */
- val inSeconds: Int,
- /**
- * Copy of the value found in the configuration. Used
- * for logging.
- */
- val fromConfig: String
-)
-
-/**
- * Converts human-readable duration in how many seconds. Supports
- * the suffixes 's' (seconds), 'm' (minute), 'h' (hours). A valid
- * duration is therefore, for example, Nm, where N is the number of
- * minutes.
- *
- * @param trimmed duration
- * @return how many seconds is the duration input, or null if the input
- * is not valid.
- */
-fun getFrequencyInSeconds(humanFormat: String): Int? {
- val trimmed = humanFormat.trim()
- if (trimmed.isEmpty()) {
- logger.error("Input was empty")
- return null
- }
- val howManySeconds: Int = when (val lastChar = trimmed.last()) {
- 's' -> {1}
- 'm' -> {60}
- 'h' -> {60 * 60}
- else -> {
- logger.error("Duration symbol not one of s, m, h. '$lastChar' was found instead")
- return null
- }
- }
- val maybeNumber = trimmed.dropLast(1)
- val howMany = try {
- maybeNumber.trimEnd().toInt()
- } catch (e: Exception) {
- logger.error("Prefix was not a valid input: '$maybeNumber'")
- return null
- }
- if (howMany == 0) return 0
- val ret = howMany * howManySeconds
- if (howMany != ret / howManySeconds) {
- logger.error("Result overflew")
- return null
- }
- return ret
-}
-
-/**
- * Sanity-checks the frequency found in the configuration and
- * either returns it or fails the process. Note: the returned
- * value is also guaranteed to be non-negative.
- *
- * @param foundInConfig frequency value as found in the configuration.
- * @return the duration in seconds of the value found in the configuration.
- */
-fun checkFrequency(foundInConfig: String): Int {
- val frequencySeconds = getFrequencyInSeconds(foundInConfig)
- ?: throw Exception("Invalid frequency value in config section nexus-submit: $foundInConfig")
- if (frequencySeconds < 0) {
- throw Exception("Configuration error: cannot operate with a negative submit frequency ($foundInConfig)")
- }
- return frequencySeconds
-}
-
fun Instant.fmtDate(): String =
DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZoneId.of("UTC")).format(this)
diff --git a/nexus/src/test/kotlin/ConfigLoading.kt b/nexus/src/test/kotlin/ConfigLoading.kt
deleted file mode 100644
index ebdfa381..00000000
--- a/nexus/src/test/kotlin/ConfigLoading.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is part of LibEuFin.
- * Copyright (C) 2024 Taler Systems S.A.
-
- * LibEuFin is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation; either version 3, or
- * (at your option) any later version.
-
- * LibEuFin is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
- * Public License for more details.
-
- * You should have received a copy of the GNU Affero General Public
- * License along with LibEuFin; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>
- */
-
-import org.junit.Test
-import tech.libeufin.nexus.getFrequencyInSeconds
-import kotlin.test.assertEquals
-import kotlin.test.assertNull
-
-class ConfigLoading {
- // Checks converting human-readable durations to seconds.
- @Test
- fun timeParsing() {
- assertEquals(1, getFrequencyInSeconds("1s"))
- assertEquals(1, getFrequencyInSeconds(" 1 s "))
- assertEquals(10*60, getFrequencyInSeconds("10m"))
- assertEquals(10*60, getFrequencyInSeconds("10 m"))
- assertEquals(24*60*60, getFrequencyInSeconds("24h"))
- assertEquals(24*60*60, getFrequencyInSeconds(" 24h"))
- assertEquals(60*60, getFrequencyInSeconds(" 1h "))
- assertEquals(60*60, getFrequencyInSeconds("01h"))
- assertNull(getFrequencyInSeconds("1.1s"))
- assertNull(getFrequencyInSeconds(" "))
- assertNull(getFrequencyInSeconds("m"))
- assertNull(getFrequencyInSeconds(""))
- assertNull(getFrequencyInSeconds("0"))
- }
-} \ No newline at end of file