rskit_config/watch/contract.rs
1use std::fmt;
2
3use rskit_errors::AppResult;
4use rskit_stream::BroadcastStream;
5use tokio_util::sync::CancellationToken;
6
7/// A typed configuration change emitted by a [`ConfigWatch`] source.
8///
9/// Carries only the affected key (never the value), so change notifications are safe to log.
10/// Consumers react by re-running the load pipeline and re-decoding.
11#[derive(Debug, Clone, PartialEq, Eq)]
12#[non_exhaustive]
13pub enum ConfigChange {
14 /// The value at `key` was created or replaced.
15 Set {
16 /// The affected configuration key.
17 key: String,
18 },
19 /// The value at `key` was removed.
20 Removed {
21 /// The affected configuration key.
22 key: String,
23 },
24 /// The backend changed wholesale; consumers should reload everything.
25 Reloaded,
26}
27
28/// A bounded stream of [`ConfigChange`] events.
29///
30/// The stream terminates when the originating [`CancellationToken`] fires or the source is dropped.
31/// It is the [`Broadcaster`](rskit_stream::Broadcaster) stream specialized to config change events.
32pub type ConfigChangeStream = BroadcastStream<ConfigChange>;
33
34/// Adapter contract for configuration backends that emit change notifications.
35///
36/// Implemented by backends that can signal updates (a watched file, a remote config service, an in-memory store).
37/// The returned stream is bounded and owned;
38/// cancellation is driven by the supplied [`CancellationToken`] per the rskit concurrency baseline (ownership + cancellation + shutdown).
39pub trait ConfigWatch: fmt::Debug + Send + Sync + 'static {
40 /// Subscribe to configuration changes until `cancel` is triggered.
41 ///
42 /// The returned stream yields [`ConfigChange`] events and completes once `cancel` fires
43 /// or the source is dropped.
44 ///
45 /// # Errors
46 ///
47 /// Returns a typed [`AppError`](rskit_errors::AppError) (cause preserved) if the backend cannot establish a watch.
48 fn watch(&self, cancel: CancellationToken) -> AppResult<ConfigChangeStream>;
49}