Skip to content

Latest commit

 

History

History
186 lines (139 loc) · 5.25 KB

File metadata and controls

186 lines (139 loc) · 5.25 KB

redis-cloud Harmonization Plan

Goal: Align redis-cloud with redis-enterprise patterns for consistency.

Changes Overview

1. Add TypedBuilder to Request Types

Priority: High

Currently request types use manual Option<T> fields:

pub struct DatabaseCreateRequest {
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub memory_limit_in_gb: Option<f64>,
    // ... many more
}

Change to TypedBuilder pattern (matching redis-enterprise):

#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
pub struct DatabaseCreateRequest {
    #[builder(setter(into))]
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(strip_option))]
    pub memory_limit_in_gb: Option<f64>,
    // ...
}

Files to update:

  • src/flexible/databases.rs - DatabaseCreateRequest, DatabaseUpdateRequest, DatabaseImportRequest, etc.
  • src/flexible/subscriptions.rs - SubscriptionCreateRequest, SubscriptionUpdateRequest, etc.
  • src/fixed/databases.rs - Fixed plan request types
  • src/fixed/subscriptions.rs - Fixed plan request types
  • src/acl.rs - ACL request types
  • src/users.rs - User request types
  • src/connectivity/*.rs - VPC peering, PSC, etc. request types

Dependencies to add:

typed-builder = "0.18"

2. Add Error Helper Methods

Priority: High

Currently CloudError only has is_retryable(). Add helpers matching redis-enterprise:

impl CloudError {
    pub fn is_retryable(&self) -> bool { /* existing */ }

    // Add these:
    pub fn is_not_found(&self) -> bool {
        matches!(self, CloudError::NotFound { .. })
    }

    pub fn is_unauthorized(&self) -> bool {
        matches!(self, CloudError::AuthenticationFailed { .. } | CloudError::Forbidden { .. })
    }

    pub fn is_server_error(&self) -> bool {
        matches!(self, CloudError::InternalServerError { .. } | CloudError::ServiceUnavailable { .. })
    }

    pub fn is_timeout(&self) -> bool {
        matches!(self, CloudError::ConnectionError(msg) if msg.contains("timeout"))
    }

    pub fn is_rate_limited(&self) -> bool {
        matches!(self, CloudError::RateLimited { .. })
    }

    pub fn is_conflict(&self) -> bool {
        matches!(self, CloudError::PreconditionFailed)
    }

    pub fn is_bad_request(&self) -> bool {
        matches!(self, CloudError::BadRequest { .. })
    }
}

Files to update:

  • src/error.rs

3. Consistent Handler Method Naming

Priority: Medium

Align method names where semantically equivalent:

Operation Current (Cloud) Target Enterprise
List DBs get_subscription_databases list list
Get DB get_subscription_database_by_id get get / info
Create DB create_database create create
Update DB update_database update update
Delete DB delete_database_by_id delete delete

Note: Keep subscription_id as parameter (architectural difference), but simplify method names.

Approach: Add new methods with simpler names, deprecate old ones:

impl DatabaseHandler {
    /// List databases in a subscription
    pub async fn list(&self, subscription_id: i32) -> Result<Vec<Database>> {
        // Unwrap the nested response internally
        let response = self.get_subscription_databases(subscription_id, None, None).await?;
        Ok(Self::extract_databases_from_response(&response))
    }

    #[deprecated(since = "0.10.0", note = "Use `list` instead")]
    pub async fn get_subscription_databases(...) -> Result<AccountSubscriptionDatabases> {
        // existing implementation
    }
}

Files to update:

  • src/flexible/databases.rs
  • src/flexible/subscriptions.rs
  • src/fixed/databases.rs
  • src/fixed/subscriptions.rs

4. Simplify Return Types (New Methods)

Priority: Medium

Add simplified methods that unwrap nested containers:

// Current: Returns nested wrapper
pub async fn get_subscription_databases(...) -> Result<AccountSubscriptionDatabases>

// Add: Returns direct vector
pub async fn list(&self, subscription_id: i32) -> Result<Vec<Database>>

Keep original methods for backward compatibility but encourage new patterns.

5. Add Timeout Error Variant

Priority: Low

Enterprise has explicit Timeout variant. Consider adding to Cloud:

pub enum CloudError {
    // ... existing variants

    /// Request timed out
    Timeout,
}

Files to update:

  • src/error.rs
  • src/client.rs (map timeout errors)

Non-Changes (Keep as Layer 2 Concern)

These are architectural differences that Layer 2 should handle:

  • Async task model - TaskStateUpdate returns are by design (Cloud API is async)
  • Subscription context - Required parameter is architectural (multi-tenant)
  • Nested response wrappers - Original methods preserved for full API access

Testing

  • Ensure all existing tests pass
  • Add tests for new TypedBuilder usage
  • Add tests for error helper methods
  • Add tests for new simplified methods

Version

This will be a minor version bump (e.g., 0.9.x -> 0.10.0) due to:

  • New dependency (typed-builder)
  • New methods
  • Deprecations (non-breaking)