118 lines
3.5 KiB
Rust
118 lines
3.5 KiB
Rust
use async_trait::async_trait;
|
|
use futures::future::select;
|
|
use overwatch_derive::Services;
|
|
use overwatch_rs::overwatch::OverwatchRunner;
|
|
use overwatch_rs::services::handle::{ServiceHandle, ServiceStateHandle};
|
|
use overwatch_rs::services::relay::RelayMessage;
|
|
use overwatch_rs::services::state::{NoOperator, NoState};
|
|
use overwatch_rs::services::{ServiceCore, ServiceData, ServiceId};
|
|
use std::time::Duration;
|
|
use tokio::time::sleep;
|
|
|
|
pub struct PrintService {
|
|
state: ServiceStateHandle<Self>,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct PrintServiceMessage(String);
|
|
|
|
impl RelayMessage for PrintServiceMessage {}
|
|
|
|
impl ServiceData for PrintService {
|
|
const SERVICE_ID: ServiceId = "FooService";
|
|
type Settings = ();
|
|
type State = NoState<Self::Settings>;
|
|
type StateOperator = NoOperator<Self::State>;
|
|
type Message = PrintServiceMessage;
|
|
}
|
|
|
|
#[async_trait]
|
|
impl ServiceCore for PrintService {
|
|
fn init(state: ServiceStateHandle<Self>) -> Result<Self, overwatch_rs::DynError> {
|
|
Ok(Self { state })
|
|
}
|
|
|
|
async fn run(mut self) -> Result<(), overwatch_rs::DynError> {
|
|
use tokio::io::{self, AsyncWriteExt};
|
|
|
|
let Self {
|
|
state: ServiceStateHandle {
|
|
mut inbound_relay, ..
|
|
},
|
|
} = self;
|
|
|
|
let print = async move {
|
|
let mut stdout = io::stdout();
|
|
while let Some(message) = inbound_relay.recv().await {
|
|
match message.0.as_ref() {
|
|
"stop" => {
|
|
stdout
|
|
.write_all(b"Printing service stopping\n")
|
|
.await
|
|
.expect("stop Output wrote");
|
|
break;
|
|
}
|
|
m => {
|
|
stdout
|
|
.write_all(format!("{m}\n").as_bytes())
|
|
.await
|
|
.expect("Message output wrote");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
let idle = async move {
|
|
let mut stdout = io::stdout();
|
|
loop {
|
|
stdout
|
|
.write_all(b"Waiting for print process to finish...\n")
|
|
.await
|
|
.expect("Message output wrote");
|
|
sleep(Duration::from_millis(50)).await;
|
|
}
|
|
};
|
|
|
|
select(Box::pin(print), Box::pin(idle)).await;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Services)]
|
|
struct TestApp {
|
|
print_service: ServiceHandle<PrintService>,
|
|
}
|
|
|
|
#[test]
|
|
fn derive_print_service() {
|
|
let settings: TestAppServiceSettings = TestAppServiceSettings { print_service: () };
|
|
let overwatch = OverwatchRunner::<TestApp>::run(settings, None).unwrap();
|
|
let handle = overwatch.handle().clone();
|
|
let print_service_relay = handle.relay::<PrintService>();
|
|
|
|
overwatch.spawn(async move {
|
|
let print_service_relay = print_service_relay
|
|
.connect()
|
|
.await
|
|
.expect("A connection to the print service is established");
|
|
|
|
for _ in 0..3 {
|
|
print_service_relay
|
|
.send(PrintServiceMessage("Hey oh let's go!".to_string()))
|
|
.await
|
|
.expect("Message is sent");
|
|
}
|
|
sleep(Duration::from_millis(50)).await;
|
|
print_service_relay
|
|
.send(PrintServiceMessage("stop".to_string()))
|
|
.await
|
|
.expect("stop message to be sent");
|
|
});
|
|
|
|
overwatch.spawn(async move {
|
|
sleep(Duration::from_secs(1)).await;
|
|
handle.shutdown().await;
|
|
});
|
|
overwatch.wait_finished();
|
|
}
|