1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
pub(crate) mod config;
mod graphql;
use config::*;
mod server;
mod stdin;
mod watcher;
use watcher::*;
mod database;
use database::*;
use log::error;
use snafu::{ResultExt, Snafu};
use std::{path::Path, sync::Arc};
use tokio::sync::Mutex;
pub type ProgramResult<T, E = ProgramError> = std::result::Result<T, E>;
#[derive(Debug, Snafu)]
pub enum ProgramError {
#[snafu(display("Could not load database: {}", source))]
LoadDatabase { source: DatabaseError },
#[snafu(display("Could not start file watcher: {}", source))]
FileWatcher { source: notify::Error },
}
pub struct Program {
database: ShareableDatabase,
watcher: Watcher,
}
impl Program {
pub async fn run(config: Config) -> ProgramResult<()> {
let database: ShareableDatabase = Arc::new(Mutex::new(
Database::load(&config).await.context(LoadDatabase {})?,
));
let watcher = Watcher::initialize(Arc::clone(&database), &config)
.await
.context(FileWatcher {})?;
let program = Self { database, watcher };
match config.mode {
Mode::Stdin => stdin::run(program, config).await,
Mode::Http => server::run(program, config).await,
}
Ok(())
}
pub async fn load_and_watch_graphql_page(
&self,
path: impl AsRef<Path>,
reload: bool,
) -> Option<graphql::elements::Page> {
let mut database = self.database.lock().await;
if reload {
if let Err(x) = database.load_file(&path).await {
error!("{}", x);
} else if let Err(x) = self.watcher.watch_standalone(&path).await {
error!("{}", x);
}
}
database.graphql_page(path)
}
pub async fn graphql_pages(&self) -> Vec<graphql::elements::Page> {
self.database.lock().await.graphql_pages()
}
pub async fn wiki_by_index(&self, index: usize) -> Option<Wiki> {
self.database.lock().await.wiki_by_index(index).cloned()
}
pub async fn wiki_by_name(&self, name: &str) -> Option<Wiki> {
self.database.lock().await.wiki_by_name(name).cloned()
}
}