1use std::collections::HashMap;
2use std::sync::Arc;
3use url::Url;
4
5use crate::blobservice::BlobService;
6use crate::composition::{
7 Composition, DeserializeWithRegistry, REG, ServiceBuilder, with_registry,
8};
9use crate::directoryservice::DirectoryService;
10
11#[derive(serde::Deserialize, Default)]
12pub struct CompositionConfigs {
13 pub blobservices:
14 HashMap<String, DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn BlobService>>>>,
15 pub directoryservices: HashMap<
16 String,
17 DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>>,
18 >,
19}
20
21#[derive(clap::Parser, Clone)]
26#[group(id = "CastoreServiceUrls")]
27pub struct ServiceUrls {
28 #[arg(
29 long,
30 env,
31 default_value = "objectstore+file:///var/lib/snix-store/blobs.object_store"
32 )]
33 pub blob_service_addr: String,
34
35 #[arg(
36 long,
37 env,
38 default_value = "redb:///var/lib/snix-store/directories.redb"
39 )]
40 pub directory_service_addr: String,
41
42 #[cfg(feature = "xp-composition-cli")]
46 #[arg(long, env)]
47 experimental_store_composition: Option<String>,
48}
49
50#[derive(clap::Parser, Clone)]
55#[group(id = "CastoreServiceUrlsGrpc")]
56pub struct ServiceUrlsGrpc {
57 #[arg(long, env, default_value = "grpc+http://[::1]:8000")]
58 blob_service_addr: String,
59
60 #[arg(long, env, default_value = "grpc+http://[::1]:8000")]
61 directory_service_addr: String,
62
63 #[cfg(feature = "xp-composition-cli")]
64 #[arg(long, env)]
65 experimental_store_composition: Option<String>,
66}
67
68#[derive(clap::Parser, Clone)]
76#[group(id = "CastoreServiceUrlsMemory")]
77pub struct ServiceUrlsMemory {
78 #[arg(long, env, default_value = "memory://")]
79 blob_service_addr: String,
80
81 #[arg(long, env, default_value = "memory://")]
82 directory_service_addr: String,
83
84 #[cfg(feature = "xp-composition-cli")]
85 #[arg(long, env)]
86 experimental_store_composition: Option<String>,
87}
88
89impl From<ServiceUrlsGrpc> for ServiceUrls {
90 fn from(urls: ServiceUrlsGrpc) -> ServiceUrls {
91 ServiceUrls {
92 blob_service_addr: urls.blob_service_addr,
93 directory_service_addr: urls.directory_service_addr,
94 #[cfg(feature = "xp-composition-cli")]
95 experimental_store_composition: urls.experimental_store_composition,
96 }
97 }
98}
99
100impl From<ServiceUrlsMemory> for ServiceUrls {
101 fn from(urls: ServiceUrlsMemory) -> ServiceUrls {
102 ServiceUrls {
103 blob_service_addr: urls.blob_service_addr,
104 directory_service_addr: urls.directory_service_addr,
105 #[cfg(feature = "xp-composition-cli")]
106 experimental_store_composition: urls.experimental_store_composition,
107 }
108 }
109}
110
111pub async fn addrs_to_configs(
116 urls: impl Into<ServiceUrls>,
117) -> Result<CompositionConfigs, Box<dyn std::error::Error + Send + Sync>> {
118 let urls: ServiceUrls = urls.into();
119
120 #[cfg(feature = "xp-composition-cli")]
121 if let Some(conf_path) = urls.experimental_store_composition {
122 let conf_text = tokio::fs::read_to_string(conf_path).await?;
123 return Ok(with_registry(®, || toml::from_str(&conf_text))?);
124 }
125
126 let mut configs: CompositionConfigs = Default::default();
127
128 let blob_service_url = Url::parse(&urls.blob_service_addr)?;
129 let directory_service_url = Url::parse(&urls.directory_service_addr)?;
130 configs.blobservices.insert(
131 "root".into(),
132 with_registry(®, || blob_service_url.try_into())?,
133 );
134 configs.directoryservices.insert(
135 "root".into(),
136 with_registry(®, || directory_service_url.try_into())?,
137 );
138 Ok(configs)
139}
140
141pub async fn construct_services(
143 urls: impl Into<ServiceUrls>,
144) -> Result<
145 (Arc<dyn BlobService>, Arc<dyn DirectoryService>),
146 Box<dyn std::error::Error + Send + Sync>,
147> {
148 let configs = addrs_to_configs(urls).await?;
149 construct_services_from_configs(configs).await
150}
151
152pub async fn construct_services_from_configs(
154 configs: CompositionConfigs,
155) -> Result<
156 (Arc<dyn BlobService>, Arc<dyn DirectoryService>),
157 Box<dyn std::error::Error + Send + Sync>,
158> {
159 let mut comp = Composition::new(®);
160
161 comp.extend(configs.blobservices);
162 comp.extend(configs.directoryservices);
163
164 let blob_service: Arc<dyn BlobService> = comp.build("root").await?;
165 let directory_service: Arc<dyn DirectoryService> = comp.build("root").await?;
166
167 Ok((blob_service, directory_service))
168}