-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #613 from swimos/docs_devguide_2.2
Example code for dev guide 2.2
- Loading branch information
Showing
7 changed files
with
183 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,7 @@ | |
!/demos/**/Cargo.lock | ||
|
||
**/.DS_Store | ||
*.iml | ||
*.iml | ||
|
||
# Code coverage files | ||
*.profraw |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "example_client_2_2" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
tokio = { workspace = true, features = ["full"] } | ||
swimos_client = { path = "../../../../client/swimos_client" } | ||
swimos_form = { path = "../../../../api/swimos_form" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use swimos_client::{BasicValueDownlinkLifecycle, DownlinkConfig, RemotePath, SwimClientBuilder}; | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
// Build a Swim Client using the default configuration. | ||
// The `build` method returns a `SwimClient` instance and its internal | ||
// runtime future that is spawned below. | ||
let (client, task) = SwimClientBuilder::default().build().await; | ||
let _client_task = tokio::spawn(task); | ||
let handle = client.handle(); | ||
|
||
// Build a path the downlink. | ||
let state_path = RemotePath::new( | ||
// The host address | ||
"ws://0.0.0.0:8080", | ||
// You can provide any agent URI that matches the pattern | ||
// "/example/:id" | ||
"/example/1", | ||
// This is the URI of the ValueLane<i32> in our ExampleAgent | ||
"state", | ||
); | ||
|
||
let lifecycle = BasicValueDownlinkLifecycle::<usize>::default() | ||
// Register an event handler that is invoked when the downlink connects to the agent. | ||
.on_linked_blocking(|| println!("Downlink linked")) | ||
// Register an event handler that is invoked when the downlink synchronises its state. | ||
// with the agent. | ||
.on_synced_blocking(|value| println!("Downlink synced with: {value:?}")) | ||
// Register an event handler that is invoked when the downlink receives an event. | ||
.on_event_blocking(|value| println!("Downlink event: {value:?}")); | ||
|
||
// Build our downlink. | ||
// | ||
// This operation may fail if there is a connection issue. | ||
let state_downlink = handle | ||
.value_downlink::<i32>(state_path) | ||
.lifecycle(lifecycle) | ||
.downlink_config(DownlinkConfig::default()) | ||
.open() | ||
.await | ||
.expect("Failed to open downlink"); | ||
|
||
for i in 0..10 { | ||
// Update the lane's state. | ||
state_downlink | ||
.set(i) | ||
.await | ||
.expect("Failed to set downlink state"); | ||
} | ||
|
||
tokio::signal::ctrl_c() | ||
.await | ||
.expect("Failed to listen for ctrl-c."); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "example_server_2_2" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
tokio = { workspace = true, features = ["full"] } | ||
swimos = { path = "../../../../swimos", features = ["server"] } | ||
swimos_form = { path = "../../../../api/swimos_form" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use swimos::{ | ||
agent::{ | ||
agent_lifecycle::HandlerContext, agent_model::AgentModel, event_handler::EventHandler, | ||
lanes::ValueLane, lifecycle, projections, AgentLaneModel, | ||
}, | ||
route::RoutePattern, | ||
server::{Server, ServerBuilder, ServerHandle}, | ||
}; | ||
|
||
use std::{error::Error, time::Duration}; | ||
|
||
#[derive(AgentLaneModel)] | ||
#[projections] | ||
pub struct ExampleAgent { | ||
state: ValueLane<i32>, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct ExampleLifecycle; | ||
|
||
#[lifecycle(ExampleAgent)] | ||
impl ExampleLifecycle { | ||
// Handler invoked when the agent starts. | ||
#[on_start] | ||
pub fn on_start( | ||
&self, | ||
context: HandlerContext<ExampleAgent>, | ||
) -> impl EventHandler<ExampleAgent> { | ||
context.effect(|| println!("Starting agent.")) | ||
} | ||
|
||
// Handler invoked when the agent is about to stop. | ||
#[on_stop] | ||
pub fn on_stop( | ||
&self, | ||
context: HandlerContext<ExampleAgent>, | ||
) -> impl EventHandler<ExampleAgent> { | ||
context.effect(|| println!("Stopping agent.")) | ||
} | ||
|
||
// Handler invoked after the state of 'lane' has changed. | ||
#[on_event(state)] | ||
pub fn on_event( | ||
&self, | ||
context: HandlerContext<ExampleAgent>, | ||
value: &i32, | ||
) -> impl EventHandler<ExampleAgent> { | ||
let n = *value; | ||
// EventHandler::effect accepts a FnOnce() | ||
// which runs a side effect. | ||
context.effect(move || { | ||
println!("Setting value to: {}", n); | ||
}) | ||
} | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { | ||
// Create a dynamic route for our agents. | ||
let route = RoutePattern::parse_str("/example/:id")?; | ||
// Create an agent model which contains the factory for creating the agent as well | ||
// as the lifecycle which will be run. | ||
let agent = AgentModel::new(ExampleAgent::default, ExampleLifecycle.into_lifecycle()); | ||
|
||
// Create a server builder. | ||
let server = ServerBuilder::with_plane_name("Plane") | ||
// Bind to port 8080 | ||
.set_bind_addr("127.0.0.1:8080".parse().unwrap()) | ||
// For this guide, ensure agents timeout fairly quickly. | ||
// An agent will timeout after they have received no new updates | ||
// for this configured period of time. | ||
.update_config(|config| { | ||
config.agent_runtime.inactive_timeout = Duration::from_secs(20); | ||
}) | ||
// Register the agent against the route. | ||
.add_route(route, agent) | ||
.build() | ||
// Building the server may fail if many routes are registered and some | ||
// are ambiguous. | ||
.await?; | ||
|
||
// Run the server. A tuple of the server's runtime | ||
// future and a handle to the runtime is returned. | ||
let (task, handle) = server.run(); | ||
// Watch for ctrl+c signals | ||
let shutdown = manage_handle(handle); | ||
|
||
// Join on the server and ctrl+c futures. | ||
let (_, result) = tokio::join!(shutdown, task); | ||
|
||
result?; | ||
println!("Server stopped successfully."); | ||
Ok(()) | ||
} | ||
|
||
// Utility function for awaiting a stop signal in the terminal. | ||
async fn manage_handle(mut handle: ServerHandle) { | ||
tokio::signal::ctrl_c() | ||
.await | ||
.expect("Failed to register interrupt handler."); | ||
|
||
println!("Stopping server."); | ||
handle.stop(); | ||
} |