Fall back to last fetched ratings file on i/o error while updating
This commit is contained in:
@@ -7,6 +7,7 @@ import okhttp3.Request
|
|||||||
import org.jeudego.pairgoth.web.WebappManager
|
import org.jeudego.pairgoth.web.WebappManager
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
@@ -27,6 +28,7 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
|
|||||||
lateinit var players: Json.Array
|
lateinit var players: Json.Array
|
||||||
lateinit var activeRatingsFile: File
|
lateinit var activeRatingsFile: File
|
||||||
private var updated = false
|
private var updated = false
|
||||||
|
val ready get() = this::activeRatingsFile.isInitialized && this::players.isInitialized
|
||||||
|
|
||||||
val url: URL by lazy {
|
val url: URL by lazy {
|
||||||
WebappManager.properties.getProperty("ratings.${origin.name.lowercase(Locale.ROOT)}")?.let { URL(it) } ?: defaultURL
|
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)
|
return initIfNeeded(latestRatingsFile)
|
||||||
}
|
}
|
||||||
val payload = fetchPayload()
|
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 (lastUpdated, lastPlayers) = parsePayload(payload)
|
||||||
val ratingsFilename = "${origin.name}-${ymd.format(lastUpdated)}.json"
|
val ratingsFilename = "${origin.name}-${ymd.format(lastUpdated)}.json"
|
||||||
if (latestRatingsFile != null && latestRatingsFile.name == ratingsFilename) {
|
if (latestRatingsFile != null && latestRatingsFile.name == ratingsFilename) {
|
||||||
@@ -87,15 +98,20 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
|
|||||||
return players
|
return players
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun fetchPayload(): String {
|
protected fun fetchPayload(): String? {
|
||||||
val request = Request.Builder()
|
try {
|
||||||
.url(url)
|
val request = Request.Builder()
|
||||||
.build()
|
.url(url)
|
||||||
|
.build()
|
||||||
|
|
||||||
client.newCall(request).execute().use { response ->
|
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()
|
val contentType = response.headers["Content-Type"]?.toMediaType()
|
||||||
return response.body!!.source().readString(contentType?.charset() ?: defaultCharset())
|
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
|
open fun defaultCharset() = StandardCharsets.UTF_8
|
||||||
|
@@ -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()
|
val timer = Timer()
|
||||||
lateinit var players: Json.MutableArray
|
lateinit var players: Json.MutableArray
|
||||||
@@ -139,7 +139,7 @@ object RatingsManager: Runnable {
|
|||||||
|
|
||||||
val index = PlayerIndex()
|
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(),
|
Pair(it.key.name.lowercase(),
|
||||||
DateTimeFormatter.ISO_LOCAL_DATE.format(it.value.activeDate()))
|
DateTimeFormatter.ISO_LOCAL_DATE.format(it.value.activeDate()))
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
@@ -112,7 +112,7 @@
|
|||||||
</div>
|
</div>
|
||||||
*#
|
*#
|
||||||
<div class="two wide field">
|
<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"/>
|
<input id="egf" name="egf" type="checkbox" checked value="true"/>
|
||||||
<div class="search-param checkbox">
|
<div class="search-param checkbox">
|
||||||
<div class="circle"></div>
|
<div class="circle"></div>
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="two wide field">
|
<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"/>
|
<input id="ffg" name="ffg" type="checkbox" checked value="true"/>
|
||||||
<div class="search-param checkbox">
|
<div class="search-param checkbox">
|
||||||
<div class="circle"></div>
|
<div class="circle"></div>
|
||||||
|
Reference in New Issue
Block a user