Directly use the database for sources in graphql

This commit is contained in:
Syer10
2023-03-31 20:29:55 -04:00
parent 007d20d417
commit 37f41ade43
4 changed files with 67 additions and 31 deletions
@@ -10,52 +10,53 @@ package suwayomi.tachidesk.graphql.dataLoaders
import com.expediagroup.graphql.dataloader.KotlinDataLoader
import org.dataloader.DataLoader
import org.dataloader.DataLoaderFactory
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
import org.jetbrains.exposed.sql.StdOutSqlLogger
import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.types.SourceType
import suwayomi.tachidesk.manga.impl.Source
import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.manga.model.table.SourceTable
import suwayomi.tachidesk.server.JavalinSetup.future
class SourceDataLoader : KotlinDataLoader<String, SourceType> {
class SourceDataLoader : KotlinDataLoader<Long, SourceType?> {
override val dataLoaderName = "SourceDataLoader"
override fun getDataLoader(): DataLoader<String, SourceType> = DataLoaderFactory.newDataLoader<String, SourceType> { ids ->
override fun getDataLoader(): DataLoader<Long, SourceType?> = DataLoaderFactory.newDataLoader { ids ->
future {
Source.getSourceList().filter { it.id in ids }
.map { SourceType(it) }
transaction {
SourceTable.select { SourceTable.id inList ids }.map {
SourceType(it)
}
}
}
}
}
class SourceForMangaDataLoader : KotlinDataLoader<Int, SourceType?> {
override val dataLoaderName = "SourceForMangaDataLoader"
override fun getDataLoader(): DataLoader<Int, SourceType?> = DataLoaderFactory.newDataLoader<Int, SourceType?> { ids ->
override fun getDataLoader(): DataLoader<Int, SourceType?> = DataLoaderFactory.newDataLoader { ids ->
future {
transaction {
addLogger(StdOutSqlLogger)
val mangaSourceMap = MangaTable
val itemsByRef = MangaTable.innerJoin(SourceTable)
.select { MangaTable.id inList ids }
.associate { it[MangaTable.id].value to it[MangaTable.sourceReference] }
.map { Triple(it[MangaTable.id].value, it[MangaTable.sourceReference], it) }
.let { triples ->
val sources = buildMap {
triples.forEach {
if (!containsKey(it.second)) {
put(it.second, SourceType(it.third))
}
}
}
triples.associate {
it.first to sources[it.second]
}
}
val sourceIds = mangaSourceMap
.values
.distinct()
.map { it.toString() }
val sources = Source.getSourceList()
.filter { it.id in sourceIds }
.map { SourceType(it) }
.associateBy { it.id }
val mangaSourceTypeMap = mangaSourceMap.mapValues {
sources[it.value]
}
ids.map {
mangaSourceTypeMap[it]
}
ids.map { itemsByRef[it] }
}
}
}
@@ -9,16 +9,22 @@ package suwayomi.tachidesk.graphql.queries
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.types.SourceType
import suwayomi.tachidesk.manga.impl.Source
import suwayomi.tachidesk.manga.model.table.SourceTable
import java.util.concurrent.CompletableFuture
class SourceQuery {
fun source(dataFetchingEnvironment: DataFetchingEnvironment, id: Long): CompletableFuture<SourceType> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, SourceType>("SourceDataLoader", id)
fun source(dataFetchingEnvironment: DataFetchingEnvironment, id: Long): CompletableFuture<SourceType?> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, SourceType?>("SourceDataLoader", id)
}
fun sources(): List<SourceType> {
return Source.getSourceList().map { SourceType(it) }
val results = transaction {
SourceTable.selectAll().toList().mapNotNull { SourceType(it) }
}
return results
}
}
@@ -96,7 +96,7 @@ class MangaType(
return dataFetchingEnvironment.getValueFromDataLoader<Int, List<CategoryType>>("CategoriesForMangaDataLoader", id)
}
fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceType> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, SourceType>("SourceForMangaDataLoader", id)
fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceType?> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, SourceType?>("SourceForMangaDataLoader", id)
}
}
@@ -8,8 +8,16 @@
package suwayomi.tachidesk.graphql.types
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.ConfigurableSource
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.select
import suwayomi.tachidesk.manga.impl.extension.Extension
import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass
import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.manga.model.table.SourceTable
import java.util.concurrent.CompletableFuture
class SourceType(
@@ -33,7 +41,28 @@ class SourceType(
displayName = source.displayName
)
constructor(row: ResultRow, sourceExtension: ResultRow, catalogueSource: CatalogueSource) : this(
id = row[SourceTable.id].value,
name = row[SourceTable.name],
lang = row[SourceTable.lang],
iconUrl = Extension.getExtensionIconUrl(sourceExtension[ExtensionTable.apkName]),
supportsLatest = catalogueSource.supportsLatest,
isConfigurable = catalogueSource is ConfigurableSource,
isNsfw = row[SourceTable.isNsfw],
displayName = catalogueSource.toString()
)
fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<MangaType>> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, List<MangaType>>("MangaForSourceDataLoader", id)
}
}
fun SourceType(row: ResultRow): SourceType? {
val catalogueSource = GetCatalogueSource
.getCatalogueSourceOrNull(row[SourceTable.id].value)
?: return null
val sourceExtension = ExtensionTable
.select { ExtensionTable.id eq row[SourceTable.extension] }
.first()
return SourceType(row, sourceExtension, catalogueSource)
}