@@ -2,19 +2,24 @@ package at.ac.uibk.dps.cirrina
22
33import at.ac.uibk.dps.cirrina.cirrina.di.Main
44import at.ac.uibk.dps.cirrina.cirrina.di.Run
5- import at.ac.uibk.dps.cirrina.execution.graph.EventGraph
65import at.ac.uibk.dps.cirrina.execution.`object`.*
76import at.ac.uibk.dps.cirrina.execution.service.RandomServiceImplementationSelector
87import at.ac.uibk.dps.cirrina.execution.service.ServiceImplementation
9- import at.ac.uibk.dps.cirrina.execution.service.ServiceImplementationSelector
108import at.ac.uibk.dps.cirrina.io.CsmParser
9+ import at.ac.uibk.dps.cirrina.spec.ContextVariable
1110import at.ac.uibk.dps.cirrina.spec.Csml as CsmlSpec
11+ import at.ac.uibk.dps.cirrina.spec.Event
12+ import at.ac.uibk.dps.cirrina.spec.Instance
13+ import at.ac.uibk.dps.cirrina.spec.graph.EventGraph
1214import com.codahale.metrics.MetricRegistry
1315import com.codahale.metrics.Timer
1416import jakarta.inject.Inject
1517import java.net.URI
18+ import kotlin.collections.component1
19+ import kotlin.collections.component2
1620import kotlin.time.measureTime
1721import kotlin.time.toJavaDuration
22+ import kotlinx.coroutines.SupervisorJob
1823import kotlinx.coroutines.joinAll
1924import kotlinx.coroutines.runBlocking
2025import mu.KotlinLogging
@@ -24,75 +29,100 @@ private val logger = KotlinLogging.logger {}
2429class Runtime
2530@Inject
2631constructor (
27- @Run private val run: List <String >,
32+ @Run run: List <String >,
2833 @Main main: URI ,
34+ metricRegistry: MetricRegistry ,
2935 persistentContext: Context ? ,
3036 stateMachineFactory: StateMachine .Factory ,
31- val metricRegistry: MetricRegistry ,
32- ) {
33- val eventHandler = EventHandler ()
37+ ) : PropagationHandler {
3438 val extent = persistentContext?.let { Extent .of(it) } ? : Extent .of()
3539
36- val selector : ServiceImplementationSelector
40+ val eventHandler = EventHandler ( this )
3741
38- private val instances: Map <String , StateMachine >
42+ private val csml =
43+ CsmlSpec .create(CsmParser .parseCsml(main))
44+ .onFailure { logger.error(it) { " failed to initialize collaborative state machine class" } }
45+ .getOrThrow()
3946
40- private val graph: EventGraph
47+ val serviceImplementationSelector =
48+ RandomServiceImplementationSelector (ServiceImplementation .from(csml.bindings ? : emptyList()))
49+
50+ private val runtimeJob = SupervisorJob ()
4151
4252 private var completion: Timer = metricRegistry.timer(" runtime.completionTime" )
4353
44- init {
45- val spec =
46- CsmlSpec .create(CsmParser .parseCsml(main))
47- .onFailure { logger.error(it) { " failed to initialize collaborative state machine class" } }
48- .getOrThrow()
54+ inner class InstanceRegistry (private val stateMachineFactory : StateMachine .Factory ) {
55+ @Volatile
56+ var version = 0L
57+ private set
4958
50- selector =
51- RandomServiceImplementationSelector (ServiceImplementation .from(spec.bindings ? : emptyList()))
59+ private val graph = EventGraph ()
5260
53- persistentContext?.let { context ->
54- spec.collaborativeStateMachine.persistentContext.forEach { variable ->
55- runCatching { context.create(variable.name, variable.value) }
56- .onFailure {
57- logger.warn { " variable '${variable.name} ' already exists or failed to create" }
58- }
59- }
61+ val instances: List <StateMachine >
62+ get() = graph.instances
63+
64+ fun instantiate (
65+ instance : Instance ,
66+ instanceData : List <ContextVariable > =
67+ instance.data.map { (k, v) -> ContextVariable (k, v.evaluate()) },
68+ ) {
69+ val hierarchy =
70+ stateMachineFactory.createHierarchy(
71+ name = instance.name,
72+ specification = instance.stateMachine,
73+ instanceData = instanceData,
74+ instanceSubscription = instance.subscription,
75+ instanceRegistry = this ,
76+ parent = null ,
77+ runtimeExtent = extent,
78+ eventHandler = eventHandler,
79+ serviceImplementationSelector = serviceImplementationSelector,
80+ )
81+
82+ hierarchy.forEach { machine -> graph.addInstance(machine) }
83+
84+ ++ version
85+
86+ val instances = graph.instances
87+
88+ eventHandler.addPublishers(graph.getOutgoing(instances).map { it.event })
89+ eventHandler.addSubscribers(instances.flatMap { it.subscriptions })
90+
91+ hierarchy.forEach { machine -> machine.start(parentContext = runtimeJob) }
6092 }
6193
62- instances =
63- spec.instances
64- .filter { it.name in run }
65- .flatMap { instance ->
66- stateMachineFactory.createHierarchy(
67- name = instance.name,
68- specification = instance.stateMachine,
69- instance = instance,
70- subscriptions =
71- spec.instances.filter { instance.subscription.matches(it.name) }.map { it.name },
72- runtime = this ,
73- parent = null ,
74- )
75- }
76- .associateBy { it.name }
94+ fun findStateMachineInstance (name : String ): StateMachine ? =
95+ graph.instances.filter { it.name == name }.firstOrNull()
96+ }
7797
78- graph = EventGraph .create(spec.instances )
98+ private val instanceRegistry = InstanceRegistry (stateMachineFactory )
7999
80- eventHandler.bind(
81- graph = graph,
82- instanceNames = run,
83- subscribedTo = instances.values.flatMap { it.subscriptions }.toSet(),
84- handlers = instances.values.map { it::pushEvent },
85- )
100+ init {
101+ persistentContext?.let { context ->
102+ csml.collaborativeStateMachine.persistentContext.forEach { (k, v) ->
103+ runCatching { context.create(k, v.evaluate()) }
104+ .onFailure { logger.warn { " variable '${k} ' already exists or failed to create" } }
105+ }
106+ }
107+ csml.instances.filter { it.name in run }.forEach { instanceRegistry.instantiate(it) }
86108 }
87109
88110 fun run () = runBlocking {
89- measureTime { instances.values.map { it.start() }.joinAll() }
111+ measureTime {
112+ while (runtimeJob.children.any()) {
113+ runtimeJob.children.toList().joinAll()
114+ }
115+
116+ runtimeJob.complete()
117+ runtimeJob.join()
118+ }
90119 .also {
91120 completion.update(it.toJavaDuration())
92121 logger.info { " runtime terminated in $it " }
93122 }
94123 }
95124
96- fun findStateMachineInstance (stateMachineObjectName : String ): StateMachine ? =
97- instances[stateMachineObjectName]
125+ override fun invoke (event : Event ) {
126+ instanceRegistry.instances.forEach { it.pushEvent(event) }
127+ }
98128}
0 commit comments