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

View File

@@ -10,52 +10,53 @@ package suwayomi.tachidesk.graphql.dataLoaders
import com.expediagroup.graphql.dataloader.KotlinDataLoader import com.expediagroup.graphql.dataloader.KotlinDataLoader
import org.dataloader.DataLoader import org.dataloader.DataLoader
import org.dataloader.DataLoaderFactory import org.dataloader.DataLoaderFactory
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
import org.jetbrains.exposed.sql.StdOutSqlLogger import org.jetbrains.exposed.sql.StdOutSqlLogger
import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.types.SourceType 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.MangaTable
import suwayomi.tachidesk.manga.model.table.SourceTable
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
class SourceDataLoader : KotlinDataLoader<String, SourceType> { class SourceDataLoader : KotlinDataLoader<Long, SourceType?> {
override val dataLoaderName = "SourceDataLoader" 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 { future {
Source.getSourceList().filter { it.id in ids } transaction {
.map { SourceType(it) } SourceTable.select { SourceTable.id inList ids }.map {
SourceType(it)
}
}
} }
} }
} }
class SourceForMangaDataLoader : KotlinDataLoader<Int, SourceType?> { class SourceForMangaDataLoader : KotlinDataLoader<Int, SourceType?> {
override val dataLoaderName = "SourceForMangaDataLoader" 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 { future {
transaction { transaction {
addLogger(StdOutSqlLogger) addLogger(StdOutSqlLogger)
val mangaSourceMap = MangaTable
val itemsByRef = MangaTable.innerJoin(SourceTable)
.select { MangaTable.id inList ids } .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 sourceIds = mangaSourceMap val sources = buildMap {
.values triples.forEach {
.distinct() if (!containsKey(it.second)) {
.map { it.toString() } put(it.second, SourceType(it.third))
}
val sources = Source.getSourceList() }
.filter { it.id in sourceIds } }
.map { SourceType(it) } triples.associate {
.associateBy { it.id } it.first to sources[it.second]
}
val mangaSourceTypeMap = mangaSourceMap.mapValues {
sources[it.value]
} }
ids.map { ids.map { itemsByRef[it] }
mangaSourceTypeMap[it]
}
} }
} }
} }

View File

@@ -9,16 +9,22 @@ package suwayomi.tachidesk.graphql.queries
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import graphql.schema.DataFetchingEnvironment 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.graphql.types.SourceType
import suwayomi.tachidesk.manga.impl.Source import suwayomi.tachidesk.manga.model.table.SourceTable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class SourceQuery { class SourceQuery {
fun source(dataFetchingEnvironment: DataFetchingEnvironment, id: Long): CompletableFuture<SourceType> { fun source(dataFetchingEnvironment: DataFetchingEnvironment, id: Long): CompletableFuture<SourceType?> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, SourceType>("SourceDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Long, SourceType?>("SourceDataLoader", id)
} }
fun sources(): List<SourceType> { fun sources(): List<SourceType> {
return Source.getSourceList().map { SourceType(it) } val results = transaction {
SourceTable.selectAll().toList().mapNotNull { SourceType(it) }
}
return results
} }
} }

View File

@@ -96,7 +96,7 @@ class MangaType(
return dataFetchingEnvironment.getValueFromDataLoader<Int, List<CategoryType>>("CategoriesForMangaDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, List<CategoryType>>("CategoriesForMangaDataLoader", id)
} }
fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceType> { fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceType?> {
return dataFetchingEnvironment.getValueFromDataLoader<Int, SourceType>("SourceForMangaDataLoader", id) return dataFetchingEnvironment.getValueFromDataLoader<Int, SourceType?>("SourceForMangaDataLoader", id)
} }
} }

View File

@@ -8,8 +8,16 @@
package suwayomi.tachidesk.graphql.types package suwayomi.tachidesk.graphql.types
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.ConfigurableSource
import graphql.schema.DataFetchingEnvironment 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.dataclass.SourceDataClass
import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.manga.model.table.SourceTable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class SourceType( class SourceType(
@@ -33,7 +41,28 @@ class SourceType(
displayName = source.displayName 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>> { fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<MangaType>> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, List<MangaType>>("MangaForSourceDataLoader", id) 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)
}