use crate::ClientError;
use crate::ClientResult;
use cheetah_string::CheetahString;
use rocketmq_protocol::protocol::remoting_command_defaults::RemotingCommandFactory;
use super::client_config::ClientConfig;
use crate::nameserver_discovery::NameServerDiscoveryConfig;
#[derive(Clone)]
pub struct ClientOptions {
client: ClientConfig,
nameserver_discovery: Option<NameServerDiscoveryConfig>,
remoting_command_factory: Option<RemotingCommandFactory>,
}
impl ClientOptions {
#[must_use]
pub fn legacy(client: ClientConfig) -> Self {
Self {
client,
nameserver_discovery: None,
remoting_command_factory: None,
}
}
#[must_use]
pub fn with_nameserver_discovery(mut self, discovery: NameServerDiscoveryConfig) -> Self {
self.nameserver_discovery = Some(discovery);
self
}
#[must_use]
pub fn with_remoting_command_factory(mut self, factory: RemotingCommandFactory) -> Self {
self.remoting_command_factory = Some(factory);
self
}
#[must_use]
pub fn client_config(&self) -> &ClientConfig {
&self.client
}
#[must_use]
pub fn nameserver_discovery(&self) -> Option<&NameServerDiscoveryConfig> {
self.nameserver_discovery.as_ref()
}
#[must_use]
pub fn remoting_command_factory(&self) -> Option<RemotingCommandFactory> {
self.remoting_command_factory
}
pub(crate) fn from_parts(client: ClientConfig, nameserver_discovery: Option<NameServerDiscoveryConfig>) -> Self {
Self {
client,
nameserver_discovery,
remoting_command_factory: None,
}
}
pub(crate) fn into_normalized_parts(
mut self,
) -> ClientResult<(
ClientConfig,
Option<NameServerDiscoveryConfig>,
Option<RemotingCommandFactory>,
)> {
let remoting_command_factory = self.remoting_command_factory;
let Some(discovery) = self.nameserver_discovery else {
self.client.normalize_namesrv_addr()?;
return Ok((self.client, None, remoting_command_factory));
};
if let Some(legacy) = self.client.namesrv_addr.as_ref() {
return Err(ClientError::config_invalid(
"nameserver_discovery",
discovery.fingerprint(),
format!("typed NameServer discovery cannot be combined with legacy namesrv_addr={legacy}"),
));
}
discovery.validate()?;
if let Some(canonical) = discovery.static_canonical() {
self.client.namesrv_addr = Some(CheetahString::from_string(canonical));
}
Ok((self.client, Some(discovery), remoting_command_factory))
}
}
impl Default for ClientOptions {
fn default() -> Self {
Self::legacy(ClientConfig::default())
}
}
impl From<ClientConfig> for ClientOptions {
fn from(value: ClientConfig) -> Self {
Self::legacy(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::nameserver_discovery::NameServerSource;
#[test]
fn legacy_options_preserve_existing_configuration() {
let options = ClientOptions::legacy(ClientConfig::default());
assert!(options.nameserver_discovery().is_none());
}
#[test]
fn typed_discovery_conflicts_with_legacy_address() {
let client = ClientConfig {
namesrv_addr: Some(CheetahString::from_static_str("ns-a:9876")),
..Default::default()
};
let discovery = NameServerDiscoveryConfig::new(NameServerSource::dns("namesrv.default.svc", 9876).unwrap());
assert!(ClientOptions::legacy(client)
.with_nameserver_discovery(discovery)
.into_normalized_parts()
.is_err());
}
}