1use std::time::Duration;
2
3use serde::Deserialize;
4use serde::Serialize;
5
6use hydra::Application;
7use hydra::CallError;
8use hydra::ChildSpec;
9use hydra::Dest;
10use hydra::ExitReason;
11use hydra::From;
12use hydra::GenServer;
13use hydra::GenServerOptions;
14use hydra::Pid;
15use hydra::Process;
16use hydra::SupervisionStrategy;
17use hydra::Supervisor;
18use hydra::SupervisorOptions;
19
20#[derive(Debug, Serialize, Deserialize)]
21enum MyMessage {
22 Hello(String),
23 HelloResponse(String),
24 Crash,
25}
26
27struct MyApplication;
28
29impl Application for MyApplication {
30 async fn start(&self) -> Result<Pid, ExitReason> {
31 let children = [
33 MyServer::new().child_spec().id("server1"),
34 MyServer::new().child_spec().id("server2"),
35 ];
36
37 Supervisor::with_children(children)
39 .strategy(SupervisionStrategy::OneForOne)
40 .start_link(SupervisorOptions::new())
41 .await
42 }
43}
44
45#[derive(Clone)]
46struct MyServer;
47
48impl MyServer {
49 pub fn new() -> Self {
51 Self
52 }
53
54 pub async fn hello<T: Into<Dest>>(server: T, string: &str) -> Result<String, CallError> {
56 use MyMessage::*;
57
58 match MyServer::call(server, Hello(string.to_owned()), None).await? {
59 HelloResponse(response) => Ok(response),
60 _ => unreachable!(),
61 }
62 }
63
64 pub fn child_spec(self) -> ChildSpec {
66 ChildSpec::new("MyServer")
67 .start(move || MyServer::start_link(MyServer, GenServerOptions::new()))
68 }
69}
70
71impl GenServer for MyServer {
72 type Message = MyMessage;
73
74 async fn init(&mut self) -> Result<(), ExitReason> {
75 let server = Process::current();
76
77 Process::spawn(async move {
78 let hello_world = MyServer::hello(server, "hello")
80 .await
81 .expect("Failed to call server!");
82
83 tracing::info!("Got: {:?}", hello_world);
84
85 Process::sleep(Duration::from_secs(1)).await;
87
88 MyServer::cast(server, MyMessage::Crash);
90 });
91
92 Ok(())
93 }
94
95 async fn handle_call(
96 &mut self,
97 message: Self::Message,
98 _from: From,
99 ) -> Result<Option<Self::Message>, ExitReason> {
100 use MyMessage::*;
101
102 match message {
103 Hello(string) => Ok(Some(HelloResponse(format!("{} world!", string)))),
104 _ => unreachable!(),
105 }
106 }
107
108 async fn handle_cast(&mut self, message: Self::Message) -> Result<(), ExitReason> {
109 use MyMessage::*;
110
111 match message {
112 Crash => {
113 panic!("Whoops! We crashed!");
114 }
115 _ => unreachable!(),
116 }
117 }
118}
119
120fn main() {
121 Application::run(MyApplication)
123}