74 lines
2.7 KiB
Rust
74 lines
2.7 KiB
Rust
//! Clock service: publishes a `Wire` on every change of the displayed
|
|
//! value, and accepts `ClockKind` wires from modules that want it to switch
|
|
//! which kind it publishes.
|
|
//!
|
|
//! The ticker knows nothing about the app's `Message` type; it produces
|
|
//! protocol wires from `common` that core routes to subscribers.
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use chrono::{DateTime, Local, Timelike};
|
|
use iced::futures::{channel::mpsc, SinkExt};
|
|
use iced::Subscription;
|
|
|
|
use common::{ClockPayload, Endpoint, Inbox, Wire};
|
|
|
|
/// Route-key namespace owned by this service; keys are `"clock.<kind>"`.
|
|
pub const NAMESPACE: &str = "clock.";
|
|
|
|
/// Drives the clock, publishing only the kind modules last asked for.
|
|
#[derive(Default)]
|
|
pub struct ClockTicker {
|
|
last: DateTime<Local>,
|
|
// want: ClockKind,
|
|
}
|
|
|
|
impl ClockTicker {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
/// Subscription that reads inbound wires from `inbox` and publishes
|
|
/// changes to every module subscribed to this service's route key.
|
|
pub fn run(inbox: Inbox) -> Subscription<Wire> {
|
|
Subscription::run_with(inbox, |inbox| {
|
|
let key = inbox.key();
|
|
// We dont need to rx any msgs from modules
|
|
let mut _rx = inbox.take().expect("inbox receiver is taken once");
|
|
|
|
iced::stream::channel(0, move |mut sender: mpsc::Sender<Wire>| async move {
|
|
let mut clock = ClockTicker::new();
|
|
let mut interval = tokio::time::interval(std::time::Duration::from_secs(1));
|
|
tracing::info!(key, "clock service started");
|
|
loop {
|
|
tokio::select! {
|
|
_ = interval.tick() => {
|
|
if let Some(payload) = clock.tick() {
|
|
tracing::debug!(key, ?payload, "publishing clock");
|
|
let wire = Wire::topic(Endpoint::service(key), key, payload);
|
|
if sender.send(wire).await.is_err() {
|
|
tracing::warn!(key, "clock send failed; stopping service");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
/// Latest value for the wanted kind, or `None` if unchanged.
|
|
pub fn tick(&mut self) -> Option<ClockPayload> {
|
|
let value = chrono::Local::now();
|
|
let meow = self.last;
|
|
if meow.minute() != value.minute() {
|
|
return Some(ClockPayload::Mins(value.format("%H:%M:%S").to_string()));
|
|
}
|
|
if meow.second() != value.second() {
|
|
return Some(ClockPayload::Seconds(value.format("%H:%M:%S").to_string()));
|
|
}
|
|
None
|
|
}
|
|
}
|