Skip to main content

running_process/broker/server/
instance.rs

1//! Broker instance routing for service definitions.
2
3use crate::broker::lifecycle::names::{
4    explicit_instance_pipe, private_broker_pipe, shared_broker_pipe, validate_service_name,
5    PipePath, PipePathError,
6};
7use crate::broker::protocol::{BrokerIsolation, ServiceDefinition};
8
9/// Stable key for one broker trust-domain instance.
10#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11pub enum BrokerInstanceKey {
12    /// Per-user shared broker.
13    Shared,
14    /// Per-service private broker.
15    Private {
16        /// Service isolated into its own broker.
17        service_name: String,
18    },
19    /// Explicit named broker instance.
20    Explicit {
21        /// Explicit trust-domain name.
22        name: String,
23    },
24}
25
26impl BrokerInstanceKey {
27    /// Resolve a service definition into its broker instance key.
28    pub fn from_service_definition(
29        definition: &ServiceDefinition,
30    ) -> Result<Self, BrokerInstanceError> {
31        validate_service_name(&definition.service_name)?;
32        match BrokerIsolation::try_from(definition.isolation) {
33            Ok(BrokerIsolation::PrivateBroker) => Ok(Self::Private {
34                service_name: definition.service_name.clone(),
35            }),
36            Ok(BrokerIsolation::SharedBroker) => Ok(Self::Shared),
37            Ok(BrokerIsolation::ExplicitInstance) => {
38                if definition.explicit_instance.is_empty() {
39                    return Err(BrokerInstanceError::InvalidIsolation {
40                        reason: "EXPLICIT_INSTANCE requires explicit_instance",
41                    });
42                }
43                validate_service_name(&definition.explicit_instance)?;
44                Ok(Self::Explicit {
45                    name: definition.explicit_instance.clone(),
46                })
47            }
48            Err(_) => Err(BrokerInstanceError::InvalidIsolation {
49                reason: "unknown BrokerIsolation value",
50            }),
51        }
52    }
53
54    /// Stable manifest/debug identifier for this instance.
55    pub fn id(&self) -> String {
56        match self {
57            Self::Shared => "shared".into(),
58            Self::Private { service_name } => format!("private:{service_name}"),
59            Self::Explicit { name } => format!("explicit:{name}"),
60        }
61    }
62
63    /// Compute the broker pipe/socket for this instance and user.
64    pub fn pipe_path(&self, user_sid_hash: &str) -> Result<PipePath, BrokerInstanceError> {
65        match self {
66            Self::Shared => shared_broker_pipe(user_sid_hash),
67            Self::Private { service_name } => private_broker_pipe(user_sid_hash, service_name),
68            Self::Explicit { name } => explicit_instance_pipe(user_sid_hash, name),
69        }
70        .map_err(BrokerInstanceError::PipePath)
71    }
72}
73
74/// Errors returned while deriving broker instance identity.
75#[derive(Debug, thiserror::Error)]
76pub enum BrokerInstanceError {
77    /// Pipe-name validation failed.
78    #[error(transparent)]
79    PipePath(#[from] PipePathError),
80    /// The service definition used an inconsistent isolation shape.
81    #[error("broker instance isolation is invalid: {reason}")]
82    InvalidIsolation {
83        /// Why the isolation shape was invalid.
84        reason: &'static str,
85    },
86}