diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt index 13f476db..9f5fa6ec 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt @@ -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 { +class SourceDataLoader : KotlinDataLoader { override val dataLoaderName = "SourceDataLoader" - override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(): DataLoader = 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 { override val dataLoaderName = "SourceForMangaDataLoader" - override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> + override fun getDataLoader(): DataLoader = 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] } } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt index edfb44d2..b28719c5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt @@ -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 { - return dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", id) + fun source(dataFetchingEnvironment: DataFetchingEnvironment, id: Long): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", id) } fun sources(): List { - return Source.getSourceList().map { SourceType(it) } + val results = transaction { + SourceTable.selectAll().toList().mapNotNull { SourceType(it) } + } + + return results } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt index 01e21816..8ded86b4 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt @@ -96,7 +96,7 @@ class MangaType( return dataFetchingEnvironment.getValueFromDataLoader>("CategoriesForMangaDataLoader", id) } - fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("SourceForMangaDataLoader", id) + fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("SourceForMangaDataLoader", id) } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt index c157747d..c5c7611e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt @@ -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> { return dataFetchingEnvironment.getValueFromDataLoader>("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) +}