Fall back to last fetched ratings file on i/o error while updating

This commit is contained in:
Claude Brisson
2024-03-30 06:03:51 +01:00
parent 4f3e11d263
commit aefc567d29
3 changed files with 28 additions and 12 deletions

View File

@@ -7,6 +7,7 @@ import okhttp3.Request
import org.jeudego.pairgoth.web.WebappManager
import org.slf4j.LoggerFactory
import java.io.File
import java.io.IOException
import java.net.URL
import java.nio.charset.StandardCharsets
import java.time.LocalDate
@@ -27,6 +28,7 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
lateinit var players: Json.Array
lateinit var activeRatingsFile: File
private var updated = false
val ready get() = this::activeRatingsFile.isInitialized && this::players.isInitialized
val url: URL by lazy {
WebappManager.properties.getProperty("ratings.${origin.name.lowercase(Locale.ROOT)}")?.let { URL(it) } ?: defaultURL
@@ -63,6 +65,15 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
return initIfNeeded(latestRatingsFile)
}
val payload = fetchPayload()
if (payload == null) {
// an error occurred while fetching the payload, and has been reported
if (latestRatingsFile != null) {
// fall back to last ratings file
return initIfNeeded(latestRatingsFile)
} else {
return false
}
}
val (lastUpdated, lastPlayers) = parsePayload(payload)
val ratingsFilename = "${origin.name}-${ymd.format(lastUpdated)}.json"
if (latestRatingsFile != null && latestRatingsFile.name == ratingsFilename) {
@@ -87,16 +98,21 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
return players
}
protected fun fetchPayload(): String {
protected fun fetchPayload(): String? {
try {
val request = Request.Builder()
.url(url)
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw Error("Could not fetch $origin ratings: unexpected code $response")
if (!response.isSuccessful) throw IOException("Could not fetch $origin ratings: unexpected code $response")
val contentType = response.headers["Content-Type"]?.toMediaType()
return response.body!!.source().readString(contentType?.charset() ?: defaultCharset())
}
} catch (ioe: IOException) {
logger.error("Could not refresh ${origin.name} ratings from ${url}", ioe)
return null
}
}
open fun defaultCharset() = StandardCharsets.UTF_8
fun updated() = updated

View File

@@ -36,7 +36,7 @@ object RatingsManager: Runnable {
);
}
fun activeMask() = ratingsHandlers.entries.filter { it.value.active }.map { it.key.flag }.reduce { a,b -> a or b }
fun activeMask() = ratingsHandlers.entries.filter { it.value.active && it.value.ready }.map { it.key.flag }.reduce { a,b -> a or b }
val timer = Timer()
lateinit var players: Json.MutableArray
@@ -139,7 +139,7 @@ object RatingsManager: Runnable {
val index = PlayerIndex()
public fun getRatingsDates() = ratingsHandlers.filter{ it.value.active }.map {
fun getRatingsDates() = ratingsHandlers.filter{ it.value.active && it.value.ready }.map {
Pair(it.key.name.lowercase(),
DateTimeFormatter.ISO_LOCAL_DATE.format(it.value.activeDate()))
}.toMap()

View File

@@ -112,7 +112,7 @@
</div>
*#
<div class="two wide field">
<div class="toggle" title="$utils.ratingsDates.egf">
<div class="toggle" title="${utils.ratingsDates.egf|'no egf ratings'}">
<input id="egf" name="egf" type="checkbox" checked value="true"/>
<div class="search-param checkbox">
<div class="circle"></div>
@@ -121,7 +121,7 @@
</div>
</div>
<div class="two wide field">
<div class="toggle" title="$utils.ratingsDates.ffg">
<div class="toggle" title="${utils.ratingsDates.ffg|'no ffg ratings'}">
<input id="ffg" name="ffg" type="checkbox" checked value="true"/>
<div class="search-param checkbox">
<div class="circle"></div>