Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions components/cron-scheduler/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Rust build artifacts
target/

# Wash build artifacts
build/

14 changes: 14 additions & 0 deletions components/cron-scheduler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "cron-scheduler"
edition = "2021"
version = "0.1.0"

[workspace]

[lib]
crate-type = ["cdylib"]

[dependencies]
wasmcloud-component = "0.2.0"
wit-bindgen = { version = "0.32" }
serde_json = { version = "1" }
69 changes: 69 additions & 0 deletions components/cron-scheduler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Here’s a simple README for your example in the same style as the **Dog Fetcher** one:

---

# Cron Scheduler Example

This is a simple Rust Wasm example that demonstrates how to build a cronjob-triggered component in wasmCloud.
When invoked by the `wasmcloud:cron/scheduler` interface, the component receives a JSON payload, logs it, extracts fields (`x1`, `x2`), and makes an outgoing HTTP request with those values as query parameters.

It shows how you can use:

* `wasi:http/outgoing-handler` to send HTTP requests
* `wasmcloud:cron/scheduler` to schedule invocations
* `wasi:logging` to log output

## Prerequisites

* `cargo` 1.75
* [`wash`](https://wasmcloud.com/docs/installation) 0.27.0
* `wasmtime` >=25.0.0 (if running with wasmtime)

## Building

```bash
wash build
```

## Running with wasmtime

You must have wasmtime >=25.0.0 for this to work. Make sure to follow the build step above first.

```bash
wasmtime serve -Scommon ./build/cron_scheduler_s.wasm
```

## Running with wasmCloud

Ensuring you've built your component with `wash build`, you can launch wasmCloud and deploy the full cron scheduling example with the following commands.

```shell
wash up -d
wash app deploy ./wadm.yaml
wash app get
```

Once deployed, the component will be triggered on the cron schedule you configure. Logs will show the JSON payload received and the HTTP request status.

## Example Payload

A sample JSON payload passed by the cron scheduler might look like:

```json
{
"x1": "foo",
"x2": "bar"
}
```

This will result in an outgoing request to:

```
http://localhost:3002/payload?foo=bar
```

## Adding Capabilities

To learn how to extend this example with additional capabilities, see the [Adding Capabilities](https://wasmcloud.com/docs/tour/adding-capabilities?lang=rust) section of the wasmCloud documentation.

---
91 changes: 91 additions & 0 deletions components/cron-scheduler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
wit_bindgen::generate!({ generate_all });

use crate::wasi::http::outgoing_handler;
use crate::wasi::http::types::*;
use serde_json::Value;
use wasmcloud_component::wasi::logging::logging::{log, Level};

use crate::exports::wasmcloud::cron::scheduler::Guest as CronDemoGuest;

#[derive(Debug)]
struct CronDemo {}

impl CronDemoGuest for CronDemo {
fn invoke(payload: Vec<u8>) -> Result<(), String> {
// Unmarshall the Byte payload into JSON
let json_result: Result<Value, _> = serde_json::from_slice(&payload);

match json_result {
Ok(json_data) => {
log(
Level::Info,
"cronjob-scheduler",
&format!("Received JSON payload: {}", json_data),
);

let x1 = json_data.get("x1").and_then(|v| v.as_str()).unwrap_or("default_x1");

let x2 = json_data.get("x2").and_then(|v| v.as_str()).unwrap_or("default_x2");

let req = outgoing_handler::OutgoingRequest::new(Fields::new());
req.set_scheme(Some(&Scheme::Http)).unwrap();
req.set_authority(Some("localhost:3002")).unwrap();
req.set_path_with_query(Some(format!("/payload?{}={}", x1, x2).as_ref()))
.unwrap();

match outgoing_handler::handle(req, None) {
Ok(resp) => {
resp.subscribe().block();

match resp.get() {
Some(Ok(Ok(response))) => {
log(
Level::Info,
"cronjob-scheduler",
format!(
"HTTP request completed with status {}",
response.status()
)
.as_str(),
);
}
Some(Ok(Err(code))) => {
log(
Level::Error,
"cronjob-scheduler",
format!("HTTP request failed with code {}", code).as_str(),
);
}
_ => {
log(
Level::Error,
"cronjob-scheduler",
"Failed to get HTTP response",
);
}
}
}
Err(e) => {
log(
Level::Error,
"cronjob-scheduler",
format!("Failed to send HTTP request: {:?}", e).as_str(),
);
}
}
}
Err(e) => {
log(
Level::Error,
"cronjob-scheduler",
&format!("Failed to parse payload as JSON: {}", e),
);
return Err(format!("JSON parsing error: {}", e));
}
}

Ok(())
}
}

export!(CronDemo);
37 changes: 37 additions & 0 deletions components/cron-scheduler/wadm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# wadm.yaml
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: cron-scheduler-demo
spec:
components:
# The Rust Wasm component
- name: cron-scheduler-component
type: component
properties:
image: file://./build/cron_scheduler.wasm
traits:
- type: spreadscaler
properties:
instances: 1

# Cron capability provider
- name: cron-provider
type: capability
properties:
image: file://./build/provider-cron-scheduler.par.gz
traits:
- type: spreadscaler
properties:
instances: 1
- type: link
properties:
target: cron-scheduler-component
namespace: wasmcloud
package: cron
interfaces: [scheduler]
target_config:
- name: cron-config
properties:
cluster_uri: nats://127.0.0.1:4222
cronjobs: job_1=0 * 1 * * ?:{"x1":"foo","x2":"bar"};
12 changes: 12 additions & 0 deletions components/cron-scheduler/wasmcloud.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file is automatically generated.
# It is not intended for manual editing.
version = 1

[[packages]]
name = "wasi:http"
registry = "wasi.dev"

[[packages.versions]]
requirement = "=0.2.2"
version = "0.2.2"
digest = "sha256:a1f129cdf1fde55ec2d4ae8d998c39a7e5cf7544a8bd84a831054ac0d2ac64dd"
8 changes: 8 additions & 0 deletions components/cron-scheduler/wasmcloud.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name = "cron-scheduler"
version = "0.1.0"
language = "rust"
type = "component"

[component]
wit_world = "hello"
wasm_target = "wasm32-wasip2"
39 changes: 39 additions & 0 deletions components/cron-scheduler/wit/deps.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[cli]
sha256 = "052c438d7606115bcfbe43094c55764c3396acfc8e4c69a6f54f7abcf8ef7c8c"
sha512 = "cce72d006e639cacabbd01137af99029591403a9bf6db8475e87d82cd6f256fa2118f9d15d5d88a34cacfaeb8d472f21f0914b20c83f6da1771f763cad4e1379"

[clocks]
sha256 = "c2da62619d1067646316e8592b583d77036d778e28b1154353e0825956b3d6aa"
sha512 = "4d409fc38b31646fc5de70160e81bd3fa67f9c99b4d24543b4fd40a922c7545739869521b8a997efb675d0816de8b001b6af7950e0cb0bc823d89b9f07b286c4"

[cron-example]
path = "../../../../../crates/provider-cron-scheduler/wit/deps/cron/"
sha256 = "f9a47021f2b9a7d0e3094be525e0542e9ff5d200310a65661bc2f41e734f0298"
sha512 = "ea5873a55505f4644901f887982efc28eacef63cf83347cfe3afc2b25d7324d4ce062fb5ba98a281257bfd29b03a5ed2caa6ee95afad928854b8bc9154fc29f1"

[filesystem]
sha256 = "69e220ec22593f097c7f486dd9e4f95576ef7056d3d531a86a277654872997ba"
sha512 = "457c027aebd1430e924564b3bb2477bc163083cb1029105c1432cbdc165cdf3cce4ac62dbb8e43e3dec09e24a6b2029204212e2f0e3919137cb207165368e157"

[http]
url = "https://github.com/WebAssembly/wasi-http/archive/v0.2.2.tar.gz"
sha256 = "982d44b46a4d0732091404f237eadd8adbb17d156c7afacbf36736570c408f3f"
sha512 = "c16db312a3a758ba760cf5503794722b4dd61aa0040fdce758b9f89c4c5672e6d0bafed7e199c5c885397621d8b73a5797313dcf554d0ebd41dae9087ef35598"
deps = ["cli", "clocks", "filesystem", "io", "random", "sockets"]

[io]
sha256 = "6d8dbfaaaa685167c1829616dc7265f5f3cb776845879555612d56544f6d9bfc"
sha512 = "52219562c4183503169cd2947b8164e1c96974500a5adf15bbf382c5992a10a626cc89c3b319204aeda6698ce59cbca2c42f98f7fde296aa77b9db4b41154dbe"

[logging]
url = "https://github.com/WebAssembly/wasi-logging/archive/main.tar.gz"
sha256 = "ad81d8b7f7a8ceb729cf551f1d24586f0de9560a43eea57a9bb031d2175804e1"
sha512 = "1687ad9a02ab3e689443e67d1a0605f58fc5dea828d2e4d2c7825c6002714fac9bd4289b1a68b61a37dcca6c3b421f4c8ed4b1e6cc29f6460e0913cf1bf11c04"

[random]
sha256 = "b4bb285b1c51aac2f8911f6b44ba1587108a2b24f910fe4774414dc286678b66"
sha512 = "bc2ffca0ae48f54977a763a70fcfcd5f4fca6b7c530916352f98c59627cc3f5899e47b6308bd9848b8c72e14db57e254757d580010a3d56e6888dafce3dcb679"

[sockets]
sha256 = "f254783796170fdeac6756496cc6169903a88adeda7a5895265414bc63ba4d66"
sha512 = "3f68e874beb0ac9729d1738546a430f2f8b369eb510d3cd6dfcfc41427acb52a82701d73584b8ab637b8c3908c5d4f7a7d4806032cc5d375643fad0ebf84e053"
3 changes: 3 additions & 0 deletions components/cron-scheduler/wit/deps.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cron-example = "../../../providers/provider-cron-scheduler/wit/cron"
logging = "https://github.com/WebAssembly/wasi-logging/archive/main.tar.gz"
http = "https://github.com/WebAssembly/wasi-http/archive/v0.2.2.tar.gz"
10 changes: 10 additions & 0 deletions components/cron-scheduler/wit/deps/cli/command.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package wasi:cli@0.2.2;

@since(version = 0.2.0)
world command {
@since(version = 0.2.0)
include imports;

@since(version = 0.2.0)
export run;
}
22 changes: 22 additions & 0 deletions components/cron-scheduler/wit/deps/cli/environment.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@since(version = 0.2.0)
interface environment {
/// Get the POSIX-style environment variables.
///
/// Each environment variable is provided as a pair of string variable names
/// and string value.
///
/// Morally, these are a value import, but until value imports are available
/// in the component model, this import function should return the same
/// values each time it is called.
@since(version = 0.2.0)
get-environment: func() -> list<tuple<string, string>>;

/// Get the POSIX-style arguments to the program.
@since(version = 0.2.0)
get-arguments: func() -> list<string>;

/// Return a path that programs should use as their initial current working
/// directory, interpreting `.` as shorthand for this.
@since(version = 0.2.0)
initial-cwd: func() -> option<string>;
}
17 changes: 17 additions & 0 deletions components/cron-scheduler/wit/deps/cli/exit.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@since(version = 0.2.0)
interface exit {
/// Exit the current instance and any linked instances.
@since(version = 0.2.0)
exit: func(status: result);

/// Exit the current instance and any linked instances, reporting the
/// specified status code to the host.
///
/// The meaning of the code depends on the context, with 0 usually meaning
/// "success", and other values indicating various types of failure.
///
/// This function does not return; the effect is analogous to a trap, but
/// without the connotation that something bad has happened.
@unstable(feature = cli-exit-with-code)
exit-with-code: func(status-code: u8);
}
36 changes: 36 additions & 0 deletions components/cron-scheduler/wit/deps/cli/imports.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package wasi:cli@0.2.2;

@since(version = 0.2.0)
world imports {
@since(version = 0.2.0)
include wasi:clocks/imports@0.2.2;
@since(version = 0.2.0)
include wasi:filesystem/imports@0.2.2;
@since(version = 0.2.0)
include wasi:sockets/imports@0.2.2;
@since(version = 0.2.0)
include wasi:random/imports@0.2.2;
@since(version = 0.2.0)
include wasi:io/imports@0.2.2;

@since(version = 0.2.0)
import environment;
@since(version = 0.2.0)
import exit;
@since(version = 0.2.0)
import stdin;
@since(version = 0.2.0)
import stdout;
@since(version = 0.2.0)
import stderr;
@since(version = 0.2.0)
import terminal-input;
@since(version = 0.2.0)
import terminal-output;
@since(version = 0.2.0)
import terminal-stdin;
@since(version = 0.2.0)
import terminal-stdout;
@since(version = 0.2.0)
import terminal-stderr;
}
6 changes: 6 additions & 0 deletions components/cron-scheduler/wit/deps/cli/run.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@since(version = 0.2.0)
interface run {
/// Run the program.
@since(version = 0.2.0)
run: func() -> result;
}
Loading