subgraph_mock/state/
mod.rs

1use notify::{Config as NotifyConfig, Event, EventKind, PollWatcher, RecursiveMode, Watcher};
2use std::{path::PathBuf, sync::Arc, time::Duration};
3use tokio::sync::RwLock;
4use tracing::error;
5
6mod config;
7mod schema;
8
9pub use config::Config;
10pub use config::default_port;
11pub use schema::FederatedSchema;
12
13use schema::update_schema;
14
15pub struct State {
16    pub config: Arc<RwLock<Config>>,
17    pub schema: Arc<RwLock<FederatedSchema>>,
18    /// Handle to the pollwatcher that updates the schema for this config, so that it only drops out of scope when this state does
19    _schema_watcher: PollWatcher,
20}
21
22impl State {
23    pub fn new(config: Config, schema_path: PathBuf) -> anyhow::Result<Self> {
24        let schema = FederatedSchema::parse(&schema_path)?;
25        let schema = Arc::new(RwLock::new(schema));
26
27        let lock = schema.clone();
28        // We have to use a PollWatcher because Docker on MacOS doesn't support filesystem events:
29        // https://docs.rs/notify/8.2.0/notify/index.html#docker-with-linux-on-macos-m1
30        let mut schema_watcher = PollWatcher::new(
31            move |res: Result<Event, _>| match res {
32                Ok(event) => {
33                    if let EventKind::Modify(_) = event.kind
34                        && let Some(path) = event.paths.first()
35                        && let Err(err) = update_schema(path, lock.clone())
36                    {
37                        error!("Failed to reload schema: {}", err);
38                    }
39                }
40                Err(errors) => {
41                    error!("Error watching schema file: {:?}", errors)
42                }
43            },
44            NotifyConfig::default()
45                .with_poll_interval(Duration::from_secs(1))
46                .with_compare_contents(true),
47        )?;
48        schema_watcher.watch(&schema_path, RecursiveMode::NonRecursive)?;
49
50        Ok(Self {
51            config: Arc::new(RwLock::new(config)),
52            schema,
53            _schema_watcher: schema_watcher,
54        })
55    }
56
57    pub fn default(schema_path: PathBuf) -> anyhow::Result<Self> {
58        Self::new(Config::default(), schema_path)
59    }
60}