forked from kscience/visionforge
Add vision client-side events
This commit is contained in:
parent
6144410d22
commit
cf6d73305b
@ -9,12 +9,34 @@ import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.isEmpty
|
||||
import space.kscience.dataforge.names.plus
|
||||
import kotlin.time.Duration
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A vision used only in change propagation and showing that the target should be removed
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("null")
|
||||
public object NullVision : Vision {
|
||||
override var parent: Vision?
|
||||
get() = null
|
||||
set(_) {
|
||||
error("Can't set parent for null vision")
|
||||
}
|
||||
|
||||
override val properties: MutableVisionProperties get() = error("Can't get properties of `NullVision`")
|
||||
|
||||
override val descriptor: MetaDescriptor? = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deep copy of given Vision without external connections.
|
||||
*/
|
||||
@ -28,6 +50,22 @@ private fun Vision.deepCopy(manager: VisionManager): Vision {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An event that contains changes made to a vision.
|
||||
*
|
||||
* @param vision a new value for vision content. If the Vision is to be removed should be [NullVision]
|
||||
* @param properties updated properties
|
||||
* @param children a map of children changed in ths [VisionChange].
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("change")
|
||||
public data class VisionChange(
|
||||
public val vision: Vision? = null,
|
||||
public val properties: Meta? = null,
|
||||
public val children: Map<Name, VisionChange>? = null,
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* An update for a [Vision]
|
||||
*/
|
@ -3,50 +3,23 @@ package space.kscience.visionforge
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.dataforge.names.Name
|
||||
|
||||
/**
|
||||
* An event propagated from client to a server
|
||||
*/
|
||||
@Serializable
|
||||
public sealed interface VisionEvent
|
||||
public sealed interface VisionEvent{
|
||||
public val targetName: Name
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that consists of custom meta
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("meta")
|
||||
public class VisionMetaEvent(public val targetName: Name, public val meta: Meta) : VisionEvent
|
||||
public class VisionMetaEvent(override val targetName: Name, public val meta: Meta) : VisionEvent
|
||||
|
||||
|
||||
/**
|
||||
* A vision used only in change propagation and showing that the target should be removed
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("null")
|
||||
public object NullVision : Vision {
|
||||
override var parent: Vision?
|
||||
get() = null
|
||||
set(_) {
|
||||
error("Can't set parent for null vision")
|
||||
}
|
||||
|
||||
override val properties: MutableVisionProperties get() = error("Can't get properties of `NullVision`")
|
||||
|
||||
override val descriptor: MetaDescriptor? = null
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param vision a new value for vision content. If the Vision is to be removed should be [NullVision]
|
||||
* @param properties updated properties
|
||||
* @param children a map of children changed in ths [VisionChange].
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("change")
|
||||
public data class VisionChange(
|
||||
public val vision: Vision? = null,
|
||||
public val properties: Meta? = null,
|
||||
public val children: Map<Name, VisionChange>? = null,
|
||||
) : VisionEvent
|
||||
public class VisionChangeEvent(override val targetName: Name, public val change: VisionChange) : VisionEvent
|
@ -5,6 +5,9 @@ import kotlinx.browser.window
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
@ -141,21 +144,19 @@ public class VisionClient : AbstractPlugin() {
|
||||
|
||||
onopen = {
|
||||
feedbackJob = visionManager.context.launch {
|
||||
eventCollector.filter { it.targetName == name }.onEach {
|
||||
send(visionManager.jsonFormat.encodeToString(VisionEvent.serializer(), it))
|
||||
}.launchIn(this)
|
||||
|
||||
while (isActive) {
|
||||
delay(feedbackAggregationTime.milliseconds)
|
||||
val change = changeCollector[name] ?: continue
|
||||
if (!change.isEmpty()) {
|
||||
mutex.withLock {
|
||||
send(change.toJsonString(visionManager))
|
||||
eventCollector.emit(VisionChangeEvent(name, change.deepCopy(visionManager)))
|
||||
change.reset()
|
||||
}
|
||||
}
|
||||
// // take channel for given vision name
|
||||
// eventCollector[name]?.let { channel ->
|
||||
// for (e in channel) {
|
||||
// send(visionManager.jsonFormat.encodeToString(VisionEvent.serializer(), e))
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
logger.info { "WebSocket feedback channel established for output '$name'" }
|
||||
|
@ -75,8 +75,8 @@ public class VisionRoute(
|
||||
public fun Application.serveVisionData(
|
||||
configuration: VisionRoute,
|
||||
onEvent: suspend Vision.(VisionEvent) -> Unit = { event ->
|
||||
if (event is VisionChange) {
|
||||
update(event)
|
||||
if (event is VisionChangeEvent) {
|
||||
update(event.change)
|
||||
}
|
||||
},
|
||||
resolveVision: (Name) -> Vision?,
|
||||
|
Loading…
Reference in New Issue
Block a user