forked from kscience/visionforge
Refactor server API
This commit is contained in:
parent
fef1df3ab4
commit
d28873e796
@ -31,7 +31,7 @@ fun main() {
|
|||||||
|
|
||||||
val form = VisionOfHtmlForm("form").apply {
|
val form = VisionOfHtmlForm("form").apply {
|
||||||
onPropertyChange(visionManager.context) {
|
onPropertyChange(visionManager.context) {
|
||||||
println(this)
|
println(values)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ fun main() {
|
|||||||
value = "Submit"
|
value = "Submit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println(form.values)
|
||||||
vision(form)
|
vision(form)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,8 @@ public class VisionChangeBuilder : MutableVisionContainer<Vision> {
|
|||||||
private var propertyChange = MutableMeta()
|
private var propertyChange = MutableMeta()
|
||||||
private val children: HashMap<Name, VisionChangeBuilder> = HashMap()
|
private val children: HashMap<Name, VisionChangeBuilder> = HashMap()
|
||||||
|
|
||||||
|
public operator fun get(name: Name): VisionChangeBuilder? = children[name]
|
||||||
|
|
||||||
public fun isEmpty(): Boolean = propertyChange.isEmpty() && propertyChange.isEmpty() && children.isEmpty()
|
public fun isEmpty(): Boolean = propertyChange.isEmpty() && propertyChange.isEmpty() && children.isEmpty()
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@ -153,7 +155,7 @@ private fun CoroutineScope.collectChange(
|
|||||||
*/
|
*/
|
||||||
public fun Vision.flowChanges(
|
public fun Vision.flowChanges(
|
||||||
collectionDuration: Duration,
|
collectionDuration: Duration,
|
||||||
sendInitial: Boolean = false
|
sendInitial: Boolean = false,
|
||||||
): Flow<VisionChange> = flow {
|
): Flow<VisionChange> = flow {
|
||||||
val manager = manager ?: error("Orphan vision could not collect changes")
|
val manager = manager ?: error("Orphan vision could not collect changes")
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
@ -161,7 +163,7 @@ public fun Vision.flowChanges(
|
|||||||
val mutex = Mutex()
|
val mutex = Mutex()
|
||||||
collectChange(Name.EMPTY, this@flowChanges, mutex, collector)
|
collectChange(Name.EMPTY, this@flowChanges, mutex, collector)
|
||||||
|
|
||||||
if(sendInitial) {
|
if (sendInitial) {
|
||||||
//Send initial vision state
|
//Send initial vision state
|
||||||
val initialChange = VisionChange(vision = deepCopy(manager))
|
val initialChange = VisionChange(vision = deepCopy(manager))
|
||||||
emit(initialChange)
|
emit(initialChange)
|
||||||
|
@ -69,9 +69,9 @@ public class VisionClient : AbstractPlugin() {
|
|||||||
changeCollector.propertyChanged(visionName, propertyName, item)
|
changeCollector.propertyChanged(visionName, propertyName, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun visionChanged(name: Name?, child: Vision?) {
|
// public fun visionChanged(name: Name?, child: Vision?) {
|
||||||
changeCollector.setChild(name, child)
|
// changeCollector.setChild(name, child)
|
||||||
}
|
// }
|
||||||
|
|
||||||
private fun renderVision(element: Element, name: Name, vision: Vision, outputMeta: Meta) {
|
private fun renderVision(element: Element, name: Name, vision: Vision, outputMeta: Meta) {
|
||||||
vision.setAsRoot(visionManager)
|
vision.setAsRoot(visionManager)
|
||||||
@ -79,7 +79,7 @@ public class VisionClient : AbstractPlugin() {
|
|||||||
renderer.render(element, name, vision, outputMeta)
|
renderer.render(element, name, vision, outputMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateVision(element: Element, name: Name, vision: Vision?, outputMeta: Meta) {
|
private fun startVisionUpdate(element: Element, name: Name, vision: Vision?, outputMeta: Meta) {
|
||||||
element.attributes[OUTPUT_CONNECT_ATTRIBUTE]?.let { attr ->
|
element.attributes[OUTPUT_CONNECT_ATTRIBUTE]?.let { attr ->
|
||||||
val wsUrl = if (attr.value.isBlank() || attr.value == VisionTagConsumer.AUTO_DATA_ATTRIBUTE) {
|
val wsUrl = if (attr.value.isBlank() || attr.value == VisionTagConsumer.AUTO_DATA_ATTRIBUTE) {
|
||||||
val endpoint = resolveEndpoint(element)
|
val endpoint = resolveEndpoint(element)
|
||||||
@ -130,9 +130,10 @@ public class VisionClient : AbstractPlugin() {
|
|||||||
feedbackJob = visionManager.context.launch {
|
feedbackJob = visionManager.context.launch {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
delay(feedbackAggregationTime.milliseconds)
|
delay(feedbackAggregationTime.milliseconds)
|
||||||
if (!changeCollector.isEmpty()) {
|
val change = changeCollector[name] ?: continue
|
||||||
send(visionManager.encodeToString(changeCollector.deepCopy(visionManager)))
|
if (!change.isEmpty()) {
|
||||||
changeCollector.reset()
|
send(visionManager.encodeToString(change.deepCopy(visionManager)))
|
||||||
|
change.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +193,7 @@ public class VisionClient : AbstractPlugin() {
|
|||||||
response.text().then { text ->
|
response.text().then { text ->
|
||||||
val vision = visionManager.decodeFromString(text)
|
val vision = visionManager.decodeFromString(text)
|
||||||
renderVision(element, name, vision, outputMeta)
|
renderVision(element, name, vision, outputMeta)
|
||||||
updateVision(element, name, vision, outputMeta)
|
startVisionUpdate(element, name, vision, outputMeta)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error { "Failed to fetch initial vision state from $fetchUrl" }
|
logger.error { "Failed to fetch initial vision state from $fetchUrl" }
|
||||||
@ -208,12 +209,12 @@ public class VisionClient : AbstractPlugin() {
|
|||||||
}
|
}
|
||||||
logger.info { "Found embedded vision for output with name $name" }
|
logger.info { "Found embedded vision for output with name $name" }
|
||||||
renderVision(element, name, embeddedVision, outputMeta)
|
renderVision(element, name, embeddedVision, outputMeta)
|
||||||
updateVision(element, name, embeddedVision, outputMeta)
|
startVisionUpdate(element, name, embeddedVision, outputMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Try to load vision via websocket
|
//Try to load vision via websocket
|
||||||
element.attributes[OUTPUT_CONNECT_ATTRIBUTE] != null -> {
|
element.attributes[OUTPUT_CONNECT_ATTRIBUTE] != null -> {
|
||||||
updateVision(element, name, null, outputMeta)
|
startVisionUpdate(element, name, null, outputMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> error("No embedded vision data / fetch url for $name")
|
else -> error("No embedded vision data / fetch url for $name")
|
||||||
|
@ -93,12 +93,12 @@ public fun Application.serveVisionData(
|
|||||||
webSocket("ws") {
|
webSocket("ws") {
|
||||||
val name: String = call.request.queryParameters.getOrFail("name")
|
val name: String = call.request.queryParameters.getOrFail("name")
|
||||||
application.log.debug("Opened server socket for $name")
|
application.log.debug("Opened server socket for $name")
|
||||||
val vision: Vision = resolveVision(Name.parse(name)) ?: error("Plot with id='$name' not registered")
|
val vision: Vision = resolveVision(Name.parse(name)) ?: error("Vision with id='$name' not registered")
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
for(frame in incoming) {
|
for(frame in incoming) {
|
||||||
val data = frame.data.decodeToString()
|
val data = frame.data.decodeToString()
|
||||||
application.log.debug("Received update: \n$data")
|
application.log.debug("Received update for $name: \n$data")
|
||||||
val change = configuration.visionManager.jsonFormat.decodeFromString(
|
val change = configuration.visionManager.jsonFormat.decodeFromString(
|
||||||
VisionChange.serializer(), data
|
VisionChange.serializer(), data
|
||||||
)
|
)
|
||||||
@ -113,7 +113,7 @@ public fun Application.serveVisionData(
|
|||||||
VisionChange.serializer(),
|
VisionChange.serializer(),
|
||||||
update
|
update
|
||||||
)
|
)
|
||||||
application.log.debug("Sending update: \n$json")
|
application.log.debug("Sending update for $name: \n$json")
|
||||||
outgoing.send(Frame.Text(json))
|
outgoing.send(Frame.Text(json))
|
||||||
}.collect()
|
}.collect()
|
||||||
}
|
}
|
||||||
@ -145,27 +145,6 @@ public fun Application.serveVisionData(
|
|||||||
data: Map<Name, Vision>,
|
data: Map<Name, Vision>,
|
||||||
): Unit = serveVisionData(configuration) { data[it] }
|
): Unit = serveVisionData(configuration) { data[it] }
|
||||||
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Compile a fragment to string and serve visions from it
|
|
||||||
// */
|
|
||||||
//public fun Route.serveVisionsFromFragment(
|
|
||||||
// consumer: TagConsumer<*>,
|
|
||||||
// sererPageUrl: Url,
|
|
||||||
// visionManager: VisionManager,
|
|
||||||
// fragment: HtmlVisionFragment,
|
|
||||||
//): Unit {
|
|
||||||
// val visions = consumer.visionFragment(
|
|
||||||
// visionManager.context,
|
|
||||||
// embedData = true,
|
|
||||||
// fetchUpdatesUrl = "$serverUrl$route/ws",
|
|
||||||
// fragment = fragment
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// serveVisionData(visionManager, visions)
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serve a page, potentially containing any number of visions at a given [route] with given [header].
|
* Serve a page, potentially containing any number of visions at a given [route] with given [header].
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user