Switch to a new Ktlint Formatter (#705)

* Switch to new Ktlint plugin

* Add ktlintCheck to PR builds

* Run formatter

* Put ktlint version in libs toml

* Fix lint

* Use Zip4Java from libs.toml
This commit is contained in:
Mitchell Syer
2023-10-06 23:38:39 -04:00
committed by GitHub
parent 3cd3cb0186
commit 849acfca3d
277 changed files with 6709 additions and 5090 deletions

View File

@@ -5,7 +5,14 @@ import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
interface IUpdater {
fun getLastUpdateTimestamp(): Long
fun addCategoriesToUpdateQueue(categories: List<CategoryDataClass>, clear: Boolean?, forceAll: Boolean)
fun addCategoriesToUpdateQueue(
categories: List<CategoryDataClass>,
clear: Boolean?,
forceAll: Boolean,
)
val status: StateFlow<UpdateStatus>
fun reset()
}

View File

@@ -7,10 +7,10 @@ enum class JobStatus {
RUNNING,
COMPLETE,
FAILED,
SKIPPED
SKIPPED,
}
data class UpdateJob(
val manga: MangaDataClass,
val status: JobStatus = JobStatus.PENDING
val status: JobStatus = JobStatus.PENDING,
)

View File

@@ -5,7 +5,8 @@ import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
enum class CategoryUpdateStatus {
UPDATING, SKIPPED
UPDATING,
SKIPPED,
}
data class UpdateStatus(
@@ -13,16 +14,21 @@ data class UpdateStatus(
val mangaStatusMap: Map<JobStatus, List<MangaDataClass>> = emptyMap(),
val running: Boolean = false,
@JsonIgnore
val numberOfJobs: Int = 0
val numberOfJobs: Int = 0,
) {
constructor(categories: Map<CategoryUpdateStatus, List<CategoryDataClass>>, jobs: List<UpdateJob>, skippedMangas: List<MangaDataClass>, running: Boolean) : this(
constructor(
categories: Map<CategoryUpdateStatus, List<CategoryDataClass>>,
jobs: List<UpdateJob>,
skippedMangas: List<MangaDataClass>,
running: Boolean,
) : this(
categories,
mangaStatusMap = jobs.groupBy { it.status }
.mapValues { entry ->
entry.value.map { it.manga }
}.plus(Pair(JobStatus.SKIPPED, skippedMangas)),
mangaStatusMap =
jobs.groupBy { it.status }
.mapValues { entry ->
entry.value.map { it.manga }
}.plus(Pair(JobStatus.SKIPPED, skippedMangas)),
running = running,
numberOfJobs = jobs.size
numberOfJobs = jobs.size,
)
}

View File

@@ -70,7 +70,7 @@ class Updater : IUpdater {
}
}
},
ignoreInitialValue = false
ignoreInitialValue = false,
)
}
@@ -87,7 +87,11 @@ class Updater : IUpdater {
return
}
logger.info { "Trigger global update (interval= ${serverConfig.globalUpdateInterval.value}h, lastAutomatedUpdate= ${Date(lastAutomatedUpdate)})" }
logger.info {
"Trigger global update (interval= ${serverConfig.globalUpdateInterval.value}h, lastAutomatedUpdate= ${Date(
lastAutomatedUpdate,
)})"
}
addCategoriesToUpdateQueue(Category.getCategoryList(), clear = true, forceAll = false)
}
@@ -103,7 +107,10 @@ class Updater : IUpdater {
val lastAutomatedUpdate = preferences.getLong(lastAutomatedUpdateKey, 0)
val timeToNextExecution = (updateInterval - (System.currentTimeMillis() - lastAutomatedUpdate)).mod(updateInterval)
val wasPreviousUpdateTriggered = System.currentTimeMillis() - (if (lastAutomatedUpdate > 0) lastAutomatedUpdate else System.currentTimeMillis()) < updateInterval
val wasPreviousUpdateTriggered =
System.currentTimeMillis() - (
if (lastAutomatedUpdate > 0) lastAutomatedUpdate else System.currentTimeMillis()
) < updateInterval
if (!wasPreviousUpdateTriggered) {
autoUpdateTask()
}
@@ -114,7 +121,12 @@ class Updater : IUpdater {
/**
* Updates the status and sustains the "skippedMangas"
*/
private fun updateStatus(jobs: List<UpdateJob>, running: Boolean, categories: Map<CategoryUpdateStatus, List<CategoryDataClass>>? = null, skippedMangas: List<MangaDataClass>? = null) {
private fun updateStatus(
jobs: List<UpdateJob>,
running: Boolean,
categories: Map<CategoryUpdateStatus, List<CategoryDataClass>>? = null,
skippedMangas: List<MangaDataClass>? = null,
) {
val updateStatusCategories = categories ?: _status.value.categoryStatusMap
val tmpSkippedMangas = skippedMangas ?: _status.value.mangaStatusMap[JobStatus.SKIPPED] ?: emptyList()
_status.update { UpdateStatus(updateStatusCategories, jobs, tmpSkippedMangas, running) }
@@ -136,7 +148,7 @@ class Updater : IUpdater {
process(job),
tracker.any { (_, job) ->
job.status == JobStatus.PENDING || job.status == JobStatus.RUNNING
}
},
)
}
}
@@ -148,19 +160,24 @@ class Updater : IUpdater {
private suspend fun process(job: UpdateJob): List<UpdateJob> {
tracker[job.manga.id] = job.copy(status = JobStatus.RUNNING)
updateStatus(tracker.values.toList(), true)
tracker[job.manga.id] = try {
logger.info { "Updating \"${job.manga.title}\" (source: ${job.manga.sourceId})" }
Chapter.getChapterList(job.manga.id, true)
job.copy(status = JobStatus.COMPLETE)
} catch (e: Exception) {
if (e is CancellationException) throw e
logger.error(e) { "Error while updating ${job.manga.title}" }
job.copy(status = JobStatus.FAILED)
}
tracker[job.manga.id] =
try {
logger.info { "Updating \"${job.manga.title}\" (source: ${job.manga.sourceId})" }
Chapter.getChapterList(job.manga.id, true)
job.copy(status = JobStatus.COMPLETE)
} catch (e: Exception) {
if (e is CancellationException) throw e
logger.error(e) { "Error while updating ${job.manga.title}" }
job.copy(status = JobStatus.FAILED)
}
return tracker.values.toList()
}
override fun addCategoriesToUpdateQueue(categories: List<CategoryDataClass>, clear: Boolean?, forceAll: Boolean) {
override fun addCategoriesToUpdateQueue(
categories: List<CategoryDataClass>,
clear: Boolean?,
forceAll: Boolean,
) {
preferences.putLong(lastUpdateKey, System.currentTimeMillis())
if (clear == true) {
@@ -171,31 +188,53 @@ class Updater : IUpdater {
val excludedCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.EXCLUDE].orEmpty()
val includedCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.INCLUDE].orEmpty()
val unsetCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.UNSET].orEmpty()
val categoriesToUpdate = if (forceAll) {
categories
} else {
includedCategories.ifEmpty { unsetCategories }
}
val categoriesToUpdate =
if (forceAll) {
categories
} else {
includedCategories.ifEmpty { unsetCategories }
}
val skippedCategories = categories.subtract(categoriesToUpdate.toSet()).toList()
val updateStatusCategories = mapOf(
Pair(CategoryUpdateStatus.UPDATING, categoriesToUpdate),
Pair(CategoryUpdateStatus.SKIPPED, skippedCategories)
)
val updateStatusCategories =
mapOf(
Pair(CategoryUpdateStatus.UPDATING, categoriesToUpdate),
Pair(CategoryUpdateStatus.SKIPPED, skippedCategories),
)
logger.debug { "Updating categories: '${categoriesToUpdate.joinToString("', '") { it.name }}'" }
val categoriesToUpdateMangas = categoriesToUpdate
.flatMap { CategoryManga.getCategoryMangaList(it.id) }
.distinctBy { it.id }
val categoriesToUpdateMangas =
categoriesToUpdate
.flatMap { CategoryManga.getCategoryMangaList(it.id) }
.distinctBy { it.id }
val mangasToCategoriesMap = CategoryManga.getMangasCategories(categoriesToUpdateMangas.map { it.id })
val mangasToUpdate = categoriesToUpdateMangas
.asSequence()
.filter { it.updateStrategy == UpdateStrategy.ALWAYS_UPDATE }
.filter { if (serverConfig.excludeUnreadChapters.value) { (it.unreadCount ?: 0L) == 0L } else true }
.filter { if (serverConfig.excludeNotStarted.value) { it.lastReadAt != null } else true }
.filter { if (serverConfig.excludeCompleted.value) { it.status != MangaStatus.COMPLETED.name } else true }
.filter { forceAll || !excludedCategories.any { category -> mangasToCategoriesMap[it.id]?.contains(category) == true } }
.toList()
val mangasToUpdate =
categoriesToUpdateMangas
.asSequence()
.filter { it.updateStrategy == UpdateStrategy.ALWAYS_UPDATE }
.filter {
if (serverConfig.excludeUnreadChapters.value) {
(it.unreadCount ?: 0L) == 0L
} else {
true
}
}
.filter {
if (serverConfig.excludeNotStarted.value) {
it.lastReadAt != null
} else {
true
}
}
.filter {
if (serverConfig.excludeCompleted.value) {
it.status != MangaStatus.COMPLETED.name
} else {
true
}
}
.filter { forceAll || !excludedCategories.any { category -> mangasToCategoriesMap[it.id]?.contains(category) == true } }
.toList()
val skippedMangas = categoriesToUpdateMangas.subtract(mangasToUpdate.toSet()).toList()
// In case no manga gets updated and no update job was running before, the client would never receive an info about its update request
@@ -207,7 +246,7 @@ class Updater : IUpdater {
addMangasToQueue(
mangasToUpdate
.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER, MangaDataClass::title))
.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER, MangaDataClass::title)),
)
}

View File

@@ -19,22 +19,26 @@ object UpdaterSocket : Websocket<UpdateStatus>() {
private val updater by DI.global.instance<IUpdater>()
private var job: Job? = null
override fun notifyClient(ctx: WsContext, value: UpdateStatus?) {
override fun notifyClient(
ctx: WsContext,
value: UpdateStatus?,
) {
ctx.send(value ?: updater.status.value)
}
override fun handleRequest(ctx: WsMessageContext) {
when (ctx.message()) {
"STATUS" -> notifyClient(ctx, updater.status.value)
else -> ctx.send(
"""
else ->
ctx.send(
"""
|Invalid command.
|Supported commands are:
| - STATUS
| sends the current update status
|
""".trimMargin()
)
""".trimMargin(),
)
}
}

View File

@@ -6,16 +6,24 @@ import java.util.concurrent.ConcurrentHashMap
abstract class Websocket<T> {
protected val clients = ConcurrentHashMap<String, WsContext>()
open fun addClient(ctx: WsContext) {
clients[ctx.sessionId] = ctx
notifyClient(ctx, null)
}
open fun removeClient(ctx: WsContext) {
clients.remove(ctx.sessionId)
}
open fun notifyAllClients(value: T) {
clients.values.forEach { notifyClient(it, value) }
}
abstract fun notifyClient(ctx: WsContext, value: T?)
abstract fun notifyClient(
ctx: WsContext,
value: T?,
)
abstract fun handleRequest(ctx: WsMessageContext)
}