All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lightningkite.lightningserver.tasks.dsl.kt Maven / Gradle / Ivy

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)
            }
        )
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy