jp.nephy.kchroner.plugin.executor.ScheduleTaskExecutor.kt Maven / Gradle / Ivy
package jp.nephy.kchroner.plugin.executor
import jp.nephy.kchroner.KChroner
import jp.nephy.kchroner.plugin.Registrable
import jp.nephy.kchroner.plugin.tasks.ScheduleTask
import kotlinx.coroutines.experimental.*
import java.io.Closeable
import java.lang.reflect.InvocationTargetException
import java.util.*
import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.TimeUnit
private val logger = KChroner.logger("KChroner.ScheduleTaskExecutor")
class ScheduleTaskExecutor: Registrable, Closeable {
private val tasks = CopyOnWriteArraySet()
private val masterJob = Job()
val job by lazy {
launch(parent = masterJob) {
logger.debug { "ScheduleTaskExecutorが開始されました." }
while (isActive) {
try {
val calendar = Calendar.getInstance()
delay(60000L - calendar.get(Calendar.SECOND) * 1000L - calendar.get(Calendar.MILLISECOND), TimeUnit.MILLISECONDS)
val newCalendar = Calendar.getInstance()
tasks.filter { it.matches(newCalendar) }.forEach {
launch(parent = masterJob) {
try {
it.invoke()
logger.trace { "${it.subscription.name} が実行されました." }
} catch (e: CancellationException) {
withContext(NonCancellable) {
logger.debug { "${it.subscription.name} はキャンセルされました." }
}
} catch (e: Exception) {
val throwable = (e as? InvocationTargetException)?.targetException ?: e
logger.error(throwable) { "${it.subscription.name} の実行中に例外が発生しました." }
}
}
}
delay(1, TimeUnit.SECONDS)
} catch (e: CancellationException) {
break
}
}
logger.info { "ScheduleTaskExecutorが終了しました." }
}
}
override fun register(target: ScheduleTask): Boolean {
return tasks.add(target)
}
override fun unregister(target: ScheduleTask): Boolean {
return tasks.remove(target)
}
override fun close() {
runBlocking(CommonPool) {
masterJob.cancelChildren()
masterJob.cancelAndJoin()
}
}
}