Skip to main content

heartbeat_daemon/
heartbeat_daemon.rs

1//! A daemon plugin: every thirty seconds it publishes a heartbeat as a live
2//! message, and it answers its own `heartbeat.ping` events with a pong.
3//! Everything stays in the plugin's own namespace, so it needs no grant.
4//!
5//! Manifest:
6//!
7//! ```json
8//! {
9//!   "apiVersion": 2, "kind": "daemon", "id": "heartbeat", "version": "0.1.0",
10//!   "module": "heartbeat_daemon.wasm",
11//!   "grants": {}
12//! }
13//! ```
14#![no_std]
15
16use core::cell::Cell;
17
18use standard_plugin::daemon::{Context, DaemonPlugin};
19use standard_plugin::prelude::{Event, Target};
20
21#[standard_plugin::daemon]
22struct Heartbeat {
23    beats: Cell<u64>,
24}
25
26impl DaemonPlugin for Heartbeat {
27    fn activate(_cx: &Context) -> Self {
28        Self {
29            beats: Cell::new(0),
30        }
31    }
32
33    async fn run(&self, cx: Context) {
34        let _ = cx.events().on("heartbeat.ping");
35        // Answer pings beside the heartbeat loop.
36        let events = cx.clone();
37        cx.spawn(async move {
38            loop {
39                if let Event::Plugin { name, .. } = events.next_event().await
40                    && name == "heartbeat.ping"
41                {
42                    let _ = events.events().emit("heartbeat.pong", &(), Target::All);
43                }
44            }
45        });
46        loop {
47            self.beats.set(self.beats.get() + 1);
48            let _ = cx.live().publish("heartbeat.beat", &self.beats.get());
49            cx.sleep(30_000).await;
50        }
51    }
52}