Skip to content

Commit

Permalink
Implement ping pong example.
Browse files Browse the repository at this point in the history
  • Loading branch information
AlejandroCabeza committed Dec 20, 2024
1 parent 4160cdd commit 79a22e9
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ resolver = "2"
members = [
"overwatch-rs",
"overwatch-derive",
"examples/ping_pong",
]

[profile.release-opt]
Expand Down
10 changes: 10 additions & 0 deletions examples/ping_pong/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "ping_pong"
version = "0.1.0"
edition = "2021"

[dependencies]
overwatch-rs = { path = "../../overwatch-rs" }
overwatch-derive = { path = "../../overwatch-derive" }
async-trait = "0.1.83"
tokio = { version = "1", features = ["macros"] }
17 changes: 17 additions & 0 deletions examples/ping_pong/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# PingPong
This example project demonstrates how to set up a basic Overwatch application in Rust.

### Behaviour
This project demonstrates a simple communication pattern between two services.
1. Every second, the `Ping` service sends a message to the `Pong` service.
2. The `Pong` service receives the message and prints it to the console. Afterwards, it sends a message back to the `Ping` service.
3. The `Ping` service receives the message and prints it to the console.

### Features
- **Services**: Shows how to define and register services within an Overwatch application.
- **Message Passing**: Demonstrates communication between services using the relay.

### About
This project serves as a barebones template to get started with the Overwatch library.
It provides the foundational structure for creating more complex applications.

26 changes: 26 additions & 0 deletions examples/ping_pong/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Crate
use overwatch_derive::Services;
use overwatch_rs::overwatch::OverwatchRunner;
use overwatch_rs::services::handle::ServiceHandle;
// Internal
use crate::service_ping::PingService;
use crate::service_pong::PongService;

mod service_ping;
mod service_pong;
mod messages;

#[derive(Services)]
struct PingPong {
ping: ServiceHandle<PingService>,
pong: ServiceHandle<PongService>,
}

fn main() {
let ping_pong_settings = PingPongServiceSettings {
ping: (),
pong: (),
};
let ping_pong = OverwatchRunner::<PingPong>::run(ping_pong_settings, None).expect("OverwatchRunner failed");
ping_pong.wait_finished();
}
15 changes: 15 additions & 0 deletions examples/ping_pong/src/messages.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use overwatch_rs::services::relay::RelayMessage;

#[derive(Debug)]
pub enum PingMessage {
Pong
}

impl RelayMessage for PingMessage {}

#[derive(Debug)]
pub enum PongMessage {
Ping
}

impl RelayMessage for PongMessage {}
68 changes: 68 additions & 0 deletions examples/ping_pong/src/service_ping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Crates
use std::time::Duration;
use tokio::time::sleep;
use overwatch_rs::DynError;
use overwatch_rs::services::{ServiceCore, ServiceData, ServiceId};
use overwatch_rs::services::handle::ServiceStateHandle;
use overwatch_rs::services::state::{NoOperator, NoState};
// Internal
use crate::messages::{PingMessage, PongMessage};
use crate::service_pong::PongService;

pub struct PingService {
service_state_handle: ServiceStateHandle<Self>
}

impl ServiceData for PingService {
const SERVICE_ID: ServiceId = "ping";
type Settings = ();
type State = NoState<Self::Settings>;
type StateOperator = NoOperator<Self::State>;
type Message = PingMessage;
}

#[async_trait::async_trait]
impl ServiceCore for PingService {
fn init(service_state_handle: ServiceStateHandle<Self>) -> Result<Self, DynError> {
Ok(Self {
service_state_handle
})
}

async fn run(self) -> Result<(), DynError> {
let Self {
service_state_handle
} = self;

let mut inbound_relay = service_state_handle.inbound_relay;
let pong_outbound_relay = service_state_handle.overwatch_handle.relay::<PongService>().connect().await?;

let mut pong_count = 0;

loop {
tokio::select! {
_ = sleep(Duration::from_secs(1)) => {
println!("Sending Ping");
pong_outbound_relay.send(PongMessage::Ping).await.unwrap();
}
Some(message) = inbound_relay.recv() => {
match message {
PingMessage::Pong => {
println!("Received Pong");
pong_count += 1;
}
}
}
true = async {
pong_count >= 5
} => {
println!("Received {} Pongs. Exiting...", pong_count);
break;
}
}
}

service_state_handle.overwatch_handle.shutdown().await;
Ok(())
}
}
47 changes: 47 additions & 0 deletions examples/ping_pong/src/service_pong.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Crates
use overwatch_rs::DynError;
use overwatch_rs::services::{ServiceCore, ServiceData, ServiceId};
use overwatch_rs::services::handle::ServiceStateHandle;
use overwatch_rs::services::state::{NoOperator, NoState};
use crate::messages::{PingMessage, PongMessage};
use crate::service_ping::PingService;

pub struct PongService {
service_state_handle: ServiceStateHandle<Self>
}

impl ServiceData for PongService {
const SERVICE_ID: ServiceId = "";
type Settings = ();
type State = NoState<Self::Settings>;
type StateOperator = NoOperator<Self::State>;
type Message = PongMessage;
}

#[async_trait::async_trait]
impl ServiceCore for PongService {
fn init(service_state_handle: ServiceStateHandle<Self>) -> Result<Self, DynError> {
Ok(Self {
service_state_handle
})
}

async fn run(self) -> Result<(), DynError> {
let Self {
service_state_handle
} = self;

let mut inbound_relay = service_state_handle.inbound_relay;
let ping_outbound_relay = service_state_handle.overwatch_handle.relay::<PingService>().connect().await?;

while let Some(message) = inbound_relay.recv().await {
match message {
PongMessage::Ping => {
println!("Received Ping. Sending Pong.");
ping_outbound_relay.send(PingMessage::Pong).await.unwrap();
}
}
}
Ok(())
}
}

0 comments on commit 79a22e9

Please sign in to comment.