com.lightningkite.lightningserver.tasks.dsl.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of server-core Show documentation
Show all versions of server-core Show documentation
A set of tools to fill in/replace what Ktor is lacking in.
The newest version!
@file:UseContextualSerialization(Instant::class)
package com.lightningkite.lightningserver.tasks
import com.lightningkite.lightningdb.*
import com.lightningkite.lightningserver.core.LightningServerDsl
import com.lightningkite.lightningserver.serialization.Serialization
import kotlinx.coroutines.CoroutineScope
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseContextualSerialization
import kotlinx.serialization.serializer
import java.time.Instant
@LightningServerDsl
inline fun task(name: String, noinline implementation: suspend CoroutineScope.(INPUT) -> Unit) =
task(name, Serialization.module.serializer(), implementation)
@LightningServerDsl
fun task(name: String, serializer: KSerializer, implementation: suspend CoroutineScope.(INPUT) -> Unit) =
Task(name, serializer, implementation)
@LightningServerDsl
fun startup(priority: Double = 0.0, action: suspend () -> Unit) = Tasks.onEngineReady(priority, action)
@LightningServerDsl
fun defineAfterSettings(priority: Double = 0.0, action: suspend () -> Unit) = Tasks.onSettingsReady(priority, action)
@GenerateDataClassPaths
@Serializable
data class ActionHasOccurred(
override val _id: String,
val started: Instant? = null,
val completed: Instant? = null,
val errorMessage: String? = null
) : HasId
@LightningServerDsl
fun startupOnce(
name: String,
database: () -> Database,
maxDuration: Long = 60_000,
priority: Double = 0.0,
action: suspend () -> Unit
): StartupAction {
prepareModels()
return startup(priority) {
doOnce(name, database, maxDuration, priority, action)
}
}
@LightningServerDsl
suspend fun doOnce(
name: String,
database: () -> Database,
maxDuration: Long = 60_000,
priority: Double = 0.0,
action: suspend () -> Unit
) {
prepareModels()
val a = database().collection()
val existing = a.get(name)
if (existing == null) {
a.insertOne(ActionHasOccurred(_id = name, started = Instant.now()))
} else {
val lock = a.updateOne(
condition {
it._id eq name and (it.completed eq null) and (it.started eq null or (it.started.notNull lt Instant.now()
.minusSeconds(maxDuration)))
},
modification { it.started assign Instant.now() }
)
if (lock.new == null) return
}
try {
action()
a.updateOneById(
name,
modification {
it.completed assign Instant.now()
it.errorMessage assign null
}
)
} catch (e: Exception) {
a.updateOneById(
name,
modification {
(it.errorMessage assign e.message)
(it.started assign null)
}
)
}
}