Add JSON version of the /caches page

Signed-off-by: Graham <gpe@openrs2.org>
Graham 3 years ago
parent 759d4bf1f1
commit 71f775f282
  1. 1
      archive/build.gradle.kts
  2. 5
      archive/src/main/kotlin/org/openrs2/archive/ArchiveModule.kt
  3. 18
      archive/src/main/kotlin/org/openrs2/archive/cache/CacheExporter.kt
  4. 5
      archive/src/main/kotlin/org/openrs2/archive/web/CachesController.kt
  5. 1
      archive/src/main/kotlin/org/openrs2/archive/web/WebServer.kt
  6. 2
      archive/src/main/resources/org/openrs2/archive/templates/caches/index.html
  7. 1
      gradle/libs.versions.toml
  8. 1
      json/src/main/kotlin/org/openrs2/json/ObjectMapperProvider.kt
  9. 2
      yaml/src/main/kotlin/org/openrs2/yaml/ObjectMapperProvider.kt

@ -32,6 +32,7 @@ dependencies {
implementation(libs.flyway) implementation(libs.flyway)
implementation(libs.guava) implementation(libs.guava)
implementation(libs.hikaricp) implementation(libs.hikaricp)
implementation(libs.jackson.jsr310)
implementation(libs.jdom) implementation(libs.jdom)
implementation(libs.jquery) implementation(libs.jquery)
implementation(libs.jsoup) implementation(libs.jsoup)

@ -1,5 +1,7 @@
package org.openrs2.archive package org.openrs2.archive
import com.fasterxml.jackson.databind.Module
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.google.inject.AbstractModule import com.google.inject.AbstractModule
import com.google.inject.Scopes import com.google.inject.Scopes
import com.google.inject.multibindings.Multibinder import com.google.inject.multibindings.Multibinder
@ -44,6 +46,9 @@ public object ArchiveModule : AbstractModule() {
keyBinder.addBinding().to(PolarKeyDownloader::class.java) keyBinder.addBinding().to(PolarKeyDownloader::class.java)
keyBinder.addBinding().to(RuneLiteKeyDownloader::class.java) keyBinder.addBinding().to(RuneLiteKeyDownloader::class.java)
val moduleBinder = Multibinder.newSetBinder(binder(), Module::class.java)
moduleBinder.addBinding().to(JavaTimeModule::class.java)
val nameBinder = Multibinder.newSetBinder(binder(), NameDownloader::class.java) val nameBinder = Multibinder.newSetBinder(binder(), NameDownloader::class.java)
nameBinder.addBinding().to(RuneStarNameDownloader::class.java) nameBinder.addBinding().to(RuneStarNameDownloader::class.java)
} }

@ -1,6 +1,8 @@
package org.openrs2.archive.cache package org.openrs2.archive.cache
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonUnwrapped
import io.netty.buffer.ByteBufAllocator import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.Unpooled import io.netty.buffer.Unpooled
import org.openrs2.buffer.use import org.openrs2.buffer.use
@ -35,21 +37,30 @@ public class CacheExporter @Inject constructor(
val size: Long, val size: Long,
val blocks: Long val blocks: Long
) { ) {
@JsonIgnore
public val allIndexesValid: Boolean = indexes == validIndexes && indexes != 0L public val allIndexesValid: Boolean = indexes == validIndexes && indexes != 0L
@JsonIgnore
public val validIndexesFraction: Double = if (indexes == 0L) { public val validIndexesFraction: Double = if (indexes == 0L) {
1.0 1.0
} else { } else {
validIndexes.toDouble() / indexes validIndexes.toDouble() / indexes
} }
@JsonIgnore
public val allGroupsValid: Boolean = groups == validGroups public val allGroupsValid: Boolean = groups == validGroups
@JsonIgnore
public val validGroupsFraction: Double = if (groups == 0L) { public val validGroupsFraction: Double = if (groups == 0L) {
1.0 1.0
} else { } else {
validGroups.toDouble() / groups validGroups.toDouble() / groups
} }
@JsonIgnore
public val allKeysValid: Boolean = keys == validKeys public val allKeysValid: Boolean = keys == validKeys
@JsonIgnore
public val validKeysFraction: Double = if (keys == 0L) { public val validKeysFraction: Double = if (keys == 0L) {
1.0 1.0
} else { } else {
@ -103,7 +114,8 @@ public class CacheExporter @Inject constructor(
val language: String, val language: String,
val builds: SortedSet<Build>, val builds: SortedSet<Build>,
val timestamp: Instant?, val timestamp: Instant?,
val names: SortedSet<String>, val sources: SortedSet<String>,
@JsonUnwrapped
val stats: Stats? val stats: Stats?
) )
@ -181,7 +193,7 @@ public class CacheExporter @Inject constructor(
val language = rows.getString(4) val language = rows.getString(4)
val builds = rows.getArray(5).array as Array<*> val builds = rows.getArray(5).array as Array<*>
val timestamp = rows.getTimestamp(6)?.toInstant() val timestamp = rows.getTimestamp(6)?.toInstant()
@Suppress("UNCHECKED_CAST") val names = rows.getArray(7).array as Array<String> @Suppress("UNCHECKED_CAST") val sources = rows.getArray(7).array as Array<String>
val validIndexes = rows.getLong(8) val validIndexes = rows.getLong(8)
val stats = if (!rows.wasNull()) { val stats = if (!rows.wasNull()) {
@ -204,7 +216,7 @@ public class CacheExporter @Inject constructor(
language, language,
builds.mapNotNull { o -> Build.fromPgObject(o as PGobject) }.toSortedSet(), builds.mapNotNull { o -> Build.fromPgObject(o as PGobject) }.toSortedSet(),
timestamp, timestamp,
names.toSortedSet(), sources.toSortedSet(),
stats stats
) )
} }

@ -40,6 +40,11 @@ public class CachesController @Inject constructor(
call.respond(ThymeleafContent("caches/index.html", mapOf("caches" to caches))) call.respond(ThymeleafContent("caches/index.html", mapOf("caches" to caches)))
} }
public suspend fun indexJson(call: ApplicationCall) {
val caches = exporter.list()
call.respond(caches)
}
public suspend fun show(call: ApplicationCall) { public suspend fun show(call: ApplicationCall) {
val id = call.parameters["id"]?.toIntOrNull() val id = call.parameters["id"]?.toIntOrNull()
if (id == null) { if (id == null) {

@ -55,6 +55,7 @@ public class WebServer @Inject constructor(
routing { routing {
get("/") { call.respond(ThymeleafContent("index.html", emptyMap())) } get("/") { call.respond(ThymeleafContent("index.html", emptyMap())) }
get("/caches") { cachesController.index(call) } get("/caches") { cachesController.index(call) }
get("/caches.json") { cachesController.indexJson(call) }
get("/caches/{id}") { cachesController.show(call) } get("/caches/{id}") { cachesController.show(call) }
get("/caches/{id}.zip") { get("/caches/{id}.zip") {
val id = call.parameters["id"] val id = call.parameters["id"]

@ -45,7 +45,7 @@
<br /> <br />
<span th:text="${#temporals.format(cache.timestamp, 'HH:mm:ss')}"></span> <span th:text="${#temporals.format(cache.timestamp, 'HH:mm:ss')}"></span>
</td> </td>
<td th:text="${#strings.setJoin(cache.names, ', ')}"></td> <td th:text="${#strings.setJoin(cache.sources, ', ')}"></td>
<td th:classappend="${cache.stats}? (${cache.stats.allIndexesValid}? 'table-success' : 'table-danger')" <td th:classappend="${cache.stats}? (${cache.stats.allIndexesValid}? 'table-success' : 'table-danger')"
class="text-right"> class="text-right">
<span <span

@ -33,6 +33,7 @@ h2 = { module = "com.h2database:h2", version = "2.0.206" }
hikaricp = { module = "com.zaxxer:HikariCP", version = "5.0.0" } hikaricp = { module = "com.zaxxer:HikariCP", version = "5.0.0" }
inlineLogger = { module = "com.michael-bull.kotlin-inline-logger:kotlin-inline-logger", version = "1.0.4" } inlineLogger = { module = "com.michael-bull.kotlin-inline-logger:kotlin-inline-logger", version = "1.0.4" }
jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
jackson-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" }
jackson-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" } jackson-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
jackson-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" } jackson-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" }
javaParser = { module = "com.github.javaparser:javaparser-symbol-solver-core", version = "3.23.1" } javaParser = { module = "com.github.javaparser:javaparser-symbol-solver-core", version = "3.23.1" }

@ -16,6 +16,7 @@ public class ObjectMapperProvider @Inject constructor(
.registerKotlinModule() .registerKotlinModule()
.registerModules(modules) .registerModules(modules)
.enable(SerializationFeature.INDENT_OUTPUT) .enable(SerializationFeature.INDENT_OUTPUT)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.setDefaultPrettyPrinter(JsonPrettyPrinter()) .setDefaultPrettyPrinter(JsonPrettyPrinter())
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
} }

@ -3,6 +3,7 @@ package org.openrs2.yaml
import com.fasterxml.jackson.databind.Module import com.fasterxml.jackson.databind.Module
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.PropertyNamingStrategies
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.registerKotlinModule import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import javax.inject.Inject import javax.inject.Inject
@ -15,6 +16,7 @@ public class ObjectMapperProvider @Inject constructor(
return ObjectMapper(YAMLFactory()) return ObjectMapper(YAMLFactory())
.registerKotlinModule() .registerKotlinModule()
.registerModules(modules) .registerModules(modules)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
} }
} }

Loading…
Cancel
Save