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}