use std::time::Duration;
use memberlist_proto::Label;
use super::proto::{DelegateVersion, ProtocolVersion};
#[cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3"
))]
use super::proto::ChecksumAlgorithm;
#[cfg(any(
feature = "zstd",
feature = "snappy",
feature = "brotli",
feature = "lz4",
))]
use super::proto::CompressAlgorithm;
#[cfg(feature = "encryption")]
use super::proto::{EncryptionAlgorithm, SecretKey, SecretKeys};
#[cfg(feature = "metrics")]
pub use super::proto::MetricLabels;
#[viewit::viewit(getters(vis_all = "pub"), setters(vis_all = "pub", prefix = "with"))]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Options {
#[viewit(
getter(const, style = "ref", attrs(doc = "Get the label of the node."),),
setter(attrs(doc = "Set the label of the node. (Builder pattern)"),)
)]
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Label::is_empty")
)]
label: Label,
#[viewit(
getter(
const,
attrs(
doc = "Get if the check that inbound packets and gossip streams need to be label prefixed."
),
),
setter(attrs(
doc = "Set if the check that inbound packets and gossip streams need to be label prefixed. (Builder pattern)"
),)
)]
skip_inbound_label_check: bool,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(
const,
attrs(
doc = "Returns the timeout for establishing a stream connection with a remote node for a full state sync, and for stream read and write operations."
)
),
setter(
const,
attrs(
doc = "Sets the timeout for establishing a stream connection with a remote node for a full state sync, and for stream read and write operations (Builder pattern)."
)
)
)]
timeout: Duration,
#[viewit(
getter(
const,
attrs(
doc = "Returns the number of nodes that will be asked to perform an indirect probe of a node in the case a direct probe fails."
)
),
setter(
const,
attrs(
doc = "Sets the number of nodes that will be asked to perform an indirect probe of a node in the case a direct probe fails (Builder pattern)."
)
)
)]
indirect_checks: usize,
#[viewit(
getter(const, attrs(doc = "Returns the retransmit mult")),
setter(const, attrs(doc = "Sets the retransmit mult (Builder pattern)."))
)]
retransmit_mult: usize,
#[viewit(
getter(const, attrs(doc = "Returns the suspicion mult")),
setter(const, attrs(doc = "Sets the suspicion mult (Builder pattern)."))
)]
suspicion_mult: usize,
#[viewit(
getter(const, attrs(doc = "Returns the suspicion max timeout mult")),
setter(
const,
attrs(doc = "Sets the suspicion max timeout mult (Builder pattern).")
)
)]
suspicion_max_timeout_mult: usize,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(const, attrs(doc = "Returns the push pull interval")),
setter(const, attrs(doc = "Sets the push pull interval (Builder pattern)."))
)]
push_pull_interval: Duration,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(const, attrs(doc = "Returns the probe interval")),
setter(const, attrs(doc = "Sets the probe interval (Builder pattern)."))
)]
probe_interval: Duration,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(const, attrs(doc = "Returns the probe timeout")),
setter(const, attrs(doc = "Sets the probe timeout (Builder pattern)."))
)]
probe_timeout: Duration,
#[viewit(
getter(const, attrs(doc = "Returns whether disable promised pings or not")),
setter(
const,
attrs(doc = "Sets whether disable promised pings or not (Builder pattern).")
)
)]
disable_reliable_pings: bool,
#[viewit(
getter(const, attrs(doc = "Returns the awareness max multiplier")),
setter(
const,
attrs(doc = "Sets the awareness max multiplier (Builder pattern).")
)
)]
awareness_max_multiplier: usize,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(const, attrs(doc = "Returns the gossip interval")),
setter(const, attrs(doc = "Sets the gossip interval (Builder pattern)."))
)]
gossip_interval: Duration,
#[viewit(
getter(const, attrs(doc = "Returns the gossip nodes")),
setter(const, attrs(doc = "Sets the gossip nodes (Builder pattern)."))
)]
gossip_nodes: usize,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(const, attrs(doc = "Returns the gossip to the dead timeout")),
setter(
const,
attrs(doc = "Sets the gossip to the dead timeout (Builder pattern).")
)
)]
gossip_to_the_dead_time: Duration,
#[viewit(
getter(
const,
attrs(doc = "Returns the protocol version this node is speaking")
),
setter(
const,
attrs(doc = "Sets the protocol version this node is speaking (Builder pattern).")
)
)]
protocol_version: ProtocolVersion,
#[viewit(
getter(
const,
attrs(doc = "Returns the delegate version this node is speaking")
),
setter(
const,
attrs(doc = "Sets the delegate version this node is speaking (Builder pattern).")
)
)]
delegate_version: DelegateVersion,
#[viewit(
getter(const, attrs(doc = "Returns the handoff queue depth")),
setter(const, attrs(doc = "Sets the handoff queue depth (Builder pattern)."))
)]
handoff_queue_depth: usize,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(const, attrs(doc = "Returns the dead node reclaim time")),
setter(
const,
attrs(doc = "Sets the dead node reclaim time (Builder pattern).")
)
)]
dead_node_reclaim_time: Duration,
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
#[viewit(
getter(const, attrs(doc = "Returns the queue check interval")),
setter(const, attrs(doc = "Sets the queue check interval (Builder pattern)."))
)]
queue_check_interval: Duration,
#[cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3",
))]
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Option::is_none", default)
)]
#[viewit(
getter(
const,
attrs(
doc = "Returns the checksum algorithm for the packets sent through transport.",
cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3",
)),
cfg_attr(
docsrs,
doc(cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3",
)))
)
)
),
setter(
const,
rename = "maybe_checksum_algo",
attrs(
doc = "Sets the checksum algorithm for the packets sent through transport.",
cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3",
)),
cfg_attr(
docsrs,
doc(cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3",
)))
)
)
)
)]
checksum_algo: Option<ChecksumAlgorithm>,
#[cfg(any(
feature = "encryption",
feature = "lz4",
feature = "zstd",
feature = "brotli",
feature = "snappy",
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "encryption",
feature = "lz4",
feature = "zstd",
feature = "brotli",
feature = "snappy",
)))
)]
#[viewit(
getter(
const,
attrs(
doc = "Get the size of a message that should be offload to [`rayon`] thread pool for encryption or compression.",
cfg(any(
feature = "encryption",
feature = "lz4",
feature = "zstd",
feature = "brotli",
feature = "snappy",
)),
cfg_attr(docsrs, doc(cfg(any(feature = "compression", feature = "encryption"))))
),
),
setter(attrs(
doc = "Set the size of a message that should be offload to [`rayon`] thread pool for encryption or compression. (Builder pattern)",
cfg(any(
feature = "encryption",
feature = "lz4",
feature = "zstd",
feature = "brotli",
feature = "snappy",
)),
cfg_attr(
docsrs,
doc(cfg(any(
feature = "encryption",
feature = "lz4",
feature = "zstd",
feature = "brotli",
feature = "snappy",
)))
)
),)
)]
offload_size: usize,
#[cfg(feature = "encryption")]
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Option::is_none", default)
)]
#[viewit(
getter(
const,
attrs(
doc = "Returns the encryption algorithm for the messages sent through transport.",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
)
),
setter(
const,
rename = "maybe_encryption_algo",
attrs(
doc = "Sets the encryption algorithm for the messages sent through transport.",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
)
)
)]
encryption_algo: Option<EncryptionAlgorithm>,
#[cfg_attr(feature = "serde", serde(default))]
#[cfg(feature = "encryption")]
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
#[viewit(
getter(
const,
attrs(
doc = "Get whether to enforce encryption for outgoing gossip. It is used for upshifting from unencrypted to encrypted gossip on a running cluster.",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
),
),
setter(attrs(
doc = "Set whether to enforce encryption for outgoing gossip. It is used for upshifting from unencrypted to encrypted gossip on a running cluster. (Builder pattern)",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
),)
)]
gossip_verify_outgoing: bool,
#[cfg_attr(feature = "serde", serde(default))]
#[cfg(feature = "encryption")]
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
#[viewit(
getter(
const,
attrs(
doc = "Get whether to enforce encryption for incoming gossip. It is used for upshifting from unencrypted to encrypted gossip on a running cluster.",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
),
),
setter(attrs(
doc = "Set whether to enforce encryption for incoming gossip. It is used for upshifting from unencrypted to encrypted gossip on a running cluster. (Builder pattern)",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
),)
)]
gossip_verify_incoming: bool,
#[cfg(feature = "encryption")]
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
#[viewit(
getter(
const,
style = "ref",
result(converter(fn = "Option::as_ref"), type = "Option<&SecretKey>"),
attrs(
doc = "Get the primary encryption key in a keyring.",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
),
),
setter(
rename = "maybe_primary_key",
attrs(
doc = "Set the primary encryption key in a keyring. (Builder pattern)",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
),
)
)]
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Option::is_none", default)
)]
primary_key: Option<SecretKey>,
#[viewit(
getter(
style = "ref",
result(converter(fn = "AsRef::as_ref"), type = "&[SecretKey]"),
attrs(
doc = "Get all of the encryption keys used internally.",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
),
),
setter(attrs(
doc = "Set all of the encryption keys used internally. (Builder pattern)",
cfg(feature = "encryption"),
cfg_attr(docsrs, doc(cfg(feature = "encryption")))
))
)]
#[cfg(feature = "encryption")]
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "SecretKeys::is_empty", default)
)]
secret_keys: SecretKeys,
#[cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
))]
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Option::is_none", default)
)]
#[viewit(
getter(
const,
attrs(
doc = "Returns the compress algorithm for the messages sent through transport.",
cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
)),
cfg_attr(
docsrs,
doc(cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
)))
)
)
),
setter(
const,
rename = "maybe_compress_algo",
attrs(
doc = "Sets the compress algorithm for the messages sent through transport.",
cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
)),
cfg_attr(
docsrs,
doc(cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
)))
)
)
)
)]
compress_algo: Option<CompressAlgorithm>,
#[viewit(
getter(
style = "ref",
const,
attrs(
doc = "Get the metric labels for the memberlist.",
cfg(feature = "metrics"),
cfg_attr(docsrs, doc(cfg(feature = "metrics")))
)
),
setter(attrs(
doc = "Sets the metric labels for the memberlist.",
cfg(feature = "metrics"),
cfg_attr(docsrs, doc(cfg(feature = "metrics")))
))
)]
#[cfg(feature = "metrics")]
metric_labels: std::sync::Arc<MetricLabels>,
}
impl Default for Options {
#[inline]
fn default() -> Self {
Self::lan()
}
}
impl Options {
#[inline]
pub fn lan() -> Self {
Self {
label: Label::empty(),
timeout: Duration::from_secs(10), indirect_checks: 3, retransmit_mult: 4, suspicion_mult: 4, suspicion_max_timeout_mult: 6, push_pull_interval: Duration::from_secs(30), probe_interval: Duration::from_millis(500), probe_timeout: Duration::from_secs(1), disable_reliable_pings: false, awareness_max_multiplier: 8, gossip_interval: Duration::from_millis(200), gossip_nodes: 3, gossip_to_the_dead_time: Duration::from_secs(30), delegate_version: DelegateVersion::V1,
protocol_version: ProtocolVersion::V1,
handoff_queue_depth: 1024,
dead_node_reclaim_time: Duration::ZERO,
queue_check_interval: Duration::from_secs(30),
skip_inbound_label_check: false,
#[cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3"
))]
checksum_algo: None,
#[cfg(any(
feature = "encryption",
feature = "lz4",
feature = "zstd",
feature = "brotli",
feature = "snappy",
))]
offload_size: 1024 * 1024,
#[cfg(feature = "encryption")]
encryption_algo: None,
#[cfg(feature = "encryption")]
gossip_verify_incoming: false,
#[cfg(feature = "encryption")]
gossip_verify_outgoing: false,
#[cfg(feature = "encryption")]
primary_key: None,
#[cfg(feature = "encryption")]
secret_keys: SecretKeys::new(),
#[cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
))]
compress_algo: None,
#[cfg(feature = "metrics")]
metric_labels: std::sync::Arc::new(MetricLabels::new()),
}
}
#[inline]
pub fn wan() -> Self {
Self::lan()
.with_timeout(Duration::from_secs(30))
.with_suspicion_mult(6)
.with_push_pull_interval(Duration::from_secs(60))
.with_probe_timeout(Duration::from_secs(3))
.with_probe_interval(Duration::from_secs(5))
.with_gossip_nodes(4)
.with_gossip_interval(Duration::from_millis(500))
.with_gossip_to_the_dead_time(Duration::from_secs(60))
}
#[inline]
pub fn local() -> Self {
Self::lan()
.with_timeout(Duration::from_secs(1))
.with_indirect_checks(1)
.with_retransmit_mult(2)
.with_suspicion_mult(3)
.with_push_pull_interval(Duration::from_secs(15))
.with_probe_timeout(Duration::from_millis(200))
.with_probe_interval(Duration::from_secs(1))
.with_gossip_interval(Duration::from_millis(100))
.with_gossip_to_the_dead_time(Duration::from_secs(15))
}
#[cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "zstd",
feature = "lz4",
feature = "brotli",
feature = "snappy",
)))
)]
#[inline]
pub fn with_compress_algo(mut self, compress_algo: CompressAlgorithm) -> Self {
self.compress_algo = Some(compress_algo);
self
}
#[cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3",
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
feature = "crc32",
feature = "xxhash32",
feature = "xxhash64",
feature = "xxhash3",
feature = "murmur3",
)))
)]
#[inline]
pub fn with_checksum_algo(mut self, checksum_algo: ChecksumAlgorithm) -> Self {
self.checksum_algo = Some(checksum_algo);
self
}
#[cfg(feature = "encryption")]
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
#[inline]
pub fn with_encryption_algo(mut self, encryption_algo: EncryptionAlgorithm) -> Self {
self.encryption_algo = Some(encryption_algo);
self
}
#[cfg(feature = "encryption")]
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
#[inline]
pub fn with_primary_key(mut self, primary_key: SecretKey) -> Self {
self.primary_key = Some(primary_key);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_constructor() {
let _ = Options::wan();
let _ = Options::lan();
let _ = Options::local();
}
}