1#![cfg_attr(docsrs, feature(doc_cfg))]
2pub mod backend;
6pub mod building;
8#[cfg(feature = "tokio")]
9pub mod logging;
10pub mod settings;
11pub use flams_math_archives::FlamsExtension;
12
13pub fn span_capture<R>(f: impl FnOnce() -> R) -> (String, R) {
14 use tracing_subscriber::{fmt, layer::SubscriberExt};
15 #[derive(Clone)]
16 struct Buffer(std::sync::Arc<std::sync::Mutex<Vec<u8>>>);
17 impl std::io::Write for &Buffer {
18 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
19 if let Ok(mut l) = self.0.lock() {
20 l.extend_from_slice(buf);
21 }
22 Ok(buf.len())
23 }
24 #[inline]
25 fn flush(&mut self) -> std::io::Result<()> {
26 Ok(())
27 }
28 }
29 impl<'a> fmt::MakeWriter<'a> for Buffer {
30 type Writer = &'a Self;
31 #[inline]
32 fn make_writer(&'a self) -> Self::Writer {
33 self
34 }
35 }
36 let buffer = Buffer(std::sync::Arc::new(std::sync::Mutex::new(Vec::<u8>::new())));
37 let bufcl = buffer.clone();
38 let sub = tracing_subscriber::registry().with(
39 fmt::layer()
40 .with_writer(bufcl)
41 .with_ansi(false)
42 .with_filter(tracing_subscriber::filter::LevelFilter::INFO),
43 );
44 let ret = tracing::subscriber::with_default(sub, f);
45 let s = buffer
46 .0
47 .lock()
48 .map(|mut l| String::from_utf8_lossy(&std::mem::take(&mut *l)).into_owned())
49 .unwrap_or_default();
50 (s, ret)
51}
52
53#[cfg(feature = "zip")]
54pub mod zip;
55
56use building::queue_manager::QueueManager;
57use flams_math_archives::{utils::AsyncEngine, LocalArchive};
58use settings::SettingsSpec;
59
60pub use inventory::iter;
61pub use inventory::submit as register_exension;
62use tracing_subscriber::Layer;
63
64#[cfg(feature = "tokio")]
65pub struct TokioEngine;
66#[cfg(feature = "tokio")]
67impl AsyncEngine for TokioEngine {
68 fn background(f: impl FnOnce() + Send + 'static) {
69 let span = tracing::Span::current();
70 tokio::task::spawn_blocking(move || span.in_scope(f));
71 }
72 async fn block_on<R: Send + Sync + 'static>(
73 f: impl FnOnce() -> R + Send + Sync + 'static,
74 ) -> R {
75 tokio::task::spawn_blocking(f).await.expect("this is a bug")
76 }
77 fn exec_after(delay: std::time::Duration, f: impl FnOnce() + Send + 'static) {
78 tokio::task::spawn(async move {
79 tokio::time::sleep(delay).await;
80 f();
81 });
82 }
83}
84
85pub fn initialize<A: AsyncEngine>(settings: SettingsSpec, rdf: bool) {
87 settings::Settings::initialize(settings);
88 let settings = settings::Settings::get();
89 #[cfg(feature = "rocksdb")]
90 if let Some(p) = &settings.rdf_database {
91 flams_math_archives::backend::set_global(p);
92 }
93 if settings.lsp {
94 use tracing::Level;
95 use tracing_subscriber::layer::SubscriberExt;
96 use tracing_subscriber::Layer;
97 #[cfg(feature = "tokio")]
98 let logger = logging::LogStore::new();
99 let debug = settings.debug;
100 let level = if debug { Level::TRACE } else { Level::INFO };
101
102 let l = tracing_subscriber::fmt::layer()
103 .with_ansi(false)
105 .with_target(true)
106 .with_writer(std::io::stderr)
107 .with_filter(tracing::level_filters::LevelFilter::from(Level::INFO)); #[cfg(feature = "tokio")]
109 let sub = tracing_subscriber::registry()
110 .with(logger.with_filter(tracing::level_filters::LevelFilter::from(level)))
111 .with(l);
112 #[cfg(not(feature = "tokio"))]
113 let sub = tracing_subscriber::registry().with(l);
114 tracing::subscriber::set_global_default(sub)
115 .expect("Failed to set global default logging subscriber");
116 } else {
117 #[cfg(feature = "tokio")]
118 logging::LogStore::initialize();
119 }
120 tracing::info_span!(target:"initializing",parent:None,"initializing").in_scope(move || {
121 #[cfg(feature = "gitlab")]
122 {
123 if let Some(url) = &settings.gitlab_url {
124 let cfg = flams_git::gl::GitlabConfig::new(
125 url.clone(),
126 settings.gitlab_token.as_ref().map(ToString::to_string),
127 settings.gitlab_app_id.as_ref().map(ToString::to_string),
128 settings.gitlab_app_secret.as_ref().map(ToString::to_string),
129 );
130 flams_git::gl::GLInstance::global().clone().load(cfg);
131 }
132 }
133 backend::initialize::<A>(rdf);
134 QueueManager::initialize(settings.num_threads);
135 for e in inventory::iter::<FlamsExtension>() {
136 A::background(|| {
137 tracing::info_span!("Initializing", extension = e.name).in_scope(|| (e.on_start)());
138 });
139 }
140 });
141}
142
143#[cfg(feature = "gitlab")]
144pub trait LocalArchiveExt {
145 fn is_managed(&self) -> Option<&flams_git::GitUrl>;
146}
147
148#[cfg(feature = "gitlab")]
149impl LocalArchiveExt for LocalArchive {
150 fn is_managed(&self) -> Option<&flams_git::GitUrl> {
151 let gl = crate::settings::Settings::get().gitlab_url.as_ref()?;
152 self.git_url(gl)
153 }
154}