Skip to content

1. Your first Process

In this first chapter you run a Process that just adds 1 to its argument and returns it. The code you write is a single short function, but juiz loads it and turns it into a building block you can call over the network.

Clone and build the example repository. All later commands are run from the root of the cloned repository.

Terminal window
git clone https://github.com/OpenJUIZ/juiz_examples_rust.git
cd juiz_examples_rust
cargo build

Each example is built as a shared library in target/debug.

This Process adds 1 to the argument arg1 and returns it.

process/increment_process/src/lib.rs

use juiz_sdk::prelude::*;
#[juiz_process]
fn increment_process(arg1: i64) -> JuizResult<Capsule> {
log::trace!("increment_process({:?}) called", arg1);
return Ok(jvalue!(arg1 + 1).into());
}

A function marked with #[juiz_process] becomes a Process. The function name increment_process is the Process’s type name, and the parameter name arg1 becomes the argument name as is. The return value is created with jvalue! and converted into a Capsule.

The crate’s Cargo.toml builds it as a shared library (crate-type = ["cdylib"]).

In every language, a Process is just a function that takes arguments and returns a result. It does not read or write any outside state, so the same arguments always give the same result (it is idempotent). Thanks to this, a Process is easy to test, and its behavior does not change when you later connect it to others or move it to another machine.

Start juiz with the file given by --process.

Terminal window
juiz --process ./target/debug/libincrement_process.so -e -1 -d

On macOS the extension is .dylib (./target/debug/libincrement_process.dylib).

The options mean the following.

Option Meaning
--process <path> Load a Process file
-l <language> Language of the file (rust / python / cpp, default rust)
-1 Create one instance from the loaded Process
-e Run the created instance once with its default arguments
-d Start the HTTP broker on port 8000 and keep running (exit with Ctrl+C)

Notice that “loading” and “creating an instance” are separate steps. When juiz loads a file, it learns the Process’s type (how to make it). With -1, it creates one instance from that type. The instance name is the type name followed by 0 (for example increment_process0). You can also create several instances with different names from the same type (covered in chapter 3).

Leave juiz running, open another terminal, and call the Process. First, list the running Processes.

Terminal window
juiz process list
# => ["http://127.0.0.1:8000/process/increment_process0::increment_process"]

The URL shown is this Process’s ID. http://127.0.0.1:8000 is where the Process lives (its broker), and the part after process/ means “instance name::type name”.

Call the Process with this ID and its arguments (call). Arguments are passed as JSON.

Terminal window
juiz process call "http://127.0.0.1:8000/process/increment_process0::increment_process" '{"arg1": 3}' -p
# => CapsulePtr((value:Value(4), option: []))

You passed 3 and got 4 back. -p prints the result. Try calling it several times to confirm that the same arguments always give the same result.

The HTTP broker started with -d also serves Swagger UI. Open this URL in your browser.

http://127.0.0.1:8000/docs/

Open PATCH /api/process/call in the list, press “Try it out”, enter the following, and press “Execute” to get the result.

  • identifier: core://core/process/increment_process0::increment_process
  • Request body: {"arg1": 3}

Both the juiz command and Swagger UI simply call the same API over HTTP. In other words, any program that speaks HTTP, in any language, can call a Process and get the result back. This is call, the way of using juiz like a server and client.

Change what the Process does and run it again. For example, make it return double the argument instead of adding 1, rebuild it (Python needs no rebuild), and restart juiz. Calling it with {"arg1": 3} should now return 6.

The example repository also contains a Process that subtracts 1 (decrement_process). You can run it the same way.

  • A Process is an idempotent function that just takes arguments and returns a result. You can write it in Rust, Python or C++.
  • juiz loads a file to learn a Process type, then creates named instances from it.
  • A running Process has an ID shaped like a URL, and you can call it from outside with that ID and arguments (call).

In the next chapter you learn how to write a building block that keeps state, using a counter as the example. Move on to Keeping state: Container and ContainerProcess.