prosody 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.config/rail.toml +26 -0
- data/.release-please-manifest.json +1 -1
- data/.ruby-version +1 -1
- data/.taplo.toml +1 -1
- data/AGENTS.md +29 -15
- data/CHANGELOG.md +7 -0
- data/CONFIGURATION.md +19 -16
- data/Cargo.lock +254 -235
- data/Cargo.toml +11 -8
- data/README.md +100 -23
- data/examples/keyed_state.rb +10 -2
- data/examples/keyed_state.rbs +1 -0
- data/ext/prosody/Cargo.toml +1 -1
- data/ext/prosody/src/admin.rs +36 -36
- data/ext/prosody/src/bridge/mod.rs +5 -10
- data/ext/prosody/src/client/config/connections.rs +170 -0
- data/ext/prosody/src/client/config/middleware.rs +184 -0
- data/ext/prosody/src/client/config/mod.rs +396 -0
- data/ext/prosody/src/client/config/state.rs +323 -0
- data/ext/prosody/src/client/mod.rs +31 -117
- data/ext/prosody/src/client/readers.rs +106 -0
- data/ext/prosody/src/client/request.rs +2 -2
- data/ext/prosody/src/client/support.rs +13 -32
- data/ext/prosody/src/gvl.rs +8 -6
- data/ext/prosody/src/handler/{context.rs → context/mod.rs} +36 -150
- data/ext/prosody/src/handler/context/vending.rs +138 -0
- data/ext/prosody/src/handler/message.rs +36 -0
- data/ext/prosody/src/handler/mod.rs +18 -8
- data/ext/prosody/src/handler/state/deque.rs +144 -0
- data/ext/prosody/src/handler/state/mod.rs +163 -268
- data/ext/prosody/src/handler/state/query.rs +264 -0
- data/ext/prosody/src/handler/state/registration.rs +15 -86
- data/ext/prosody/src/handler/state/scan.rs +33 -141
- data/ext/prosody/src/handler/state/set.rs +98 -0
- data/ext/prosody/src/lib.rs +54 -36
- data/ext/prosody/src/logging.rs +6 -6
- data/ext/prosody/src/published.rs +171 -152
- data/ext/prosody/src/scheduler/result.rs +2 -1
- data/ext/prosody/src/util.rs +65 -3
- data/lib/prosody/client.rb +32 -0
- data/lib/prosody/configuration.rb +20 -12
- data/lib/prosody/demand.rb +27 -0
- data/lib/prosody/native_stubs/client.rb +157 -0
- data/lib/prosody/native_stubs/context.rb +178 -0
- data/lib/prosody/native_stubs/message.rb +133 -0
- data/lib/prosody/native_stubs.rb +11 -956
- data/lib/prosody/state/deque.rb +253 -0
- data/lib/prosody/state/map.rb +313 -0
- data/lib/prosody/state/set.rb +121 -0
- data/lib/prosody/state/value.rb +58 -0
- data/lib/prosody/state.rb +157 -677
- data/lib/prosody/version.rb +1 -1
- data/lib/prosody.rb +2 -1
- data/sig/configuration.rbs +19 -10
- data/sig/prosody.rbs +37 -4
- data/sig/published.rbs +102 -0
- data/sig/state.rbs +109 -122
- data/typecheck/payload_types.rb +12 -0
- data/typecheck/payload_types.rbs +1 -0
- metadata +30 -11
- data/ext/prosody/src/client/config.rs +0 -1300
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
//! Conversion of the Ruby client configuration into Prosody configuration.
|
|
2
|
+
//!
|
|
3
|
+
//! [`NativeConfiguration`] holds every option the Ruby side can set. This
|
|
4
|
+
//! module converts it into [`ConsumerBuilders`] and the processing [`Mode`].
|
|
5
|
+
//! The submodules own the other conversions: `connections` for the Kafka,
|
|
6
|
+
//! Cassandra, and telemetry builders, `middleware` for the middleware
|
|
7
|
+
//! builders, and `state` for keyed state.
|
|
8
|
+
|
|
9
|
+
use crate::util::seconds;
|
|
10
|
+
use prosody::PeerConfiguration;
|
|
11
|
+
use prosody::PeerEndpoint;
|
|
12
|
+
use prosody::consumer::ConsumerConfigurationBuilder;
|
|
13
|
+
use prosody::consumer::SpanRelation;
|
|
14
|
+
use prosody::high_level::ConsumerBuilders;
|
|
15
|
+
use prosody::high_level::mode::Mode;
|
|
16
|
+
use prosody::loader::KafkaLoaderConfiguration;
|
|
17
|
+
use serde::{Deserialize, Deserializer};
|
|
18
|
+
use serde_untagged::UntaggedEnumVisitor;
|
|
19
|
+
pub(crate) use state::{ReadCacheConfig, read_cache_policy};
|
|
20
|
+
use state::{StateCollectionConfig, build_keyed_state_config};
|
|
21
|
+
use std::net::SocketAddr;
|
|
22
|
+
|
|
23
|
+
mod connections;
|
|
24
|
+
mod middleware;
|
|
25
|
+
mod state;
|
|
26
|
+
|
|
27
|
+
/// Configuration structure for the Prosody client that maps Ruby configuration
|
|
28
|
+
/// values to their native Rust equivalents.
|
|
29
|
+
///
|
|
30
|
+
/// This structure contains all possible configuration options that can be
|
|
31
|
+
/// provided by the Ruby side, which are then converted to the appropriate
|
|
32
|
+
/// Prosody configuration builder types.
|
|
33
|
+
#[derive(Clone, Default, Deserialize)]
|
|
34
|
+
pub struct NativeConfiguration {
|
|
35
|
+
/// List of Kafka bootstrap server addresses
|
|
36
|
+
bootstrap_servers: Option<Vec<String>>,
|
|
37
|
+
|
|
38
|
+
/// Whether to use mock mode (for testing)
|
|
39
|
+
mock: Option<bool>,
|
|
40
|
+
|
|
41
|
+
/// Maximum time to wait for a send operation to complete (in seconds)
|
|
42
|
+
send_timeout: Option<f64>,
|
|
43
|
+
|
|
44
|
+
/// Kafka consumer group ID
|
|
45
|
+
group_id: Option<String>,
|
|
46
|
+
|
|
47
|
+
/// Global shared cache capacity across all partitions for message
|
|
48
|
+
/// deduplication
|
|
49
|
+
idempotence_cache_size: Option<u32>,
|
|
50
|
+
|
|
51
|
+
/// Version string for cache-busting deduplication hashes
|
|
52
|
+
idempotence_version: Option<String>,
|
|
53
|
+
|
|
54
|
+
/// TTL for deduplication records in Cassandra (in seconds)
|
|
55
|
+
idempotence_ttl: Option<f64>,
|
|
56
|
+
|
|
57
|
+
/// List of Kafka topics to subscribe to
|
|
58
|
+
subscribed_topics: Option<Vec<String>>,
|
|
59
|
+
|
|
60
|
+
/// List of event types that the consumer is allowed to process
|
|
61
|
+
allowed_events: Option<Vec<String>>,
|
|
62
|
+
|
|
63
|
+
/// Identifier for the system producing messages
|
|
64
|
+
source_system: Option<String>,
|
|
65
|
+
|
|
66
|
+
/// Maximum number of concurrent message processing tasks
|
|
67
|
+
max_concurrency: Option<u32>,
|
|
68
|
+
|
|
69
|
+
/// Maximum number of messages to process before committing offsets
|
|
70
|
+
max_uncommitted: Option<u32>,
|
|
71
|
+
|
|
72
|
+
/// Threshold in seconds after which a stalled consumer is detected
|
|
73
|
+
stall_threshold: Option<f64>,
|
|
74
|
+
|
|
75
|
+
/// Maximum time to wait for a clean shutdown (in seconds)
|
|
76
|
+
shutdown_timeout: Option<f64>,
|
|
77
|
+
|
|
78
|
+
/// Interval between Kafka poll operations (in seconds)
|
|
79
|
+
poll_interval: Option<f64>,
|
|
80
|
+
|
|
81
|
+
/// Interval between offset commit operations (in seconds)
|
|
82
|
+
commit_interval: Option<f64>,
|
|
83
|
+
|
|
84
|
+
/// Interval between librdkafka statistics reports (in seconds)
|
|
85
|
+
statistics_interval: Option<f64>,
|
|
86
|
+
|
|
87
|
+
/// Operation mode of the client (`pipeline`, `low_latency`, `best_effort`)
|
|
88
|
+
mode: Option<String>,
|
|
89
|
+
|
|
90
|
+
/// Base delay for retry operations (in seconds)
|
|
91
|
+
retry_base: Option<f64>,
|
|
92
|
+
|
|
93
|
+
/// Maximum number of retry attempts
|
|
94
|
+
max_retries: Option<u32>,
|
|
95
|
+
|
|
96
|
+
/// Maximum delay between retries (in seconds)
|
|
97
|
+
max_retry_delay: Option<f64>,
|
|
98
|
+
|
|
99
|
+
/// Topic to send failed messages to
|
|
100
|
+
failure_topic: Option<String>,
|
|
101
|
+
|
|
102
|
+
/// Configuration for the health probe port
|
|
103
|
+
probe_port: Option<ProbePort>,
|
|
104
|
+
|
|
105
|
+
/// List of Cassandra contact nodes (hostnames or IPs)
|
|
106
|
+
cassandra_nodes: Option<Vec<String>>,
|
|
107
|
+
|
|
108
|
+
/// Keyspace used for persistent Prosody data in Cassandra.
|
|
109
|
+
cassandra_keyspace: Option<String>,
|
|
110
|
+
|
|
111
|
+
/// Preferred datacenter for Cassandra query routing
|
|
112
|
+
cassandra_datacenter: Option<String>,
|
|
113
|
+
|
|
114
|
+
/// Preferred rack identifier for Cassandra topology-aware routing
|
|
115
|
+
cassandra_rack: Option<String>,
|
|
116
|
+
|
|
117
|
+
/// Username for authenticating with Cassandra
|
|
118
|
+
cassandra_user: Option<String>,
|
|
119
|
+
|
|
120
|
+
/// Password for authenticating with Cassandra
|
|
121
|
+
cassandra_password: Option<String>,
|
|
122
|
+
|
|
123
|
+
/// Retention period for persistent timer and deferral data in Cassandra,
|
|
124
|
+
/// in seconds.
|
|
125
|
+
cassandra_retention: Option<f64>,
|
|
126
|
+
|
|
127
|
+
/// Timer slab partitioning duration in seconds.
|
|
128
|
+
/// Controls how timers are grouped for storage and retrieval.
|
|
129
|
+
slab_size: Option<f64>,
|
|
130
|
+
|
|
131
|
+
// Scheduler configuration
|
|
132
|
+
/// Target proportion of execution time for failure/retry task processing
|
|
133
|
+
/// (0.0 to 1.0). Controls bandwidth allocation between Normal and
|
|
134
|
+
/// Failure task classes.
|
|
135
|
+
scheduler_failure_weight: Option<f64>,
|
|
136
|
+
|
|
137
|
+
/// Wait duration (in seconds) at which urgency boost reaches maximum
|
|
138
|
+
/// intensity.
|
|
139
|
+
scheduler_max_wait: Option<f64>,
|
|
140
|
+
|
|
141
|
+
/// Maximum urgency boost (in seconds of virtual time) for waiting tasks.
|
|
142
|
+
scheduler_wait_weight: Option<f64>,
|
|
143
|
+
|
|
144
|
+
/// Cache capacity for tracking per-key virtual time in the scheduler.
|
|
145
|
+
scheduler_cache_size: Option<u32>,
|
|
146
|
+
|
|
147
|
+
// Monopolization configuration
|
|
148
|
+
/// Whether monopolization detection is enabled.
|
|
149
|
+
monopolization_enabled: Option<bool>,
|
|
150
|
+
|
|
151
|
+
/// Threshold for monopolization detection (0.0 to 1.0).
|
|
152
|
+
monopolization_threshold: Option<f64>,
|
|
153
|
+
|
|
154
|
+
/// Rolling window duration (in seconds) for monopolization detection.
|
|
155
|
+
monopolization_window: Option<f64>,
|
|
156
|
+
|
|
157
|
+
/// Cache size for tracking key execution intervals.
|
|
158
|
+
monopolization_cache_size: Option<u32>,
|
|
159
|
+
|
|
160
|
+
// Defer configuration
|
|
161
|
+
/// Whether deferral is enabled for new messages.
|
|
162
|
+
defer_enabled: Option<bool>,
|
|
163
|
+
|
|
164
|
+
/// Base exponential backoff delay for deferred retries (in seconds).
|
|
165
|
+
defer_base: Option<f64>,
|
|
166
|
+
|
|
167
|
+
/// Maximum delay between deferred retries (in seconds).
|
|
168
|
+
defer_max_delay: Option<f64>,
|
|
169
|
+
|
|
170
|
+
/// Failure rate threshold for disabling deferral (0.0 to 1.0).
|
|
171
|
+
defer_failure_threshold: Option<f64>,
|
|
172
|
+
|
|
173
|
+
/// Sliding window duration (in seconds) for failure rate tracking.
|
|
174
|
+
defer_failure_window: Option<f64>,
|
|
175
|
+
|
|
176
|
+
/// Maximum messages retained by the shared Kafka loader.
|
|
177
|
+
loader_cache_size: Option<u32>,
|
|
178
|
+
|
|
179
|
+
/// Maximum number of deferred store entries kept in the write-through cache
|
|
180
|
+
/// per Cassandra defer store.
|
|
181
|
+
defer_store_cache_size: Option<u32>,
|
|
182
|
+
|
|
183
|
+
/// Timeout for Kafka loader seek operations (in seconds).
|
|
184
|
+
loader_seek_timeout: Option<f64>,
|
|
185
|
+
|
|
186
|
+
/// Messages to read sequentially before seeking.
|
|
187
|
+
loader_discard_threshold: Option<i64>,
|
|
188
|
+
|
|
189
|
+
// Timeout configuration
|
|
190
|
+
/// Fixed timeout duration for handler execution (in seconds).
|
|
191
|
+
timeout: Option<f64>,
|
|
192
|
+
|
|
193
|
+
// Telemetry emitter configuration
|
|
194
|
+
/// Kafka topic to produce telemetry events to.
|
|
195
|
+
telemetry_topic: Option<String>,
|
|
196
|
+
|
|
197
|
+
/// Whether the telemetry emitter is enabled.
|
|
198
|
+
telemetry_enabled: Option<bool>,
|
|
199
|
+
|
|
200
|
+
// OTel span linking
|
|
201
|
+
/// Span linking for message execution spans (`child` or `follows_from`).
|
|
202
|
+
message_spans: Option<String>,
|
|
203
|
+
|
|
204
|
+
/// Span linking for timer execution spans (`child` or `follows_from`).
|
|
205
|
+
timer_spans: Option<String>,
|
|
206
|
+
|
|
207
|
+
/// Address for the peer listener.
|
|
208
|
+
peer_bind_address: Option<String>,
|
|
209
|
+
|
|
210
|
+
/// gRPC connect URI that peers use for this client.
|
|
211
|
+
peer_advertised_connect: Option<String>,
|
|
212
|
+
|
|
213
|
+
/// Network name used to identify direct routes.
|
|
214
|
+
peer_network_name: Option<String>,
|
|
215
|
+
|
|
216
|
+
/// Maximum number of peer channels and registrations held in each cache.
|
|
217
|
+
peer_cache_capacity: Option<usize>,
|
|
218
|
+
|
|
219
|
+
/// Duration of each peer registration lease, in seconds.
|
|
220
|
+
peer_registration_ttl: Option<f64>,
|
|
221
|
+
|
|
222
|
+
// Keyed-state configuration
|
|
223
|
+
/// Keyed-state collections to register before subscribe.
|
|
224
|
+
state_collections: Option<Vec<StateCollectionConfig>>,
|
|
225
|
+
|
|
226
|
+
/// Subsystem under which published collections are advertised.
|
|
227
|
+
subsystem: Option<String>,
|
|
228
|
+
|
|
229
|
+
/// Directory for the local keyed-state caches. Each consumer uses a new
|
|
230
|
+
/// subdirectory, so clients can share it. Must not be empty.
|
|
231
|
+
state_cache_dir: Option<String>,
|
|
232
|
+
|
|
233
|
+
/// Capacity of the owning keyed-state cache.
|
|
234
|
+
state_owned_cache_size: Option<String>,
|
|
235
|
+
|
|
236
|
+
/// Size at which the local keyed-state cache flushes a partition's
|
|
237
|
+
/// in-memory writes to disk. `None` uses `PROSODY_STATE_MEMTABLE_SIZE`,
|
|
238
|
+
/// or the engine default of 64 MiB when that is unset.
|
|
239
|
+
state_memtable_size: Option<String>,
|
|
240
|
+
|
|
241
|
+
/// Capacity of the published-state read-through cache.
|
|
242
|
+
state_read_cache_size: Option<String>,
|
|
243
|
+
|
|
244
|
+
/// Default cache policy for published-state reads.
|
|
245
|
+
state_read_cache: Option<ReadCacheConfig>,
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/// Configuration for the health probe port.
|
|
249
|
+
///
|
|
250
|
+
/// This enum represents the three possible states for the probe port
|
|
251
|
+
/// configuration:
|
|
252
|
+
/// - Unconfigured: The default state, where the standard configuration is used
|
|
253
|
+
/// - Disabled: Explicitly disables the probe port
|
|
254
|
+
/// - Configured: Sets the probe port to a specific port number
|
|
255
|
+
#[derive(Copy, Clone, Debug, Default)]
|
|
256
|
+
pub enum ProbePort {
|
|
257
|
+
/// Use default configuration
|
|
258
|
+
#[default]
|
|
259
|
+
Unconfigured,
|
|
260
|
+
|
|
261
|
+
/// Explicitly disable the probe port
|
|
262
|
+
Disabled,
|
|
263
|
+
|
|
264
|
+
/// Use a specific port number
|
|
265
|
+
Configured(u16),
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
impl<'de> Deserialize<'de> for ProbePort {
|
|
269
|
+
/// Reads a port number as `Configured`, `false` as `Disabled`, and `true`
|
|
270
|
+
/// or `nil` as `Unconfigured`.
|
|
271
|
+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
272
|
+
where
|
|
273
|
+
D: Deserializer<'de>,
|
|
274
|
+
{
|
|
275
|
+
UntaggedEnumVisitor::new()
|
|
276
|
+
.u16(|port| Ok(Self::Configured(port)))
|
|
277
|
+
.bool(|enabled| {
|
|
278
|
+
if enabled {
|
|
279
|
+
Ok(Self::Unconfigured)
|
|
280
|
+
} else {
|
|
281
|
+
Ok(Self::Disabled)
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
.unit(|| Ok(Self::Unconfigured))
|
|
285
|
+
.deserialize(deserializer)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
impl<'a> TryFrom<&'a NativeConfiguration> for Mode {
|
|
290
|
+
type Error = String;
|
|
291
|
+
|
|
292
|
+
/// Reads the processing mode. An unrecognized mode fails.
|
|
293
|
+
fn try_from(value: &'a NativeConfiguration) -> Result<Self, Self::Error> {
|
|
294
|
+
let Some(mode_str) = value.mode.as_deref() else {
|
|
295
|
+
return Ok(Mode::default());
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
match mode_str {
|
|
299
|
+
"pipeline" => Ok(Mode::Pipeline),
|
|
300
|
+
"low_latency" => Ok(Mode::LowLatency),
|
|
301
|
+
"best_effort" => Ok(Mode::BestEffort),
|
|
302
|
+
string => Err(format!("unrecognized mode: {string}")),
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
impl<'a> TryFrom<&'a NativeConfiguration> for ConsumerBuilders {
|
|
308
|
+
type Error = String;
|
|
309
|
+
|
|
310
|
+
/// Builds every consumer builder from the configuration.
|
|
311
|
+
///
|
|
312
|
+
/// # Errors
|
|
313
|
+
///
|
|
314
|
+
/// Fails on a bad setting, for example an unrecognized `message_spans` or
|
|
315
|
+
/// `timer_spans` value, a bad loader value, or a bad peer address.
|
|
316
|
+
fn try_from(config: &'a NativeConfiguration) -> Result<Self, Self::Error> {
|
|
317
|
+
let mut consumer: ConsumerConfigurationBuilder = config.try_into()?;
|
|
318
|
+
|
|
319
|
+
if let Some(s) = &config.message_spans {
|
|
320
|
+
let relation = s
|
|
321
|
+
.parse::<SpanRelation>()
|
|
322
|
+
.map_err(|e| format!("message_spans: {e}"))?;
|
|
323
|
+
consumer.message_spans(relation);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if let Some(s) = &config.timer_spans {
|
|
327
|
+
let relation = s
|
|
328
|
+
.parse::<SpanRelation>()
|
|
329
|
+
.map_err(|e| format!("timer_spans: {e}"))?;
|
|
330
|
+
consumer.timer_spans(relation);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Route the shared Kafka message loader settings onto the consumer.
|
|
334
|
+
if config.loader_cache_size.is_some()
|
|
335
|
+
|| config.loader_seek_timeout.is_some()
|
|
336
|
+
|| config.loader_discard_threshold.is_some()
|
|
337
|
+
{
|
|
338
|
+
let mut loader = KafkaLoaderConfiguration::builder();
|
|
339
|
+
|
|
340
|
+
if let Some(cache_size) = &config.loader_cache_size {
|
|
341
|
+
loader.cache_size(*cache_size as usize);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if let Some(seek_timeout) = &config.loader_seek_timeout {
|
|
345
|
+
loader.seek_timeout(seconds("loader_seek_timeout", *seek_timeout)?);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if let Some(discard_threshold) = &config.loader_discard_threshold {
|
|
349
|
+
loader.discard_threshold(*discard_threshold);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
consumer.loader(loader.build().map_err(|e| e.to_string())?);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
Ok(Self {
|
|
356
|
+
consumer,
|
|
357
|
+
retry: config.try_into()?,
|
|
358
|
+
failure_topic: config.into(),
|
|
359
|
+
scheduler: config.try_into()?,
|
|
360
|
+
monopolization: config.try_into()?,
|
|
361
|
+
defer: config.try_into()?,
|
|
362
|
+
timeout: config.try_into()?,
|
|
363
|
+
dedup: config.try_into()?,
|
|
364
|
+
emitter: config.try_into()?,
|
|
365
|
+
keyed_state: build_keyed_state_config(config)?,
|
|
366
|
+
peer: build_peer_config(config)?,
|
|
367
|
+
})
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
fn build_peer_config(config: &NativeConfiguration) -> Result<PeerConfiguration, String> {
|
|
372
|
+
let mut builder = PeerConfiguration::builder();
|
|
373
|
+
if let Some(value) = &config.peer_bind_address {
|
|
374
|
+
builder.bind_address(
|
|
375
|
+
value
|
|
376
|
+
.parse::<SocketAddr>()
|
|
377
|
+
.map_err(|error| format!("peer_bind_address: {error}"))?,
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
if let Some(value) = &config.peer_advertised_connect {
|
|
381
|
+
builder.advertised_connect(
|
|
382
|
+
PeerEndpoint::try_from(value.clone())
|
|
383
|
+
.map_err(|error| format!("peer_advertised_connect: {error}"))?,
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
if let Some(value) = &config.peer_network_name {
|
|
387
|
+
builder.network_name(value.clone());
|
|
388
|
+
}
|
|
389
|
+
if let Some(value) = config.peer_cache_capacity {
|
|
390
|
+
builder.peer_cache_capacity(value);
|
|
391
|
+
}
|
|
392
|
+
if let Some(value) = config.peer_registration_ttl {
|
|
393
|
+
builder.registration_ttl(seconds("peer_registration_ttl", value)?);
|
|
394
|
+
}
|
|
395
|
+
builder.build().map_err(|error| error.to_string())
|
|
396
|
+
}
|