Skip to content

Commit 944d31f

Browse files
committed
feat: add builder patterns to ALL remaining request structs
Complete 100% builder pattern coverage across both libraries! redis-cloud (already complete): - All 6 request structs have TypedBuilder redis-enterprise (now complete): - All 18 request structs now have TypedBuilder - Migrated CreateDatabaseRequest from custom builder to TypedBuilder - Added builders to all HIGH, MEDIUM, and LOW priority structs Structs updated in this commit: - CreateDatabaseRequest (migrated from custom builder) - BootstrapRequest with nested ClusterBootstrapInfo - CreateMigrationRequest with MigrationEndpoint - DebugInfoRequest (all optional fields) - CreateScheduledJobRequest - CreateLdapMappingRequest - CreateSuffixRequest - CreateRedisAclRequest - CreateCrdbTaskRequest - DiagnosticRequest - ServiceConfigRequest - NodeActionRequest - LicenseUpdateRequest - ModuleConfig (helper struct) Achievement: 100% builder pattern coverage! - redis-cloud: 6/6 structs ✅ - redis-enterprise: 18/18 structs ✅ Resolves #38 Closes #41
1 parent 0a518d8 commit 944d31f

File tree

15 files changed

+107
-133
lines changed

15 files changed

+107
-133
lines changed

crates/redis-enterprise/src/bdb.rs

Lines changed: 30 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::client::RestClient;
44
use crate::error::Result;
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
7+
use typed_builder::TypedBuilder;
78

89
// Aliases for easier use
910
pub type Database = DatabaseInfo;
@@ -243,136 +244,62 @@ pub struct EndpointInfo {
243244
pub dns_name: Option<String>,
244245
}
245246

246-
/// Builder for CreateDatabaseRequest
247-
#[derive(Debug, Default)]
248-
pub struct CreateDatabaseRequestBuilder {
249-
name: Option<String>,
250-
memory_size: Option<u64>,
251-
port: Option<u16>,
252-
replication: Option<bool>,
253-
persistence: Option<String>,
254-
eviction_policy: Option<String>,
255-
shards_count: Option<u32>,
256-
module_list: Option<Vec<ModuleConfig>>,
257-
authentication_redis_pass: Option<String>,
258-
}
259-
260-
impl CreateDatabaseRequestBuilder {
261-
/// Create a new builder
262-
pub fn new() -> Self {
263-
Self::default()
264-
}
265-
266-
/// Set the database name (required)
267-
pub fn name(mut self, name: impl Into<String>) -> Self {
268-
self.name = Some(name.into());
269-
self
270-
}
271-
272-
/// Set the memory size in bytes (required)
273-
pub fn memory_size(mut self, size: u64) -> Self {
274-
self.memory_size = Some(size);
275-
self
276-
}
277-
278-
/// Set the port number
279-
pub fn port(mut self, port: u16) -> Self {
280-
self.port = Some(port);
281-
self
282-
}
283-
284-
/// Enable or disable replication
285-
pub fn replication(mut self, enabled: bool) -> Self {
286-
self.replication = Some(enabled);
287-
self
288-
}
289-
290-
/// Set persistence type ("aof", "snapshot", "disabled")
291-
pub fn persistence(mut self, persistence: impl Into<String>) -> Self {
292-
self.persistence = Some(persistence.into());
293-
self
294-
}
295-
296-
/// Set eviction policy
297-
pub fn eviction_policy(mut self, policy: impl Into<String>) -> Self {
298-
self.eviction_policy = Some(policy.into());
299-
self
300-
}
301-
302-
/// Set number of shards
303-
pub fn shards(mut self, count: u32) -> Self {
304-
self.shards_count = Some(count);
305-
self
306-
}
307-
308-
/// Add Redis modules
309-
pub fn modules(mut self, modules: Vec<ModuleConfig>) -> Self {
310-
self.module_list = Some(modules);
311-
self
312-
}
313-
314-
/// Set database password
315-
pub fn password(mut self, password: impl Into<String>) -> Self {
316-
self.authentication_redis_pass = Some(password.into());
317-
self
318-
}
319-
320-
/// Build the request
321-
pub fn build(self) -> Result<CreateDatabaseRequest> {
322-
Ok(CreateDatabaseRequest {
323-
name: self.name.ok_or_else(|| {
324-
crate::error::RestError::ValidationError("Database name is required".to_string())
325-
})?,
326-
memory_size: self.memory_size.ok_or_else(|| {
327-
crate::error::RestError::ValidationError("Memory size is required".to_string())
328-
})?,
329-
port: self.port,
330-
replication: self.replication,
331-
persistence: self.persistence,
332-
eviction_policy: self.eviction_policy,
333-
shards_count: self.shards_count,
334-
module_list: self.module_list,
335-
authentication_redis_pass: self.authentication_redis_pass,
336-
})
337-
}
338-
}
339-
340247
/// Module configuration for database creation
341-
#[derive(Debug, Clone, Serialize, Deserialize)]
248+
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
342249
pub struct ModuleConfig {
250+
#[builder(setter(into))]
343251
pub module_name: String,
344252
#[serde(skip_serializing_if = "Option::is_none")]
253+
#[builder(default, setter(into, strip_option))]
345254
pub module_args: Option<String>,
346255
}
347256

348257
/// Create database request
349-
#[derive(Debug, Serialize, Deserialize)]
258+
///
259+
/// # Examples
260+
///
261+
/// ```rust,no_run
262+
/// use redis_enterprise::{CreateDatabaseRequest, ModuleConfig};
263+
///
264+
/// let request = CreateDatabaseRequest::builder()
265+
/// .name("my-database")
266+
/// .memory_size(1024 * 1024 * 1024) // 1GB
267+
/// .port(12000)
268+
/// .replication(true)
269+
/// .persistence("aof")
270+
/// .eviction_policy("volatile-lru")
271+
/// .shards_count(2)
272+
/// .authentication_redis_pass("secure-password")
273+
/// .build();
274+
/// ```
275+
#[derive(Debug, Serialize, Deserialize, TypedBuilder)]
350276
pub struct CreateDatabaseRequest {
277+
#[builder(setter(into))]
351278
pub name: String,
352279
pub memory_size: u64,
353280
#[serde(skip_serializing_if = "Option::is_none")]
281+
#[builder(default, setter(strip_option))]
354282
pub port: Option<u16>,
355283
#[serde(skip_serializing_if = "Option::is_none")]
284+
#[builder(default, setter(strip_option))]
356285
pub replication: Option<bool>,
357286
#[serde(skip_serializing_if = "Option::is_none")]
287+
#[builder(default, setter(into, strip_option))]
358288
pub persistence: Option<String>,
359289
#[serde(skip_serializing_if = "Option::is_none")]
290+
#[builder(default, setter(into, strip_option))]
360291
pub eviction_policy: Option<String>,
361292
#[serde(skip_serializing_if = "Option::is_none")]
293+
#[builder(default, setter(strip_option))]
362294
pub shards_count: Option<u32>,
363295
#[serde(skip_serializing_if = "Option::is_none")]
296+
#[builder(default, setter(strip_option))]
364297
pub module_list: Option<Vec<ModuleConfig>>,
365298
#[serde(skip_serializing_if = "Option::is_none")]
299+
#[builder(default, setter(into, strip_option))]
366300
pub authentication_redis_pass: Option<String>,
367301
}
368302

369-
impl CreateDatabaseRequest {
370-
/// Create a new builder for the request
371-
pub fn builder() -> CreateDatabaseRequestBuilder {
372-
CreateDatabaseRequestBuilder::new()
373-
}
374-
}
375-
376303
/// Database handler for executing database commands
377304
pub struct DatabaseHandler {
378305
client: RestClient,
@@ -398,16 +325,6 @@ impl DatabaseHandler {
398325
self.client.post("/v1/bdbs", &request).await
399326
}
400327

401-
/// Create a new database using builder pattern
402-
pub async fn create_with_builder<F>(&self, f: F) -> Result<DatabaseInfo>
403-
where
404-
F: FnOnce(CreateDatabaseRequestBuilder) -> CreateDatabaseRequestBuilder,
405-
{
406-
let builder = CreateDatabaseRequestBuilder::new();
407-
let request = f(builder).build()?;
408-
self.create(request).await
409-
}
410-
411328
/// Update database configuration (BDB.UPDATE)
412329
pub async fn update(&self, uid: u32, updates: Value) -> Result<DatabaseInfo> {
413330
self.client

crates/redis-enterprise/src/cluster.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::client::RestClient;
44
use crate::error::Result;
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
7+
use typed_builder::TypedBuilder;
78

89
/// Node information
910
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -119,23 +120,27 @@ pub struct ClusterSettings {
119120
}
120121

121122
/// Bootstrap request for creating a new cluster
122-
#[derive(Debug, Serialize)]
123+
#[derive(Debug, Serialize, TypedBuilder)]
123124
pub struct BootstrapRequest {
125+
#[builder(setter(into))]
124126
pub action: String,
125127
pub cluster: ClusterBootstrapInfo,
126128
pub credentials: BootstrapCredentials,
127129
}
128130

129131
/// Cluster information for bootstrap
130-
#[derive(Debug, Serialize)]
132+
#[derive(Debug, Serialize, TypedBuilder)]
131133
pub struct ClusterBootstrapInfo {
134+
#[builder(setter(into))]
132135
pub name: String,
133136
}
134137

135138
/// Credentials for bootstrap
136-
#[derive(Debug, Serialize)]
139+
#[derive(Debug, Serialize, TypedBuilder)]
137140
pub struct BootstrapCredentials {
141+
#[builder(setter(into))]
138142
pub username: String,
143+
#[builder(setter(into))]
139144
pub password: String,
140145
}
141146

crates/redis-enterprise/src/crdb_tasks.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::client::RestClient;
44
use crate::error::Result;
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
7+
use typed_builder::TypedBuilder;
78

89
/// CRDB task information
910
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -26,11 +27,14 @@ pub struct CrdbTask {
2627
}
2728

2829
/// CRDB task creation request
29-
#[derive(Debug, Clone, Serialize, Deserialize)]
30+
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
3031
pub struct CreateCrdbTaskRequest {
32+
#[builder(setter(into))]
3133
pub crdb_guid: String,
34+
#[builder(setter(into))]
3235
pub task_type: String,
3336
#[serde(skip_serializing_if = "Option::is_none")]
37+
#[builder(default, setter(strip_option))]
3438
pub params: Option<Value>,
3539
}
3640

crates/redis-enterprise/src/debuginfo.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,28 @@ use crate::client::RestClient;
44
use crate::error::Result;
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
7+
use typed_builder::TypedBuilder;
78

89
/// Debug info collection request
9-
#[derive(Debug, Clone, Serialize, Deserialize)]
10+
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
1011
pub struct DebugInfoRequest {
1112
#[serde(skip_serializing_if = "Option::is_none")]
13+
#[builder(default, setter(strip_option))]
1214
pub node_uids: Option<Vec<u32>>,
1315
#[serde(skip_serializing_if = "Option::is_none")]
16+
#[builder(default, setter(strip_option))]
1417
pub bdb_uids: Option<Vec<u32>>,
1518
#[serde(skip_serializing_if = "Option::is_none")]
19+
#[builder(default, setter(strip_option))]
1620
pub include_logs: Option<bool>,
1721
#[serde(skip_serializing_if = "Option::is_none")]
22+
#[builder(default, setter(strip_option))]
1823
pub include_metrics: Option<bool>,
1924
#[serde(skip_serializing_if = "Option::is_none")]
25+
#[builder(default, setter(strip_option))]
2026
pub include_configs: Option<bool>,
2127
#[serde(skip_serializing_if = "Option::is_none")]
28+
#[builder(default, setter(strip_option))]
2229
pub time_range: Option<TimeRange>,
2330
}
2431

crates/redis-enterprise/src/diagnostics.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ use crate::client::RestClient;
44
use crate::error::Result;
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
7+
use typed_builder::TypedBuilder;
78

89
/// Diagnostic check request
9-
#[derive(Debug, Clone, Serialize, Deserialize)]
10+
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
1011
pub struct DiagnosticRequest {
1112
#[serde(skip_serializing_if = "Option::is_none")]
13+
#[builder(default, setter(strip_option))]
1214
pub checks: Option<Vec<String>>,
1315
#[serde(skip_serializing_if = "Option::is_none")]
16+
#[builder(default, setter(strip_option))]
1417
pub node_uids: Option<Vec<u32>>,
1518
#[serde(skip_serializing_if = "Option::is_none")]
19+
#[builder(default, setter(strip_option))]
1620
pub bdb_uids: Option<Vec<u32>>,
1721
}
1822

crates/redis-enterprise/src/job_scheduler.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::client::RestClient;
44
use crate::error::Result;
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
7+
use typed_builder::TypedBuilder;
78

89
/// Scheduled job information
910
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -26,14 +27,19 @@ pub struct ScheduledJob {
2627
}
2728

2829
/// Create scheduled job request
29-
#[derive(Debug, Clone, Serialize, Deserialize)]
30+
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
3031
pub struct CreateScheduledJobRequest {
32+
#[builder(setter(into))]
3133
pub name: String,
34+
#[builder(setter(into))]
3235
pub job_type: String,
36+
#[builder(setter(into))]
3337
pub schedule: String,
3438
#[serde(skip_serializing_if = "Option::is_none")]
39+
#[builder(default, setter(strip_option))]
3540
pub enabled: Option<bool>,
3641
#[serde(skip_serializing_if = "Option::is_none")]
42+
#[builder(default, setter(strip_option))]
3743
pub params: Option<Value>,
3844
}
3945

crates/redis-enterprise/src/ldap_mappings.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::client::RestClient;
44
use crate::error::Result;
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
7+
use typed_builder::TypedBuilder;
78

89
/// LDAP mapping information
910
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -22,14 +23,19 @@ pub struct LdapMapping {
2223
}
2324

2425
/// Create or update LDAP mapping request
25-
#[derive(Debug, Serialize, Deserialize)]
26+
#[derive(Debug, Serialize, Deserialize, TypedBuilder)]
2627
pub struct CreateLdapMappingRequest {
28+
#[builder(setter(into))]
2729
pub name: String,
30+
#[builder(setter(into))]
2831
pub dn: String,
32+
#[builder(setter(into))]
2933
pub role: String,
3034
#[serde(skip_serializing_if = "Option::is_none")]
35+
#[builder(default, setter(into, strip_option))]
3136
pub email: Option<String>,
3237
#[serde(skip_serializing_if = "Option::is_none")]
38+
#[builder(default, setter(strip_option))]
3339
pub role_uids: Option<Vec<u32>>,
3440
}
3541

crates/redis-enterprise/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
//! ## Working with Databases
2525
//!
2626
//! ```no_run
27-
//! use redis_enterprise::{EnterpriseClient, BdbHandler, CreateDatabaseRequestBuilder};
27+
//! use redis_enterprise::{EnterpriseClient, BdbHandler, CreateDatabaseRequest};
2828
//!
2929
//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
3030
//! // List all databases
@@ -35,13 +35,13 @@
3535
//! }
3636
//!
3737
//! // Create a new database
38-
//! let request = CreateDatabaseRequestBuilder::new()
38+
//! let request = CreateDatabaseRequest::builder()
3939
//! .name("my-database")
4040
//! .memory_size(1024 * 1024 * 1024) // 1GB
4141
//! .port(12000)
4242
//! .replication(false)
4343
//! .persistence("aof")
44-
//! .build()?;
44+
//! .build();
4545
//!
4646
//! let new_db = handler.create(request).await?;
4747
//! println!("Created database: {}", new_db.uid);

0 commit comments

Comments
 (0)