Skip to main content

redis_cloud/
tasks.rs

1//! Asynchronous task tracking and management
2//!
3//! This module provides functionality for tracking long-running operations in
4//! Redis Cloud. Many API operations are asynchronous and return a task ID that
5//! can be used to monitor progress and completion status.
6//!
7//! # Overview
8//!
9//! Redis Cloud uses tasks for operations that may take time to complete, such as:
10//! - Creating or deleting subscriptions
11//! - Database creation, updates, and deletion
12//! - Backup and restore operations
13//! - Import/export operations
14//! - Network configuration changes
15//!
16//! # Task Lifecycle
17//!
18//! 1. **Initiated**: Task is created and queued
19//! 2. **Processing**: Task is being executed
20//! 3. **Completed**: Task finished successfully
21//! 4. **Failed**: Task encountered an error
22//!
23//! # Key Features
24//!
25//! - **Task Status**: Check current status of any task
26//! - **Progress Tracking**: Monitor completion percentage for long operations
27//! - **Result Retrieval**: Get operation results once completed
28//! - **Error Information**: Access detailed error messages for failed tasks
29//! - **Task History**: Query historical task information
30//!
31//! # Example Usage
32//!
33//! ```no_run
34//! use redis_cloud::{CloudClient, TaskHandler};
35//!
36//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
37//! let client = CloudClient::builder()
38//!     .api_key("your-api-key")
39//!     .api_secret("your-api-secret")
40//!     .build()?;
41//!
42//! let handler = TaskHandler::new(client);
43//!
44//! // Get task status
45//! let task = handler.get_task_by_id("task-123".to_string()).await?;
46//!
47//! // Check if task is complete
48//! if task.status == Some("completed".to_string()) {
49//!     println!("Task completed successfully");
50//!     if let Some(response) = task.response {
51//!         println!("Result: {:?}", response);
52//!     }
53//! }
54//! # Ok(())
55//! # }
56//! ```
57
58use crate::types::{Link, ProcessorResponse};
59use crate::{CloudClient, Result};
60use serde::{Deserialize, Serialize};
61
62// ============================================================================
63// Models
64// ============================================================================
65
66/// Task state update
67///
68/// Represents the state and result of an asynchronous task
69#[derive(Debug, Clone, Serialize, Deserialize)]
70#[serde(rename_all = "camelCase")]
71pub struct TaskStateUpdate {
72    /// Unique task identifier
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub task_id: Option<String>,
75
76    /// Type of command being executed (e.g., "`CREATE_DATABASE`", "`DELETE_SUBSCRIPTION`")
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub command_type: Option<String>,
79
80    /// Current task status (e.g., "processing", "completed", "failed")
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub status: Option<String>,
83
84    /// Human-readable description of the task
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub description: Option<String>,
87
88    /// Timestamp of last task update
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub timestamp: Option<String>,
91
92    /// Task completion percentage (0-100)
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub progress: Option<f64>,
95
96    /// Result data once task is completed
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub response: Option<ProcessorResponse>,
99
100    /// HATEOAS links for API navigation
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub links: Option<Vec<Link>>,
103}
104
105// ============================================================================
106// Handler
107// ============================================================================
108
109/// Handler for asynchronous task operations
110///
111/// Tracks and manages long-running operations, providing status updates,
112/// progress monitoring, and result retrieval for asynchronous API calls.
113pub struct TasksHandler {
114    client: CloudClient,
115}
116
117impl TasksHandler {
118    /// Create a new handler
119    #[must_use]
120    pub fn new(client: CloudClient) -> Self {
121        Self { client }
122    }
123
124    /// Get tasks
125    /// Gets a list of all currently running tasks for this account.
126    ///
127    /// GET /tasks
128    pub async fn get_all_tasks(&self) -> Result<Vec<TaskStateUpdate>> {
129        self.client.get("/tasks").await
130    }
131
132    /// Get tasks (raw JSON)
133    /// Gets a list of all currently running tasks for this account.
134    ///
135    /// GET /tasks
136    pub async fn get_all_tasks_raw(&self) -> Result<serde_json::Value> {
137        self.client.get_raw("/tasks").await
138    }
139
140    /// Get a single task
141    /// Gets details and status of a single task by the Task ID.
142    ///
143    /// GET /tasks/{taskId}
144    ///
145    /// # Example
146    ///
147    /// ```no_run
148    /// use redis_cloud::CloudClient;
149    ///
150    /// # async fn example() -> redis_cloud::Result<()> {
151    /// let client = CloudClient::builder()
152    ///     .api_key("your-api-key")
153    ///     .api_secret("your-api-secret")
154    ///     .build()?;
155    ///
156    /// let task = client.tasks().get_task_by_id("task-id".to_string()).await?;
157    /// println!("Task status: {:?}", task.status);
158    /// # Ok(())
159    /// # }
160    /// ```
161    pub async fn get_task_by_id(&self, task_id: String) -> Result<TaskStateUpdate> {
162        self.client.get(&format!("/tasks/{task_id}")).await
163    }
164}