![Flawless Logo, a beautiful woman with freckles head illustration.](/img/logo.png)
Your First Workflow
First, you will need to start the Flawless server with:
$ flawless up
Setting up a cargo
project
Let's now use cargo flw
to create a new Flawless project:
$ cargo flw new hello-workflow
$ cd hello-workflow
Running cargo flw new
will have a similar result to running (cargo new
), but it adds
a few Flawless specific configuration options to the project:
1. .cargo/config.toml
The default compilation target is set to wasm32-unknown-unknown
.
[build]
target = "wasm32-unknown-unknown"
2. Cargo.toml
When compiling to WebAssembly, the crate-type
needs to be set to cdylib
. Also, the
flawless
and log
crates are added as dependencies.
# ... truncated ...
[lib]
crate-type = ["cdylib"]
[dependencies]
flawless = "1.0.0-alpha.16"
log = "0.4"
3. src/lib.rs
Workflows in flawless are just regular Rust functions that are annotated with the
#[workflow("<name>")]
macro. You can have multiple of them inside one project.
Printing to standard output is not supported from a workflow, but you can use the log crate for logging. Flawless will set up a logging environment for each workflow automatically.
use flawless::workflow;
use log::info;
#[workflow("hello_workflow")]
fn hello_workflow() {
info!("👋 Hello from a workflow!");
}
Running the workflow
To run the workflow you can use the cargo flw run
command:
$ cargo flw run hello_workflow
This will build the project, upload it to the flawless server and trigger the
hello_workflow
workflow. The workflow just prints out "👋 Hello from a workflow!" to the
log. You can observe the output in the terminal window where you started flawless up
.
The durability part of flawless
To demonstrate the durability part of Flawless, let's open the src/lib.rs
file and
replace the existing code with:
use flawless::{exe::sleep, log, workflow};
use std::time::Duration;
#[workflow("hello_workflow")]
fn hello_workflow() {
for i in 0..30 {
log::info!("👋 Hello from a workflow! {i}");
sleep(Duration::from_secs(2));
}
}
You can again start the workflow with:
$ cargo flw run hello_workflow
This workflow runs for 1 minute and just prints a greeting message every 2 seconds.
To test the durability, you can abruptly stop the server with Ctrl+C
or using the
killall flawless
command. And next time you bring up the server again with flawless up
,
the execution should pick up exactly where it stopped.
This is a very important property of Flawless. It implicitly "remembers" the exact point in code where the execution was interrupted, but it does so by only saving the minimal amount of information to reconstruct the state. Every other feature that Flawless has is a result of this guarantee.
Workflow performing HTTP requests
Let's look now at a bit more complicated workflow that performs HTTP requests, fetches 10 dad jokes and logs them.
First we need to add another dependency to flawless, an HTTP client:
[dependencies]
flawless = "1.0.0-alpha.16"
flawless-http = "1.0.0-alpha.16"
log = "0.4"
Now let's update the src/lib.rs
file with the implementation:
use std::time::Duration;
use flawless::{exe::sleep, workflow};
use flawless_http::get;
#[workflow("dad_joke_api")]
fn dad_joke_api() {
for i in 1..11 {
let request = get("https://icanhazdadjoke.com/")
.set_header("Accept", "application/json");
let response = request.send().unwrap();
let response_txt = String::from_utf8(response.body()).unwrap();
log::info!("Dad Joke {i}: {}", response_txt.trim());
sleep(Duration::from_secs(1));
}
}
Notice that the name of the workflow also changed, now you can start it using:
$ cargo flw run dad_joke_api
You will see the fetched jokes being printed out in the server window.
Next steps
Flawless is still very early in development and new APIs are being added on a weekly basis. The best way to check what is available is by looking at the API reference.
Check also out workflow fundamentals, for examples on how to pass input values to workflows and how to get some output from them.