Skip to content

Commit f63b2ea

Browse files
chore(deps): bump redis-cloud to v0.10.0 and redis-enterprise to v0.9.1 (#935)
1 parent 4e1fd65 commit f63b2ea

15 files changed

Lines changed: 423 additions & 201 deletions

File tree

Cargo.lock

Lines changed: 13 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,8 @@ pretty_assertions = "1.4"
9999
redis = { version = "0.27", features = ["tokio-comp", "tokio-rustls-comp", "connection-manager", "cluster-async"] }
100100

101101
# External crates (git for dev, version required for crates.io publish)
102-
# TODO: revert to branch = "main" once redis-developer/redis-cloud-rs#103 merges.
103-
redis-cloud = { version = "0.9.5", git = "https://github.com/redis-developer/redis-cloud-rs", branch = "fix/task-error-object-deserialization" }
104-
redis-enterprise = { version = "0.8.5", git = "https://github.com/redis-developer/redis-enterprise-rs", branch = "main" }
102+
redis-cloud = { version = "0.10.0" }
103+
redis-enterprise = { version = "0.9.1" }
105104

106105
# Windows CI workaround - ensure these are available in workspace
107106
shellexpand = "3.1"

crates/redisctl-core/src/enterprise/workflows.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
use crate::enterprise::progress::{EnterpriseProgressCallback, poll_action};
99
use crate::error::Result;
10-
use redis_enterprise::bdb::DatabaseUpgradeRequest;
10+
use redis_enterprise::bdb::{DatabaseActionResponse, DatabaseUpgradeRequest, ModuleUpgrade};
1111
use redis_enterprise::{Database, EnterpriseClient};
1212
use std::time::Duration;
1313

@@ -97,10 +97,19 @@ pub async fn upgrade_module_and_wait(
9797
timeout: Duration,
9898
on_progress: Option<EnterpriseProgressCallback>,
9999
) -> Result<Database> {
100-
// Submit the module upgrade request
100+
// Submit the module upgrade as part of a database upgrade request. The
101+
// dedicated module-upgrade method was folded into the upgrade endpoint
102+
// upstream; modules are now carried in the `modules` field.
103+
let request = DatabaseUpgradeRequest::builder()
104+
.modules(vec![ModuleUpgrade {
105+
module_name: module_name.to_string(),
106+
new_version: Some(new_version.to_string()),
107+
module_args: None,
108+
}])
109+
.build();
101110
let action = client
102111
.databases()
103-
.upgrade(bdb_uid, module_name, new_version)
112+
.upgrade_redis_version(bdb_uid, request)
104113
.await?;
105114

106115
// Poll until completion
@@ -137,13 +146,24 @@ pub async fn backup_database_and_wait(
137146
timeout: Duration,
138147
on_progress: Option<EnterpriseProgressCallback>,
139148
) -> Result<()> {
140-
// Trigger backup
141-
let response = client.databases().backup(bdb_uid).await?;
149+
// Trigger backup. The dedicated `backup` handler method was removed
150+
// upstream; POST the backup action directly (BDB.BACKUP).
151+
let response: DatabaseActionResponse = client
152+
.post(
153+
&format!("/v1/bdbs/{}/actions/backup", bdb_uid),
154+
&serde_json::json!({}),
155+
)
156+
.await?;
142157

143-
// Poll until completion if we got an action_uid
144-
if let Some(action_uid) = response.action_uid {
145-
poll_action(client, &action_uid, timeout, DEFAULT_INTERVAL, on_progress).await?;
146-
}
158+
// Poll until completion
159+
poll_action(
160+
client,
161+
&response.action_uid,
162+
timeout,
163+
DEFAULT_INTERVAL,
164+
on_progress,
165+
)
166+
.await?;
147167

148168
Ok(())
149169
}

crates/redisctl-core/src/progress.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use crate::error::{CoreError, Result};
88
use redis_cloud::tasks::TaskStateUpdate;
9+
use redis_cloud::types::TaskStatus;
910
use redis_cloud::{CloudClient, TaskHandler};
1011
use std::time::{Duration, Instant};
1112

@@ -102,21 +103,24 @@ pub async fn poll_task(
102103
}
103104

104105
let task = handler.get_task_by_id(task_id.to_string()).await?;
105-
let status = task.status.clone().unwrap_or_default();
106+
let status = task.status.clone();
107+
let status_label = task_status_label(status.as_ref());
106108

107109
emit(
108110
&on_progress,
109111
ProgressEvent::Polling {
110112
task_id: task_id.to_string(),
111-
status: status.clone(),
113+
status: status_label.clone(),
112114
elapsed,
113115
},
114116
);
115117

116-
// Check for terminal states (case-insensitive)
117-
match status.to_lowercase().as_str() {
118-
// Success states
119-
"processing-completed" | "completed" | "complete" | "succeeded" | "success" => {
118+
// Check for terminal states. `TaskStatus` only models the two terminal
119+
// states explicitly; everything else (Initialized, Received,
120+
// ProcessingInProgress, and any Unknown wire value) is still in flight.
121+
match status {
122+
// Success
123+
Some(TaskStatus::ProcessingCompleted) => {
120124
let resource_id = task.response.as_ref().and_then(|r| r.resource_id);
121125
emit(
122126
&on_progress,
@@ -127,13 +131,13 @@ pub async fn poll_task(
127131
);
128132
return Ok(task);
129133
}
130-
// Failure states
131-
"processing-error" | "failed" | "error" => {
134+
// Failure
135+
Some(TaskStatus::ProcessingError) => {
132136
let error = task
133137
.response
134138
.as_ref()
135139
.and_then(|r| r.error_message())
136-
.unwrap_or_else(|| format!("Task failed with status: {}", status));
140+
.unwrap_or_else(|| format!("Task failed with status: {}", status_label));
137141

138142
emit(
139143
&on_progress,
@@ -144,19 +148,8 @@ pub async fn poll_task(
144148
);
145149
return Err(CoreError::TaskFailed(error));
146150
}
147-
// Cancelled state
148-
"cancelled" => {
149-
emit(
150-
&on_progress,
151-
ProgressEvent::Failed {
152-
task_id: task_id.to_string(),
153-
error: "Task was cancelled".to_string(),
154-
},
155-
);
156-
return Err(CoreError::TaskFailed("Task was cancelled".to_string()));
157-
}
151+
// Still processing, wait and try again
158152
_ => {
159-
// Still processing, wait and try again
160153
tokio::time::sleep(interval).await;
161154
}
162155
}
@@ -170,6 +163,22 @@ fn emit(callback: &Option<ProgressCallback>, event: ProgressEvent) {
170163
}
171164
}
172165

166+
/// Human-readable label for a task status, mirroring the kebab-case wire form.
167+
///
168+
/// Used for progress events and failure messages. A missing status (or one the
169+
/// client doesn't recognize) is reported as `"unknown"`.
170+
fn task_status_label(status: Option<&TaskStatus>) -> String {
171+
match status {
172+
Some(TaskStatus::Initialized) => "initialized",
173+
Some(TaskStatus::Received) => "received",
174+
Some(TaskStatus::ProcessingInProgress) => "processing-in-progress",
175+
Some(TaskStatus::ProcessingCompleted) => "processing-completed",
176+
Some(TaskStatus::ProcessingError) => "processing-error",
177+
Some(TaskStatus::Unknown) | None => "unknown",
178+
}
179+
.to_string()
180+
}
181+
173182
#[cfg(test)]
174183
mod tests {
175184
use super::*;

crates/redisctl-mcp/src/tools/cloud/account.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use redis_cloud::acl::{
66
AclUserUpdateRequest,
77
};
88
use redis_cloud::cloud_accounts::{CloudAccountCreateRequest, CloudAccountUpdateRequest};
9+
use redis_cloud::types::TaskStatus;
910
use redis_cloud::users::AccountUserUpdateRequest;
1011
use redis_cloud::{
1112
AccountHandler, AclHandler, CloudAccountHandler, CostReportCreateRequest, CostReportHandler,
@@ -688,20 +689,13 @@ cloud_tool!(read_only, wait_for_cloud_task, "wait_for_cloud_task",
688689
.await
689690
.tool_context("Failed to get task status")?;
690691

691-
// Check for terminal states
692-
if let Some(ref status) = task.status {
693-
let s = status.to_lowercase();
694-
if matches!(
695-
s.as_str(),
696-
"completed"
697-
| "failed"
698-
| "error"
699-
| "success"
700-
| "cancelled"
701-
| "aborted"
702-
) {
703-
return CallToolResult::from_serialize(&task);
704-
}
692+
// Check for terminal states. `TaskStatus` models only the two
693+
// terminal states explicitly; everything else is still in flight.
694+
if matches!(
695+
task.status,
696+
Some(TaskStatus::ProcessingCompleted) | Some(TaskStatus::ProcessingError)
697+
) {
698+
return CallToolResult::from_serialize(&task);
705699
}
706700

707701
// Check timeout

0 commit comments

Comments
 (0)