20211010 Event Handling - orbitalfoundation/wiki GitHub Wiki

WAYS TO WIRE SERVICES TOGETHER

Listen to a path

Rust side services can ask the broker to request to mount themselves on a path and listen to traffic there. This is a good way (if you are a service) to listen for commands and work to do from the outside world. This is the expected way a service starts to get commands and do work:

		let receiver_channel = broker::listen("/services/view");

		while let Ok(blob) = receiver_channel.recv() {
			// do work...
		}

Listen to a path manually

Rust side services can alternatively request to listen to a path by supplying both sides of the channel by hand - channels are just ordinary rust crossbeam channels. The difference from above here is slight, but there are arguably some cases where a service might want to know the sender channel. For example one can imagine a case where a service passes a handle on the sender channel to some third party to allow direct comms bypassing the broker.

		let (sender_channel,receiver_channel) = crossbeam::unbounded::<Message>();

		broker::listen_manually("/service/view",sender_channel)

		while let Ok(blob) = receiver_channel.recv() {
			// ... do work
		}

Send messages via broker

A script, or some code, or a service can send messages. Typically sending a message to the broker - that then forwards said message onwards. This is the main way that arbitrary pieces of code drive the whole system forward, they basically issue commands. This is similar to calling methods in a library - such as calling the POSIX library methods - but since Orbital is 100% event and message driven there is actually no direct binding of low level libraries - and you have to send messages always to do any work:

		broker::event({
			target:"/services/view",
			command:"frag",
			fragment:{
				path:"/myscene/mycube",
				kind:"cube",
				whd:[1,1,1],
				ypr:[0,0,0],
				xyz:[0,0,0],
				color:"blue"
			}
		})

Service Spawn

The only way to spawn any new service in Orbital is to call one of the built-in services and ask it to make some other service. For example a WASM blob can be loaded and run by calling the built-in WASM service which manages those topics. Or a instance of a scripting engine is spawned in a similar way. Any service you spawn typically mounts its own message receiver - think of it as a snorkel for it to get air via - and once spawned you can talk to it.

		broker::event({
			target:"/services/scripting",
			command:"spawn",
			script:"/public/accounts/root/myscript.js",
			listen:"/accounts/root/scripts/myscript",
		})

Service Spawn and Echo

It's also common - and in fact preferable - that if you want traffic from a service that you tell that service specifically to send traffic to you. This is slightly different from what one might imagine as the standard pattern. One might imagine that you would tell the broker to echo traffic to you - but it turns out it is more useful to make services themselves a bit smarter, and have them do the sending.

		broker::event({
			target:"/services/timer",
			command:"spawn",
			millis:"1000",
			listen:"/accounts/root/scripts/myscript/mytimer",
			echo:"/accounts/root/scripts/myscript",
		})

Echo only

Also, existing services can be asked to echo to you.

		broker::event({
			target:"/services/view",
			command:"echo",
			echo:"/accounts/root/scripts/myscript",
		})

Security

[TBD]

Manifests and Messaging

An application manifest is a text file that describes a pile of services to bring up, and how to wire them together. It's effectively just a json file, and in fact building the wiring is done in javascript - effectively the scripting is used to produce the Rust side arrangement of services and wires. This can also be done by hand, manifests are a convenience concept.

		let app = {
			path:"/accounts/root/apps/myapp",
			mytimer:{
				target:"/service/timer", // service to talk to
				command:"spawn", // command for it to do
				millis:"1000",  // 
				listen:"*mytimer", // in the case of spawning, where to mount a listener relatively to app
				echo:"*"
			},
			myview:{
				target:"/service/view",
				command:"echo",
				echo:"*",
			},
			myboot:{
				target:"/service/scripting",
				command:"spawn",
				script:"/public/root/app/boot.js",
				listen:"*"
			},
		}
⚠️ **GitHub.com Fallback** ⚠️