Crate flo_scene_pipe

Crate flo_scene_pipe 

Source
Expand description

flo_scene_pipe provides ways to connect scenes created in flo_scene across process boundaries.

This can create socket programs using different protocols. These will automatically accept connections and pass them on as messages. For example, start_unencrypted_tcp_socket() will create a TCP/IP socket subprogram that will decode and encode messages for the scene. Socket subprograms send SocketMessage::Connection() messages to the scene to indicate when a new connection is established. Receivers of this message can use it to read and write messages to the corresponding connection.

Internal (in-process), TCP and unix domain sockets are supported.

This also adds an interactive command interpreter that can be used to interact directly with a scene. This provides a lot of use cases - for example:

  • Debug or query a running system
  • Run automatic tests on a system that’s in production at a lower level than just clicking around the UI or prodding public API instances (for example as part of a commisioning process)
  • Configure or reconfigure a system without needing to restart it
  • Load modules or upgrade them in place, particularly when combined with flo_scene_wasm

The command interface runs as a subprogram that interacts with a socket. Commands are themselves served by subprograms. For example, you can set up a unix-domain socket like this:

use flo_scene::*;
use flo_scene_pipe::*;
use flo_scene_pipe::commands::*;

// Create a scene with some commands
let scene = Scene::default()
    .with_standard_json_commands();

// Create a program that will receive connections from the socket and run commands
let command_program = SubProgramId::new();
scene.add_subprogram(command_program, |input, context| command_connection_program(input, context, ()), 0);

// Set up a UNIX socket that will parse commands in the standard syntax using `read_command_data`
// and write the results to the output using `write_command_data`
let socket_program = SubProgramId::new();
start_unix_socket_program(&scene, socket_program, "./example_unix_socket", read_command_data, write_command_data).unwrap();

// Connect the programs together so socket connects are processed by the command program
scene.connect_programs(socket_program, command_program, StreamId::with_message_type::<CommandProgramSocketMessage>()).unwrap();

Connect to this socket with socat - UNIX-CONNECT:./example_unix_socket - it will present an interactive prompt where you can type help to get more instructions.

This pattern can be used to make other kinds of server: replace read_command_data and write_command_data with your own functions to set the format of the data sent over the socket and replace command_connection_program to define how those messages are processed. The different socket types can be chosen by changing start_unix_socket_program to something else.

New commands can be created using CommandLauncher which can be used to configure a subprogram to process them. For example:

use flo_scene::commands::*;
 
let command_program = SubProgramId::called("my_crate::my_commands");
let json_launcher = CommandLauncher::json()
    .with_json_command("::test", |param: String, _context| async move {
        CommandResponse::Json(serde_json::Value::String(param))
    });
scene.add_subprogram(command_program, json_launcher.to_subprogram(), 1);

Re-exports§

pub use commands::JsonCommandLauncherExt;
pub use standard_json_commands::StandardCommandsLauncherExt;
pub use standard_json_commands::StandardCommandsSceneExt;

Modules§

commands
parser
standard_json_commands
A set of command subprograms that implement a basic set of commands for interacting with a scene

Structs§

SocketConnection
Represents an incoming socket connection. When a socket is connected, we retrieve an input stream, and need to respond with an output stream.

Enums§

InternalSocketMessage
Requests that can be made to the internal socket program
SocketMessage
Event message sent from a program that represents a socket. Socket programs represent points where two-way connections can be made to this program.

Functions§

socket_listener_subprogram
Runs a socket listener suprogram. This accepts ‘Subscribe’ messages from subprograms that wish to receive connections (subscription messages are sent in a round-robin fashion), and calls the ‘accept_message’ function to receive incoming connections
start_internal_socket_program
Creates an internal socket program
start_unencrypted_tcp_socket
Starts a sub-program that accepts unencrypted connections on a TCP socket.
start_unix_socket_program
Starts a sub-program in a sceme that accepts connections on a unix domain socket that binds at a specified path