Skip to content

Commit e97f995

Browse files
feat(enterprise): implement job scheduler commands (#162) (#289)
* feat(enterprise): implement job scheduler commands (#162) - Add Get command to retrieve job scheduler configuration - Add Update command to modify job scheduler settings - Support stdin input with '-' flag for JSON data - Successfully tested against Docker compose environment * docs(enterprise): add documentation for job scheduler commands
1 parent 8b51189 commit e97f995

File tree

9 files changed

+935
-2
lines changed

9 files changed

+935
-2
lines changed

crates/redisctl/src/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,10 @@ pub enum EnterpriseCommands {
995995
#[command(subcommand)]
996996
Crdb(EnterpriseCrdbCommands),
997997

998+
/// Job scheduler operations
999+
#[command(subcommand, name = "job-scheduler")]
1000+
JobScheduler(crate::commands::enterprise::job_scheduler::JobSchedulerCommands),
1001+
9981002
/// Log operations
9991003
#[command(subcommand)]
10001004
Logs(crate::commands::enterprise::logs::LogsCommands),
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use anyhow::Context;
2+
use clap::Subcommand;
3+
4+
use crate::cli::OutputFormat;
5+
use crate::connection::ConnectionManager;
6+
use crate::error::Result as CliResult;
7+
8+
#[derive(Debug, Clone, Subcommand)]
9+
pub enum JobSchedulerCommands {
10+
/// Get job scheduler configuration/settings
11+
Get,
12+
13+
/// Update job scheduler settings
14+
Update {
15+
/// JSON data for configuration update (use @filename or - for stdin)
16+
#[arg(short, long)]
17+
data: String,
18+
},
19+
}
20+
21+
impl JobSchedulerCommands {
22+
#[allow(dead_code)]
23+
pub async fn execute(
24+
&self,
25+
conn_mgr: &ConnectionManager,
26+
profile_name: Option<&str>,
27+
output_format: OutputFormat,
28+
query: Option<&str>,
29+
) -> CliResult<()> {
30+
let client = conn_mgr.create_enterprise_client(profile_name).await?;
31+
32+
match self {
33+
JobSchedulerCommands::Get => {
34+
// Get job scheduler configuration/settings
35+
let response: serde_json::Value = client
36+
.get("/v1/job_scheduler")
37+
.await
38+
.context("Failed to get job scheduler settings")?;
39+
40+
let output_data = if let Some(q) = query {
41+
super::utils::apply_jmespath(&response, q)?
42+
} else {
43+
response
44+
};
45+
super::utils::print_formatted_output(output_data, output_format)?;
46+
}
47+
48+
JobSchedulerCommands::Update { data } => {
49+
let json_data = super::utils::read_json_data(data)?;
50+
51+
let response: serde_json::Value = client
52+
.put("/v1/job_scheduler", &json_data)
53+
.await
54+
.context("Failed to update job scheduler settings")?;
55+
56+
let output_data = if let Some(q) = query {
57+
super::utils::apply_jmespath(&response, q)?
58+
} else {
59+
response
60+
};
61+
super::utils::print_formatted_output(output_data, output_format)?;
62+
}
63+
}
64+
65+
Ok(())
66+
}
67+
}
68+
69+
#[allow(dead_code)]
70+
pub async fn handle_job_scheduler_command(
71+
conn_mgr: &ConnectionManager,
72+
profile_name: Option<&str>,
73+
job_scheduler_cmd: JobSchedulerCommands,
74+
output_format: OutputFormat,
75+
query: Option<&str>,
76+
) -> CliResult<()> {
77+
job_scheduler_cmd
78+
.execute(conn_mgr, profile_name, output_format, query)
79+
.await
80+
}

crates/redisctl/src/commands/enterprise/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub mod crdb;
66
pub mod crdb_impl;
77
pub mod database;
88
pub mod database_impl;
9+
pub mod job_scheduler;
910
pub mod logs;
1011
pub mod logs_impl;
1112
pub mod module;

crates/redisctl/src/commands/enterprise/utils.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,22 @@ pub fn confirm_action(message: &str) -> CliResult<bool> {
9292
}
9393
}
9494

95-
/// Read JSON data from string or file
95+
/// Read JSON data from string, file, or stdin
9696
pub fn read_json_data(data: &str) -> CliResult<Value> {
97-
let json_str = if let Some(file_path) = data.strip_prefix('@') {
97+
let json_str = if data == "-" {
98+
// Read from stdin
99+
use std::io::Read;
100+
let mut buffer = String::new();
101+
std::io::stdin()
102+
.read_to_string(&mut buffer)
103+
.map_err(|e| anyhow::anyhow!("Failed to read from stdin: {}", e))?;
104+
buffer
105+
} else if let Some(file_path) = data.strip_prefix('@') {
106+
// Read from file
98107
std::fs::read_to_string(file_path)
99108
.map_err(|e| anyhow::anyhow!("Failed to read file {}: {}", file_path, e))?
100109
} else {
110+
// Direct JSON string
101111
data.to_string()
102112
};
103113

crates/redisctl/src/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,16 @@ async fn execute_enterprise_command(
244244
)
245245
.await
246246
}
247+
JobScheduler(job_scheduler_cmd) => {
248+
commands::enterprise::job_scheduler::handle_job_scheduler_command(
249+
conn_mgr,
250+
profile,
251+
job_scheduler_cmd.clone(),
252+
output,
253+
query,
254+
)
255+
.await
256+
}
247257
Logs(logs_cmd) => {
248258
commands::enterprise::logs_impl::handle_logs_commands(
249259
conn_mgr, profile, logs_cmd, output, query,

docs/src/SUMMARY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
- [Modules](./enterprise/modules.md)
3636
- [Logs](./enterprise/logs.md)
3737
- [Active-Active (CRDB)](./enterprise/crdb.md)
38+
- [Actions (Tasks)](./enterprise/actions.md)
39+
- [Diagnostics](./enterprise/diagnostics.md)
40+
- [Job Scheduler](./enterprise/job-scheduler.md)
3841
- [Workflows](./enterprise/workflows.md)
3942
- [Raw API Access](./enterprise/api-access.md)
4043

docs/src/enterprise/actions.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Actions (Async Tasks)
2+
3+
Actions in Redis Enterprise represent asynchronous operations or tasks that are running or have completed. The action commands allow you to monitor and manage these background operations.
4+
5+
## Overview
6+
7+
Many Redis Enterprise operations are asynchronous, returning an action ID that can be used to track progress. Actions include database creation/deletion, backup operations, imports/exports, and cluster maintenance tasks.
8+
9+
## Available Commands
10+
11+
### List All Actions
12+
13+
List all actions in the cluster with optional filtering:
14+
15+
```bash
16+
# List all actions
17+
redisctl enterprise action list
18+
19+
# Filter by status
20+
redisctl enterprise action list --status completed
21+
redisctl enterprise action list --status running
22+
23+
# Filter by type
24+
redisctl enterprise action list --type bdb_backup
25+
26+
# Combine filters
27+
redisctl enterprise action list --status running --type bdb_import
28+
29+
# Output as table
30+
redisctl enterprise action list -o table
31+
```
32+
33+
### Get Action Details
34+
35+
Get detailed information about a specific action:
36+
37+
```bash
38+
# Get action by UID
39+
redisctl enterprise action get <action_uid>
40+
41+
# Get action with specific fields using JMESPath
42+
redisctl enterprise action get <action_uid> -q "status"
43+
```
44+
45+
### Check Action Status
46+
47+
Quick status check for an action (returns just the status field):
48+
49+
```bash
50+
redisctl enterprise action status <action_uid>
51+
```
52+
53+
### Cancel Running Action
54+
55+
Cancel a running action:
56+
57+
```bash
58+
redisctl enterprise action cancel <action_uid>
59+
```
60+
61+
### List Actions for Database
62+
63+
List all actions for a specific database:
64+
65+
```bash
66+
redisctl enterprise action list-for-bdb <bdb_uid>
67+
68+
# Filter by status for specific database
69+
redisctl enterprise action list-for-bdb <bdb_uid> --status running
70+
```
71+
72+
## Action Types
73+
74+
Common action types you'll encounter:
75+
76+
- `bdb_create` - Database creation
77+
- `bdb_delete` - Database deletion
78+
- `bdb_update` - Database configuration update
79+
- `bdb_backup` - Database backup operation
80+
- `bdb_import` - Database import operation
81+
- `bdb_export` - Database export operation
82+
- `crdb_create` - Active-Active database creation
83+
- `node_join` - Node joining cluster
84+
- `cluster_recovery` - Cluster recovery operation
85+
86+
## Action Statuses
87+
88+
Actions can have the following statuses:
89+
90+
- `queued` - Action is queued for execution
91+
- `running` - Action is currently executing
92+
- `completed` - Action completed successfully
93+
- `failed` - Action failed with errors
94+
- `canceled` - Action was canceled
95+
96+
## Examples
97+
98+
### Monitor Database Creation
99+
100+
```bash
101+
# Create a database (returns action_uid)
102+
ACTION_UID=$(redisctl enterprise database create --data @db.json -q "action_uid")
103+
104+
# Check status
105+
redisctl enterprise action status $ACTION_UID
106+
107+
# Get full details when complete
108+
redisctl enterprise action get $ACTION_UID
109+
```
110+
111+
### List Recent Failed Actions
112+
113+
```bash
114+
# List failed actions in table format
115+
redisctl enterprise action list --status failed -o table
116+
117+
# Get details of a failed action
118+
redisctl enterprise action get <failed_action_uid> -q "{error: error_message, started: start_time}"
119+
```
120+
121+
### Cancel Long-Running Import
122+
123+
```bash
124+
# List running imports
125+
redisctl enterprise action list --status running --type bdb_import
126+
127+
# Cancel specific import
128+
redisctl enterprise action cancel <import_action_uid>
129+
```
130+
131+
### Monitor All Database Actions
132+
133+
```bash
134+
# Watch all actions for a database
135+
watch -n 5 "redisctl enterprise action list-for-bdb 1 -o table"
136+
```
137+
138+
## Integration with Async Operations
139+
140+
The action commands work seamlessly with the `--wait` flag available on create/update/delete operations:
141+
142+
```bash
143+
# This uses action monitoring internally
144+
redisctl enterprise database create --data @db.json --wait
145+
146+
# Equivalent to manually monitoring:
147+
ACTION_UID=$(redisctl enterprise database create --data @db.json -q "action_uid")
148+
while [ "$(redisctl enterprise action status $ACTION_UID)" = "running" ]; do
149+
sleep 5
150+
done
151+
```
152+
153+
## API Versions
154+
155+
The action commands support both v1 and v2 API endpoints:
156+
- v2 endpoints (`/v2/actions`) are preferred when available
157+
- v1 endpoints (`/v1/actions`) are used as fallback
158+
- Both return the same data structure
159+
160+
## Best Practices
161+
162+
1. **Always check action status** for async operations before proceeding
163+
2. **Use filtering** to reduce output when listing many actions
164+
3. **Save action UIDs** from create/update operations for tracking
165+
4. **Set up monitoring** for critical long-running actions
166+
5. **Check failed actions** for error details to diagnose issues
167+
168+
## Related Commands
169+
170+
- [`enterprise database`](./databases.md) - Database operations that create actions
171+
- [`enterprise cluster`](./cluster.md) - Cluster operations that create actions
172+
- [`enterprise crdb`](./crdb.md) - Active-Active operations that create actions

0 commit comments

Comments
 (0)