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