webhook through event system, extract data-generators adapter

webhook route now emits WebhookDataReceived event instead of directly
mutating DataProjection and broadcasting. event_handler applies data
and pushes incremental DataUpdate.

clock/static_text generators extracted to data-generators crate behind
DataSourcePort. chrono removed from bootstrap. polling adapters grouped
into Adapters struct.
This commit is contained in:
2026-06-19 12:33:42 +02:00
parent 437056cfc4
commit 455d5da901
9 changed files with 216 additions and 116 deletions

View File

@@ -0,0 +1,10 @@
[package]
name = "data-generators"
version = "0.1.0"
edition = "2024"
[dependencies]
domain.workspace = true
chrono = "0.4"
chrono-tz = "0.10"
thiserror.workspace = true

View File

@@ -0,0 +1,59 @@
use chrono::Utc;
use chrono_tz::Tz;
use domain::{DataSource, DataSourceConfig, DataSourcePort, Value};
use std::collections::BTreeMap;
#[derive(Default)]
pub struct ClockGenerator;
impl ClockGenerator {
pub fn new() -> Self {
Self
}
}
#[derive(Debug, thiserror::Error)]
pub enum GeneratorError {
#[error("wrong config type for generator")]
WrongConfig,
}
impl DataSourcePort for ClockGenerator {
type Error = GeneratorError;
async fn poll(&self, source: &DataSource) -> Result<Value, Self::Error> {
let (fmt, tz_name) = match &source.config {
DataSourceConfig::Clock { format, timezone } => (format.as_str(), timezone.as_str()),
_ => ("%H:%M:%S", "UTC"),
};
let tz: Tz = tz_name.parse().unwrap_or(chrono_tz::UTC);
let now = Utc::now().with_timezone(&tz);
let formatted = now.format(fmt).to_string();
let mut map = BTreeMap::new();
map.insert("time".into(), Value::String(formatted));
Ok(Value::Object(map))
}
}
#[derive(Default)]
pub struct StaticTextGenerator;
impl StaticTextGenerator {
pub fn new() -> Self {
Self
}
}
impl DataSourcePort for StaticTextGenerator {
type Error = GeneratorError;
async fn poll(&self, source: &DataSource) -> Result<Value, Self::Error> {
let text = match &source.config {
DataSourceConfig::StaticText { text } => text.clone(),
_ => String::new(),
};
let mut map = BTreeMap::new();
map.insert("text".into(), Value::String(text));
Ok(Value::Object(map))
}
}