use std::collections::BTreeMap;
use super::ServerError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BootstrapContractRef {
pub id: String,
pub digest: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BootstrapBinding {
pub contract_id: String,
pub digest: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ServiceResourceBindings {
pub kv: BTreeMap<String, KvResourceBinding>,
pub store: BTreeMap<String, StoreResourceBinding>,
pub jobs: Option<JobsResourceBinding>,
pub event_consumers: BTreeMap<String, EventConsumerResourceBinding>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EventConsumerResourceBinding {
pub stream: String,
pub consumer_name: String,
pub filter_subjects: Vec<String>,
pub replay: EventConsumerReplay,
pub ordering: EventConsumerOrdering,
pub concurrency: i64,
pub ack_wait_ms: i64,
pub max_deliver: i64,
pub backoff_ms: Vec<i64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EventConsumerReplay {
New,
All,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EventConsumerOrdering {
Strict,
Unknown,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KvResourceBinding {
pub bucket: String,
pub history: i64,
pub max_value_bytes: Option<i64>,
pub ttl_ms: i64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StoreResourceBinding {
pub name: String,
pub max_object_bytes: Option<i64>,
pub max_total_bytes: Option<i64>,
pub ttl_ms: i64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JobsResourceBinding {
pub namespace: String,
pub work_stream: Option<String>,
pub queues: BTreeMap<String, JobsQueueResourceBinding>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JobsQueueResourceBinding {
pub queue_type: String,
pub publish_prefix: String,
pub work_subject: String,
pub consumer_name: String,
pub payload: JobsSchemaRef,
pub result: Option<JobsSchemaRef>,
pub max_deliver: i64,
pub backoff_ms: Vec<i64>,
pub ack_wait_ms: i64,
pub default_deadline_ms: Option<i64>,
pub progress: bool,
pub logs: bool,
pub dlq: bool,
pub concurrency: i64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JobsSchemaRef {
pub schema: String,
}
pub fn validate_bootstrap_contract_state(
service_name: &str,
expected: &BootstrapContractRef,
catalog_contracts: &[BootstrapContractRef],
binding: Option<&BootstrapBinding>,
) -> Result<BootstrapBinding, ServerError> {
let is_active = catalog_contracts
.iter()
.any(|contract| contract.id == expected.id && contract.digest == expected.digest);
if !is_active {
return Err(ServerError::BootstrapInactiveContract {
service_name: service_name.to_string(),
contract_id: expected.id.clone(),
contract_digest: expected.digest.clone(),
});
}
let binding = binding.ok_or_else(|| ServerError::BootstrapMissingBinding {
service_name: service_name.to_string(),
contract_id: expected.id.clone(),
contract_digest: expected.digest.clone(),
})?;
if binding.contract_id != expected.id || binding.digest != expected.digest {
return Err(ServerError::BootstrapBindingMismatch {
service_name: service_name.to_string(),
expected_contract_id: expected.id.clone(),
expected_contract_digest: expected.digest.clone(),
actual_contract_id: binding.contract_id.clone(),
actual_contract_digest: binding.digest.clone(),
});
}
Ok(binding.clone())
}