enabled mode
This commit is contained in:
parent
7f014a494c
commit
9c6aa304a8
@ -50,7 +50,7 @@ fun main(args: Array<String>) {
|
|||||||
eventsDatabase.createTables(tasks, runners)
|
eventsDatabase.createTables(tasks, runners)
|
||||||
taskManager = TasksManager(eventsDatabase)
|
taskManager = TasksManager(eventsDatabase)
|
||||||
|
|
||||||
runnerManager = RunnerManager(dataSource = getEventsDatabase(), name = ConvertApplication::class.java.simpleName)
|
runnerManager = RunnerManager(dataSource = getEventsDatabase(), applicationName = ConvertApplication::class.java.simpleName)
|
||||||
runnerManager.assignRunner()
|
runnerManager.assignRunner()
|
||||||
|
|
||||||
runApplication<ConvertApplication>(*args)
|
runApplication<ConvertApplication>(*args)
|
||||||
|
|||||||
@ -19,7 +19,7 @@ class TaskCoordinator(): TaskCoordinatorBase() {
|
|||||||
|
|
||||||
override fun onCoordinatorReady() {
|
override fun onCoordinatorReady() {
|
||||||
super.onCoordinatorReady()
|
super.onCoordinatorReady()
|
||||||
runnerManager = RunnerManager(dataSource = getEventsDatabase(), name = ConvertApplication::class.java.simpleName)
|
runnerManager = RunnerManager(dataSource = getEventsDatabase(), applicationName = ConvertApplication::class.java.simpleName)
|
||||||
runnerManager.assignRunner()
|
runnerManager.assignRunner()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +77,10 @@ class TaskCoordinator(): TaskCoordinatorBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getEnabledState(): Boolean {
|
||||||
|
return runnerManager.amIEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
interface TaskEvents {
|
interface TaskEvents {
|
||||||
fun onCancelOrStopProcess(eventId: String)
|
fun onCancelOrStopProcess(eventId: String)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,7 @@ fun main(args: Array<String>) {
|
|||||||
)
|
)
|
||||||
storeDatabase.createTables(*tables)
|
storeDatabase.createTables(*tables)
|
||||||
|
|
||||||
runnerManager = RunnerManager(dataSource = eventDatabase.database, name = CoordinatorApplication::class.java.simpleName)
|
runnerManager = RunnerManager(dataSource = eventDatabase.database, applicationName = CoordinatorApplication::class.java.simpleName)
|
||||||
runnerManager.assignRunner()
|
runnerManager.assignRunner()
|
||||||
|
|
||||||
runApplication<CoordinatorApplication>(*args)
|
runApplication<CoordinatorApplication>(*args)
|
||||||
|
|||||||
@ -98,4 +98,10 @@ class Coordinator(
|
|||||||
}
|
}
|
||||||
return taskMode
|
return taskMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateEnabledState(): Boolean {
|
||||||
|
isEnabled = runnerManager.amIEnabled()
|
||||||
|
return isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,7 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
taskManager = TasksManager(eventsDatabase)
|
taskManager = TasksManager(eventsDatabase)
|
||||||
|
|
||||||
runnerManager = RunnerManager(dataSource = getEventsDatabase(), name = ProcesserApplication::class.java.simpleName)
|
runnerManager = RunnerManager(dataSource = getEventsDatabase(), applicationName = ProcesserApplication::class.java.simpleName)
|
||||||
runnerManager.assignRunner()
|
runnerManager.assignRunner()
|
||||||
|
|
||||||
runApplication<ProcesserApplication>(*args)
|
runApplication<ProcesserApplication>(*args)
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class TaskCoordinator(): TaskCoordinatorBase() {
|
|||||||
|
|
||||||
override fun onCoordinatorReady() {
|
override fun onCoordinatorReady() {
|
||||||
super.onCoordinatorReady()
|
super.onCoordinatorReady()
|
||||||
runnerManager = RunnerManager(dataSource = getEventsDatabase(), name = ProcesserApplication::class.java.simpleName)
|
runnerManager = RunnerManager(dataSource = getEventsDatabase(), applicationName = ProcesserApplication::class.java.simpleName)
|
||||||
runnerManager.assignRunner()
|
runnerManager.assignRunner()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +68,10 @@ class TaskCoordinator(): TaskCoordinatorBase() {
|
|||||||
taskManager.produceEvent(event)
|
taskManager.produceEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getEnabledState(): Boolean {
|
||||||
|
return runnerManager.amIEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
override fun clearExpiredClaims() {
|
override fun clearExpiredClaims() {
|
||||||
val expiredClaims = taskManager.getTasksWithExpiredClaim().filter { it.task in listOf(TaskType.Encode, TaskType.Extract) }
|
val expiredClaims = taskManager.getTasksWithExpiredClaim().filter { it.task in listOf(TaskType.Encode, TaskType.Extract) }
|
||||||
expiredClaims.forEach {
|
expiredClaims.forEach {
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
package no.iktdev.mediaprocessing.processer
|
||||||
|
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.contract.Events
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.contract.data.Event
|
||||||
|
import no.iktdev.mediaprocessing.shared.common.contract.jsonToEvent
|
||||||
|
import org.json.JSONArray
|
||||||
|
|
||||||
|
enum class Files(val fileName: String) {
|
||||||
|
Output1("encodeProgress1.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun Files.getAsList(): List<String> {
|
||||||
|
return this.javaClass.classLoader.getResource(this.fileName)?.readText()?.lines() ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun Files.getContent(): String? {
|
||||||
|
return this.javaClass.classLoader.getResource(this.fileName)?.readText()
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package no.iktdev.mediaprocessing.processer.ffmpeg
|
||||||
|
|
||||||
|
import no.iktdev.mediaprocessing.processer.Files
|
||||||
|
import no.iktdev.mediaprocessing.processer.getAsList
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class FfmpegRunnerTest {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package no.iktdev.mediaprocessing.processer.ffmpeg.progress
|
||||||
|
|
||||||
|
import no.iktdev.mediaprocessing.processer.Files
|
||||||
|
import no.iktdev.mediaprocessing.processer.ffmpeg.FfmpegRunner
|
||||||
|
import no.iktdev.mediaprocessing.processer.getAsList
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class FfmpegProgressDecoderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Verify that progress can be decoded")
|
||||||
|
fun parseReadout1() {
|
||||||
|
val lines = Files.Output1.getAsList()
|
||||||
|
val decoder = FfmpegProgressDecoder()
|
||||||
|
lines.forEach {
|
||||||
|
decoder.defineDuration(it)
|
||||||
|
}
|
||||||
|
val result = decoder.parseVideoProgress(lines)
|
||||||
|
assertThat(result?.progress).isNotNull()
|
||||||
|
val progress = decoder.getProgress(result!!)
|
||||||
|
assertThat(progress.progress).isGreaterThanOrEqualTo(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
141
apps/processer/src/test/resources/encodeProgress1.txt
Normal file
141
apps/processer/src/test/resources/encodeProgress1.txt
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
Guessed Channel Layout for Input Stream #0.1 : 5.1
|
||||||
|
Input #0, matroska,webm, from '/src/input/completed/standalone/Potato.mkv':
|
||||||
|
Metadata:
|
||||||
|
encoder : libebml v1.3.10 + libmatroska v1.5.2
|
||||||
|
creation_time : 2020-02-17T16:42:19.000000Z
|
||||||
|
Duration: 00:29:09.75, start: 0.000000, bitrate: 9882 kb/s
|
||||||
|
Stream #0:0: Video: h264 (High), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
|
||||||
|
Metadata:
|
||||||
|
BPS-eng : 9239506
|
||||||
|
DURATION-eng : 00:29:09.748000000
|
||||||
|
NUMBER_OF_FRAMES-eng: 41952
|
||||||
|
NUMBER_OF_BYTES-eng: 2020851044
|
||||||
|
_STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit
|
||||||
|
_STATISTICS_WRITING_DATE_UTC-eng: 2020-02-17 16:42:19
|
||||||
|
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
|
||||||
|
Stream #0:1(eng): Audio: eac3, 48000 Hz, 5.1, fltp (default)
|
||||||
|
Metadata:
|
||||||
|
BPS-eng : 640000
|
||||||
|
DURATION-eng : 00:29:09.728000000
|
||||||
|
NUMBER_OF_FRAMES-eng: 54679
|
||||||
|
NUMBER_OF_BYTES-eng: 139978240
|
||||||
|
_STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit
|
||||||
|
_STATISTICS_WRITING_DATE_UTC-eng: 2020-02-17 16:42:19
|
||||||
|
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
|
||||||
|
Stream #0:2(eng): Subtitle: subrip
|
||||||
|
Metadata:
|
||||||
|
BPS-eng : 120
|
||||||
|
DURATION-eng : 00:28:08.917000000
|
||||||
|
NUMBER_OF_FRAMES-eng: 718
|
||||||
|
NUMBER_OF_BYTES-eng: 25445
|
||||||
|
_STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit
|
||||||
|
_STATISTICS_WRITING_DATE_UTC-eng: 2020-02-17 16:42:19
|
||||||
|
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
|
||||||
|
Stream #0:3(eng): Subtitle: subrip
|
||||||
|
Metadata:
|
||||||
|
title : SDH
|
||||||
|
BPS-eng : 120
|
||||||
|
DURATION-eng : 00:28:08.917000000
|
||||||
|
NUMBER_OF_FRAMES-eng: 718
|
||||||
|
NUMBER_OF_BYTES-eng: 25445
|
||||||
|
_STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit
|
||||||
|
_STATISTICS_WRITING_DATE_UTC-eng: 2020-02-17 16:42:19
|
||||||
|
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
|
||||||
|
Stream mapping:
|
||||||
|
Stream #0:0 -> #0:0 (h264 (native) -> hevc (libx265))
|
||||||
|
Stream #0:1 -> #0:1 (copy)
|
||||||
|
x265 [info]: HEVC encoder version 3.4
|
||||||
|
x265 [info]: build info [Linux][GCC 9.3.0][64 bit] 8bit+10bit+12bit
|
||||||
|
x265 [info]: using cpu capabilities: MMX2 SSE2Fast LZCNT SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
|
||||||
|
x265 [info]: Main profile, Level-4 (Main tier)
|
||||||
|
x265 [info]: Thread pool created using 16 threads
|
||||||
|
x265 [info]: Slices : 1
|
||||||
|
x265 [info]: frame threads / pool features : 4 / wpp(17 rows)
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
set_mempolicy: Operation not permitted
|
||||||
|
x265 [info]: Coding QT: max CU size, min CU size : 64 / 8
|
||||||
|
x265 [info]: Residual QT: max TU size, max depth : 32 / 1 inter / 1 intra
|
||||||
|
x265 [info]: ME / range / subpel / merge : hex / 57 / 2 / 3
|
||||||
|
x265 [info]: Keyframe min / max / scenecut / bias : 23 / 250 / 40 / 5.00
|
||||||
|
x265 [info]: Lookahead / bframes / badapt : 20 / 4 / 2
|
||||||
|
x265 [info]: b-pyramid / weightp / weightb : 1 / 1 / 0
|
||||||
|
x265 [info]: References / ref-limit cu / depth : 3 / off / on
|
||||||
|
x265 [info]: AQ: mode / str / qg-size / cu-tree : 2 / 1.0 / 32 / 1
|
||||||
|
x265 [info]: Rate Control / qCompress : CRF-16.0 / 0.60
|
||||||
|
x265 [info]: tools: rd=3 psy-rd=2.00 early-skip rskip mode=1 signhide tmvp
|
||||||
|
x265 [info]: tools: b-intra strong-intra-smoothing lslices=6 deblock sao
|
||||||
|
[mp4 @ 0x64a098f4e140] track 1: codec frame size is not set
|
||||||
|
Output #0, mp4, to '/src/cache/Potato.work.mp4':
|
||||||
|
Metadata:
|
||||||
|
encoder : Lavf58.45.100
|
||||||
|
Stream #0:0: Video: hevc (libx265) (hev1 / 0x31766568), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
|
||||||
|
Metadata:
|
||||||
|
BPS-eng : 9239506
|
||||||
|
DURATION-eng : 00:29:09.748000000
|
||||||
|
NUMBER_OF_FRAMES-eng: 41952
|
||||||
|
NUMBER_OF_BYTES-eng: 2020851044
|
||||||
|
_STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit
|
||||||
|
_STATISTICS_WRITING_DATE_UTC-eng: 2020-02-17 16:42:19
|
||||||
|
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
|
||||||
|
encoder : Lavc58.91.100 libx265
|
||||||
|
Side data:
|
||||||
|
cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
|
||||||
|
Stream #0:1(eng): Audio: eac3 (ec-3 / 0x332D6365), 48000 Hz, 5.1, fltp (default)
|
||||||
|
Metadata:
|
||||||
|
BPS-eng : 640000
|
||||||
|
DURATION-eng : 00:29:09.728000000
|
||||||
|
NUMBER_OF_FRAMES-eng: 54679
|
||||||
|
NUMBER_OF_BYTES-eng: 139978240
|
||||||
|
_STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit
|
||||||
|
_STATISTICS_WRITING_DATE_UTC-eng: 2020-02-17 16:42:19
|
||||||
|
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
|
||||||
|
frame=34
|
||||||
|
fps=0.00
|
||||||
|
stream_0_0_q=21.9
|
||||||
|
bitrate= 0.2kbits/s
|
||||||
|
total_size=44
|
||||||
|
out_time_us=2198000
|
||||||
|
out_time_ms=2198000
|
||||||
|
out_time=00:00:02.198000
|
||||||
|
dup_frames=0
|
||||||
|
drop_frames=0
|
||||||
|
speed=4.04x
|
||||||
|
progress=continue
|
||||||
@ -13,6 +13,7 @@ import javax.annotation.PostConstruct
|
|||||||
abstract class TaskCoordinatorBase() {
|
abstract class TaskCoordinatorBase() {
|
||||||
private val log = KotlinLogging.logger {}
|
private val log = KotlinLogging.logger {}
|
||||||
var taskMode: ActiveMode = ActiveMode.Active
|
var taskMode: ActiveMode = ActiveMode.Active
|
||||||
|
var isEnabled: Boolean = true
|
||||||
private var ready: Boolean = false
|
private var ready: Boolean = false
|
||||||
fun isReady() = ready
|
fun isReady() = ready
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ abstract class TaskCoordinatorBase() {
|
|||||||
|
|
||||||
@Scheduled(fixedDelay = (5_000))
|
@Scheduled(fixedDelay = (5_000))
|
||||||
fun pullAvailable() {
|
fun pullAvailable() {
|
||||||
if (taskMode != ActiveMode.Active) {
|
if (taskMode != ActiveMode.Active || !isEnabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pullForAvailableTasks()
|
pullForAvailableTasks()
|
||||||
@ -51,6 +52,20 @@ abstract class TaskCoordinatorBase() {
|
|||||||
|
|
||||||
abstract fun clearExpiredClaims()
|
abstract fun clearExpiredClaims()
|
||||||
|
|
||||||
|
abstract fun getEnabledState(): Boolean
|
||||||
|
|
||||||
|
@Scheduled(fixedDelay = 10_000)
|
||||||
|
fun pullEnabledState() {
|
||||||
|
val prevState = isEnabled
|
||||||
|
isEnabled = getEnabledState()
|
||||||
|
if (prevState != isEnabled) {
|
||||||
|
log.info { "State changed for coordinator: $prevState -> $isEnabled" }
|
||||||
|
if (isEnabled) {
|
||||||
|
log.info { "New tasks will now be processed" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Scheduled(fixedDelay = (300_000))
|
@Scheduled(fixedDelay = (300_000))
|
||||||
fun resetExpiredClaims() {
|
fun resetExpiredClaims() {
|
||||||
if (taskMode != ActiveMode.Active) {
|
if (taskMode != ActiveMode.Active) {
|
||||||
|
|||||||
@ -11,24 +11,35 @@ import org.jetbrains.exposed.sql.insert
|
|||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.sql.select
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
class RunnerManager(private val dataSource: DataSource, private val startId: String = UUID.randomUUID().toString(), val name: String) {
|
class RunnerManager(private val dataSource: DataSource, val startId: String = UUID.randomUUID().toString(), val applicationName: String) {
|
||||||
private val log = KotlinLogging.logger {}
|
private val log = KotlinLogging.logger {}
|
||||||
|
|
||||||
fun assignRunner(): Boolean {
|
fun assignRunner(): Boolean {
|
||||||
return executeOrException(dataSource.database) {
|
return executeOrException(dataSource.database) {
|
||||||
runners.insert {
|
runners.insert {
|
||||||
it[runners.startId] = this@RunnerManager.startId
|
it[runners.startId] = this@RunnerManager.startId
|
||||||
it[runners.application] = this@RunnerManager.name
|
it[runners.application] = this@RunnerManager.applicationName
|
||||||
it[runners.version] = getAppVersion()
|
it[runners.version] = getAppVersion()
|
||||||
}
|
}
|
||||||
} == null
|
} == null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun amIEnabled(): Boolean {
|
||||||
|
return withDirtyRead(dataSource.database) {
|
||||||
|
runners.select {
|
||||||
|
(runners.application eq applicationName) and
|
||||||
|
(runners.startId eq startId)
|
||||||
|
}.singleOrNull()?.get(runners.enabled)
|
||||||
|
} ?: run {
|
||||||
|
log.error { "Failed to get a response, reporting false for enabled" }
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun iAmSuperseded(): Boolean {
|
fun iAmSuperseded(): Boolean {
|
||||||
return withDirtyRead(dataSource.database) {
|
return withDirtyRead(dataSource.database) {
|
||||||
val runnerVersionCodes = runners.select {
|
val runnerVersionCodes = runners.select {
|
||||||
(runners.application eq this@RunnerManager.name) and
|
(runners.application eq this@RunnerManager.applicationName) and
|
||||||
(runners.startId neq this@RunnerManager.startId)
|
(runners.startId neq this@RunnerManager.startId)
|
||||||
|
|
||||||
}.map { it[runners.version] }
|
}.map { it[runners.version] }
|
||||||
|
|||||||
@ -11,4 +11,5 @@ object runners: IntIdTable() {
|
|||||||
val application: Column<String> = varchar("application", 50)
|
val application: Column<String> = varchar("application", 50)
|
||||||
val version: Column<Int> = integer("version")
|
val version: Column<Int> = integer("version")
|
||||||
val created: Column<LocalDateTime> = datetime("created").defaultExpression(CurrentDateTime)
|
val created: Column<LocalDateTime> = datetime("created").defaultExpression(CurrentDateTime)
|
||||||
|
val enabled: Column<Boolean> = bool("enabled").default(true)
|
||||||
}
|
}
|
||||||
@ -36,6 +36,7 @@ abstract class EventCoordinator<T : EventImpl, E : EventsManagerImpl<T>> {
|
|||||||
|
|
||||||
|
|
||||||
open var taskMode: ActiveMode = ActiveMode.Active
|
open var taskMode: ActiveMode = ActiveMode.Active
|
||||||
|
open var isEnabled: Boolean = true
|
||||||
private val referencePool: MutableMap<String, Deferred<Boolean>> = mutableMapOf()
|
private val referencePool: MutableMap<String, Deferred<Boolean>> = mutableMapOf()
|
||||||
private fun referencePoolIsReadyForEvents(): Boolean {
|
private fun referencePoolIsReadyForEvents(): Boolean {
|
||||||
return (referencePool.isEmpty() || referencePool.any { !it.value.isActive })
|
return (referencePool.isEmpty() || referencePool.any { !it.value.isActive })
|
||||||
@ -44,6 +45,7 @@ abstract class EventCoordinator<T : EventImpl, E : EventsManagerImpl<T>> {
|
|||||||
private var newEventProduced: Boolean = false
|
private var newEventProduced: Boolean = false
|
||||||
|
|
||||||
abstract fun getActiveTaskMode(): ActiveMode
|
abstract fun getActiveTaskMode(): ActiveMode
|
||||||
|
abstract fun updateEnabledState(): Boolean
|
||||||
|
|
||||||
private var activePolls: Int = 0
|
private var activePolls: Int = 0
|
||||||
data class PollStats(val active: Int, val total: Int)
|
data class PollStats(val active: Int, val total: Int)
|
||||||
@ -119,7 +121,8 @@ abstract class EventCoordinator<T : EventImpl, E : EventsManagerImpl<T>> {
|
|||||||
var cachedReferenceList: MutableList<String> = mutableListOf()
|
var cachedReferenceList: MutableList<String> = mutableListOf()
|
||||||
private fun pullForEvents() {
|
private fun pullForEvents() {
|
||||||
coroutine.launch {
|
coroutine.launch {
|
||||||
while (taskMode == ActiveMode.Active && coroutine.isActive) {
|
while (taskMode == ActiveMode.Active && coroutine.isActive && isEnabled) {
|
||||||
|
|
||||||
if (referencePoolIsReadyForEvents()) {
|
if (referencePoolIsReadyForEvents()) {
|
||||||
log.debug { "New pull on database" }
|
log.debug { "New pull on database" }
|
||||||
val referenceIdsAvailable = eventManager.getAvailableReferenceIds()
|
val referenceIdsAvailable = eventManager.getAvailableReferenceIds()
|
||||||
@ -155,6 +158,21 @@ abstract class EventCoordinator<T : EventImpl, E : EventsManagerImpl<T>> {
|
|||||||
}
|
}
|
||||||
taskMode = getActiveTaskMode()
|
taskMode = getActiveTaskMode()
|
||||||
}
|
}
|
||||||
|
coroutine.launch {
|
||||||
|
while (taskMode == ActiveMode.Active && coroutine.isActive) {
|
||||||
|
val previousState = isEnabled
|
||||||
|
val iminentStatus = updateEnabledState()
|
||||||
|
if (previousState != iminentStatus) {
|
||||||
|
log.info { "Observed change to enabled state, changed $previousState -> $iminentStatus" }
|
||||||
|
if (iminentStatus) {
|
||||||
|
log.info { "Ovserved change to enabled state, new state is enabled\n\tRestarting pullForEvents!" }
|
||||||
|
onReady()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(10_000)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var cachedListeners: List<String> = emptyList()
|
private var cachedListeners: List<String> = emptyList()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user