You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

58 lines
2.4 KiB
Kotlin

package me.eater.hefbrug.executor
import me.eater.hefbrug.access.ExecutionOutput
import me.eater.hefbrug.access.Local
import me.eater.hefbrug.definition.DefinitionKey
import me.eater.hefbrug.definition.DefinitionSkeleton
import me.eater.hefbrug.dsl.context.DefinitionContextSkeleton
import me.eater.hefbrug.dsl.scope.SelectorScope
import me.eater.hefbrug.logging.Logging
import me.eater.hefbrug.logging.message.Messages
import me.eater.hefbrug.node.Node
import me.eater.hefbrug.state.AbstractState
import me.eater.hefbrug.utils.parallel
import org.apache.logging.log4j.MarkerManager
import org.jetbrains.kotlin.utils.mapToIndex
class ExecutionInstance(private val node: Node, private val definitions: Map<DefinitionKey, DefinitionSkeleton<*, *>>) :
Logging {
suspend fun apply(noop: Boolean = true) {
val layers = GraphBuilder.makeGraph(definitions)
debug("Graph created ${layers.size} layers of definitions to apply")
val context = ExecutionContext(Local(), node, noop)
val collector = StateCollector(context)
val enforcer = StateEnforcer(context)
for ((layer, i) in layers.mapToIndex()) {
debug("Start applying layer #$i for @|green $node|@")
parallel(layer) { item ->
debug(Messages.applying(item, node))
val def = definitions[item] ?: run {
error("Missing definition for @|blue $item|@")
return@parallel
}
try {
trace(Messages.collectingCurrentState(item, node))
@Suppress("UNCHECKED_CAST") val state =
collector.collect(def as DefinitionSkeleton<AbstractState, DefinitionContextSkeleton<AbstractState>>)
trace(Messages.startEnforcing(item, node))
enforcer.enforce(def, state)
} catch (e: ExecutionOutput.ExecutionException) {
error(Messages.failedDefinition(def.key, node, e.output))
} catch (t: Throwable) {
error(
MarkerManager.getMarker("DefinitionError"),
"Failed collecting and enforcing state for @|blue $item|@ for @|green $node|@",
t
)
}
}
}
}
companion object {
suspend fun forNode(node: Node, scope: SelectorScope) = ExecutionInstance(node, scope.collect(node))
}
}