use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
use crate::broker::host_identity;
use crate::broker::manifest::{
manifest_with_self_sha256, write_to_central, write_to_central_in_dir, ManifestError,
CACHE_MANIFEST_MEDIA_TYPE, SUPPORTED_MANIFEST_SCHEMA_VERSION,
};
use crate::broker::protocol::{
BrokerIsolation, CacheManifest, CacheRoot, CacheRootKind, ServiceDefinition,
};
use crate::broker::server::service_def_loader::{
service_definition_dir, validate_service_definition_for_service, write_service_definition,
ServiceDefinitionError,
};
const BROKER_ENVELOPE_VERSION: &str = "v1";
#[derive(Clone, Debug)]
pub struct ServiceDefinitionBuilder {
definition: ServiceDefinition,
}
impl ServiceDefinitionBuilder {
pub fn shared_broker(service_name: impl Into<String>, binary_path: impl Into<String>) -> Self {
Self {
definition: ServiceDefinition {
service_name: service_name.into(),
binary_path: binary_path.into(),
isolation: BrokerIsolation::SharedBroker as i32,
..Default::default()
},
}
}
pub fn explicit_instance(
service_name: impl Into<String>,
binary_path: impl Into<String>,
instance: impl Into<String>,
) -> Self {
Self {
definition: ServiceDefinition {
service_name: service_name.into(),
binary_path: binary_path.into(),
isolation: BrokerIsolation::ExplicitInstance as i32,
explicit_instance: instance.into(),
..Default::default()
},
}
}
pub fn min_version(mut self, version: impl Into<String>) -> Self {
self.definition.min_version = version.into();
self
}
pub fn allow_version(mut self, version: impl Into<String>) -> Self {
self.definition.version_allow_list.push(version.into());
self
}
pub fn per_version_binary_dir(mut self, dir: impl Into<String>) -> Self {
self.definition.per_version_binary_dir = dir.into();
self
}
pub fn label(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.definition.labels.insert(key.into(), value.into());
self
}
pub fn build(self) -> Result<ServiceDefinition, ServiceDefinitionError> {
validate_service_definition_for_service(&self.definition, &self.definition.service_name)?;
Ok(self.definition)
}
pub fn install(self) -> Result<PathBuf, ServiceDefinitionError> {
self.install_in(&service_definition_dir())
}
pub fn install_in(self, root: &Path) -> Result<PathBuf, ServiceDefinitionError> {
let definition = self.build()?;
write_service_definition(root, &definition)
}
}
#[derive(Clone, Debug)]
pub struct CacheManifestBuilder {
manifest: CacheManifest,
}
impl CacheManifestBuilder {
pub fn new(service_name: impl Into<String>, service_version: impl Into<String>) -> Self {
let now = now_unix_ms();
Self {
manifest: CacheManifest {
manifest_schema_version: SUPPORTED_MANIFEST_SCHEMA_VERSION,
media_type: CACHE_MANIFEST_MEDIA_TYPE.to_string(),
host: Some(host_identity::current()),
service_name: service_name.into(),
service_version: service_version.into(),
broker_envelope_version: BROKER_ENVELOPE_VERSION.to_string(),
created_at_unix_ms: now,
last_active_unix_ms: now,
..Default::default()
},
}
}
pub fn broker_instance(mut self, instance: impl Into<String>) -> Self {
self.manifest.broker_instance = instance.into();
self
}
pub fn bundle_id(mut self, bundle_id: impl Into<String>) -> Self {
self.manifest.bundle_id = bundle_id.into();
self
}
pub fn root(mut self, kind: CacheRootKind, path: impl Into<String>) -> Self {
self.manifest.roots.push(CacheRoot {
path: path.into(),
kind: kind as i32,
..Default::default()
});
self
}
pub fn build(self) -> Result<CacheManifest, ManifestError> {
manifest_with_self_sha256(&self.manifest)
}
pub fn publish(self) -> Result<PathBuf, ManifestError> {
let manifest = self.build()?;
write_to_central(&manifest.service_name, &manifest.service_version, &manifest)
}
pub fn publish_in(self, registry_dir: &Path) -> Result<PathBuf, ManifestError> {
let manifest = self.build()?;
write_to_central_in_dir(
registry_dir,
&manifest.service_name,
&manifest.service_version,
&manifest,
)
}
}
fn now_unix_ms() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_millis() as u64)
.unwrap_or(0)
}