Single-file Rust Syndicate services

As of crates syndicate v0.44.0-rc.6 and syndicate-macros v0.35.0-rc.4, and in conjunction with the new cargo -Zscript feature, it is now possible to write single-file Rust Syndicate services that can be started from syndicate-server as separate processes.

If you place the following code into, say, test.rs, and then chmod a+x test.rs, you will be able to run ./test.rs and feed it snippets of the Syndicate protocol:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env -S cargo +nightly -Zscript -q
---cargo
[dependencies]
syndicate = "0.44.0-rc.6"
syndicate-macros = "0.35.0-rc.4"
tokio = "*"
tracing = "*"
---
syndicate::stdio_service!{
    ($v) => |t| {
        t.on_stop(enclose!((v) move |_t| { tracing::info!("- {v:?}"); Ok(()) }));
        tracing::info!("+ {v:?}");
        Ok(())
    };
}

Here’s an example of direct interaction with the script:

1
2
3
4
5
6
7
8
$ ./test.rs
 INFO test: + <Observe <bind <_>> #:"⌜1/12:0000000101cd8890⌝">
[[0 <A hello-world 1>]]
 INFO test: + hello-world
[[0 <R 1>]]
 INFO test: - hello-world
^D
 INFO test: - <Observe <bind <_>> #:"⌜1/12:0000000101cd8890⌝">

We first see the script notice its own subscription to its dataspace, printing it as an INFO message. Then, we type [[0 <A hello-world 1>]], a turn that asserts the symbol hello-world to object #0 (the service object exposed to clients). The second INFO is the reaction of the service. Next, we type [[0 <R 1>]], a turn that retracts assertion number 1. The service prints the third INFO in response. Finally, we type control-D to close the standard input, and the service prints the final INFO as it shuts down, “noticing” the retraction of its own subscription.