redis_cloud/flexible/
databases.rs

1//! Database management operations for Pro subscriptions
2//!
3//! This module provides comprehensive database management functionality for Redis Cloud
4//! Pro subscriptions, including creation, configuration, backup, import/export, and
5//! monitoring capabilities.
6//!
7//! # Overview
8//!
9//! Pro databases offer the full range of Redis Cloud features including high availability,
10//! auto-scaling, clustering, modules, and advanced data persistence options. They can be
11//! deployed across multiple cloud providers and regions.
12//!
13//! # Key Features
14//!
15//! - **Database Lifecycle**: Create, update, delete, and manage databases
16//! - **Backup & Restore**: Automated and on-demand backup operations
17//! - **Import/Export**: Import data from RDB files or other Redis instances
18//! - **Modules**: Support for RedisJSON, RediSearch, RedisGraph, RedisTimeSeries, RedisBloom
19//! - **High Availability**: Replication, auto-failover, and clustering support
20//! - **Monitoring**: Metrics, alerts, and performance insights
21//! - **Security**: TLS, password protection, and ACL support
22//!
23//! # Database Configuration Options
24//!
25//! - Memory limits from 250MB to 500GB+
26//! - Support for Redis OSS Cluster API
27//! - Data persistence: AOF, snapshot, or both
28//! - Data eviction policies
29//! - Replication and clustering
30//! - Custom Redis versions
31//!
32//! # Example Usage
33//!
34//! ```no_run
35//! use redis_cloud::{CloudClient, DatabaseHandler};
36//!
37//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
38//! let client = CloudClient::builder()
39//!     .api_key("your-api-key")
40//!     .api_secret("your-api-secret")
41//!     .build()?;
42//!
43//! let handler = DatabaseHandler::new(client);
44//!
45//! // List all databases in a subscription (subscription ID 123)
46//! let databases = handler.get_subscription_databases(123, None, None).await?;
47//!
48//! // Get specific database details
49//! let database = handler.get_subscription_database_by_id(123, 456).await?;
50//! # Ok(())
51//! # }
52//! ```
53
54use crate::{CloudClient, Result};
55use serde::{Deserialize, Serialize};
56use serde_json::Value;
57use std::collections::HashMap;
58
59// ============================================================================
60// Models
61// ============================================================================
62
63/// RedisLabs Account Subscription Databases information
64///
65/// Response from GET /subscriptions/{subscriptionId}/databases
66#[derive(Debug, Clone, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct AccountSubscriptionDatabases {
69    /// Account ID
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub account_id: Option<i32>,
72
73    /// Subscription information with nested databases array
74    /// Contains subscriptionId, numberOfDatabases, and databases array
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub subscription: Option<Value>,
77
78    /// HATEOAS links for API navigation
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub links: Option<Vec<HashMap<String, Value>>>,
81
82    /// Only for truly unknown/future API fields
83    #[serde(flatten)]
84    pub extra: Value,
85}
86
87/// ProcessorResponse
88#[derive(Debug, Clone, Serialize, Deserialize)]
89#[serde(rename_all = "camelCase")]
90pub struct ProcessorResponse {
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub resource_id: Option<i32>,
93
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub additional_resource_id: Option<i32>,
96
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub resource: Option<HashMap<String, Value>>,
99
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub error: Option<String>,
102
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub additional_info: Option<String>,
105
106    /// Additional fields from the API
107    #[serde(flatten)]
108    pub extra: Value,
109}
110
111/// Optional. Expected read and write throughput for this region.
112#[derive(Debug, Clone, Serialize, Deserialize)]
113#[serde(rename_all = "camelCase")]
114pub struct LocalThroughput {
115    /// Specify one of the selected cloud provider regions for the subscription.
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub region: Option<String>,
118
119    /// Write operations for this region per second. Default: 1000 ops/sec
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub write_operations_per_second: Option<i64>,
122
123    /// Read operations for this region per second. Default: 1000 ops/sec
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub read_operations_per_second: Option<i64>,
126
127    /// Additional fields from the API
128    #[serde(flatten)]
129    pub extra: Value,
130}
131
132/// Database tag update request message
133#[derive(Debug, Clone, Serialize, Deserialize)]
134#[serde(rename_all = "camelCase")]
135pub struct DatabaseTagUpdateRequest {
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub subscription_id: Option<i32>,
138
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub database_id: Option<i32>,
141
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub key: Option<String>,
144
145    /// Database tag value
146    pub value: String,
147
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub command_type: Option<String>,
150
151    /// Additional fields from the API
152    #[serde(flatten)]
153    pub extra: Value,
154}
155
156/// Database tag
157#[derive(Debug, Clone, Serialize, Deserialize)]
158#[serde(rename_all = "camelCase")]
159pub struct Tag {
160    /// Database tag key.
161    pub key: String,
162
163    /// Database tag value.
164    pub value: String,
165
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub command_type: Option<String>,
168
169    /// Additional fields from the API
170    #[serde(flatten)]
171    pub extra: Value,
172}
173
174/// Active-Active database flush request message
175#[derive(Debug, Clone, Serialize, Deserialize)]
176#[serde(rename_all = "camelCase")]
177pub struct CrdbFlushRequest {
178    #[serde(skip_serializing_if = "Option::is_none")]
179    pub subscription_id: Option<i32>,
180
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub database_id: Option<i32>,
183
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub command_type: Option<String>,
186
187    /// Additional fields from the API
188    #[serde(flatten)]
189    pub extra: Value,
190}
191
192/// Database certificate
193#[derive(Debug, Clone, Serialize, Deserialize)]
194#[serde(rename_all = "camelCase")]
195pub struct DatabaseCertificate {
196    /// An X.509 PEM (base64) encoded server certificate with new line characters replaced by '\n'.
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub public_certificate_pem_string: Option<String>,
199
200    /// Additional fields from the API
201    #[serde(flatten)]
202    pub extra: Value,
203}
204
205/// Database tags update request message
206#[derive(Debug, Clone, Serialize, Deserialize)]
207#[serde(rename_all = "camelCase")]
208pub struct DatabaseTagsUpdateRequest {
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub subscription_id: Option<i32>,
211
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub database_id: Option<i32>,
214
215    /// List of database tags.
216    pub tags: Vec<Tag>,
217
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub command_type: Option<String>,
220
221    /// Additional fields from the API
222    #[serde(flatten)]
223    pub extra: Value,
224}
225
226/// Optional. This database will be a replica of the specified Redis databases, provided as a list of objects with endpoint and certificate details.
227#[derive(Debug, Clone, Serialize, Deserialize)]
228#[serde(rename_all = "camelCase")]
229pub struct DatabaseSyncSourceSpec {
230    /// Redis URI of a source database. Example format: 'redis://user:password@host:port'. If the URI provided is a Redis Cloud database, only host and port should be provided. Example: 'redis://endpoint1:6379'.
231    pub endpoint: String,
232
233    /// Defines if encryption should be used to connect to the sync source. If not set the source is a Redis Cloud database, it will automatically detect if the source uses encryption.
234    #[serde(skip_serializing_if = "Option::is_none")]
235    pub encryption: Option<bool>,
236
237    /// TLS/SSL certificate chain of the sync source. If not set and the source is a Redis Cloud database, it will automatically detect the certificate to use.
238    #[serde(skip_serializing_if = "Option::is_none")]
239    pub server_cert: Option<String>,
240
241    /// Additional fields from the API
242    #[serde(flatten)]
243    pub extra: Value,
244}
245
246/// Optional. A list of client TLS/SSL certificates. If specified, mTLS authentication will be required to authenticate user connections. If set to an empty list, TLS client certificates will be removed and mTLS will not be required. TLS connection may still apply, depending on the value of 'enableTls'.
247#[derive(Debug, Clone, Serialize, Deserialize)]
248#[serde(rename_all = "camelCase")]
249pub struct DatabaseCertificateSpec {
250    /// Client certificate public key in PEM format, with new line characters replaced with '\n'.
251    pub public_certificate_pem_string: String,
252
253    /// Additional fields from the API
254    #[serde(flatten)]
255    pub extra: Value,
256}
257
258/// Database tag
259#[derive(Debug, Clone, Serialize, Deserialize)]
260#[serde(rename_all = "camelCase")]
261pub struct CloudTag {
262    #[serde(skip_serializing_if = "Option::is_none")]
263    pub key: Option<String>,
264
265    #[serde(skip_serializing_if = "Option::is_none")]
266    pub value: Option<String>,
267
268    #[serde(skip_serializing_if = "Option::is_none")]
269    pub created_at: Option<String>,
270
271    #[serde(skip_serializing_if = "Option::is_none")]
272    pub updated_at: Option<String>,
273
274    /// HATEOAS links
275    #[serde(skip_serializing_if = "Option::is_none")]
276    pub links: Option<Vec<HashMap<String, Value>>>,
277
278    /// Additional fields from the API
279    #[serde(flatten)]
280    pub extra: Value,
281}
282
283/// BdbVersionUpgradeStatus
284#[derive(Debug, Clone, Serialize, Deserialize)]
285#[serde(rename_all = "camelCase")]
286pub struct BdbVersionUpgradeStatus {
287    #[serde(skip_serializing_if = "Option::is_none")]
288    pub database_id: Option<i32>,
289
290    #[serde(skip_serializing_if = "Option::is_none")]
291    pub target_redis_version: Option<String>,
292
293    #[serde(skip_serializing_if = "Option::is_none")]
294    pub progress: Option<f64>,
295
296    #[serde(skip_serializing_if = "Option::is_none")]
297    pub upgrade_status: Option<String>,
298
299    /// Additional fields from the API
300    #[serde(flatten)]
301    pub extra: Value,
302}
303
304/// Active-Active database update local properties request message
305#[derive(Debug, Clone, Serialize, Deserialize)]
306#[serde(rename_all = "camelCase")]
307pub struct CrdbUpdatePropertiesRequest {
308    #[serde(skip_serializing_if = "Option::is_none")]
309    pub subscription_id: Option<i32>,
310
311    #[serde(skip_serializing_if = "Option::is_none")]
312    pub database_id: Option<i32>,
313
314    /// Optional. Updated database name. Database name is limited to 40 characters or less and must include only letters, digits, and hyphens ('-'). It must start with a letter and end with a letter or digit.
315    #[serde(skip_serializing_if = "Option::is_none")]
316    pub name: Option<String>,
317
318    /// Optional. When 'false': Creates a deployment plan and deploys it, updating any resources required by the plan. When 'true': creates a read-only deployment plan and does not update any resources. Default: 'false'
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub dry_run: Option<bool>,
321
322    /// Optional. Total memory in GB, including replication and other overhead. You cannot set both datasetSizeInGb and totalMemoryInGb.
323    #[serde(skip_serializing_if = "Option::is_none")]
324    pub memory_limit_in_gb: Option<f64>,
325
326    /// Optional. The maximum amount of data in the dataset for this database in GB. You cannot set both datasetSizeInGb and totalMemoryInGb. If ‘replication’ is 'true', the database’s total memory will be twice as large as the datasetSizeInGb.If ‘replication’ is false, the database’s total memory will be the datasetSizeInGb value.
327    #[serde(skip_serializing_if = "Option::is_none")]
328    pub dataset_size_in_gb: Option<f64>,
329
330    /// Optional. Support Redis [OSS Cluster API](https://redis.io/docs/latest/operate/rc/databases/configuration/clustering/#oss-cluster-api). Default: 'false'
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub support_oss_cluster_api: Option<bool>,
333
334    /// Optional. If set to 'true', the database will use the external endpoint for OSS Cluster API. This setting blocks the database's private endpoint. Can only be set if 'supportOSSClusterAPI' is 'true'.
335    #[serde(skip_serializing_if = "Option::is_none")]
336    pub use_external_endpoint_for_oss_cluster_api: Option<bool>,
337
338    /// Optional. A public key client TLS/SSL certificate with new line characters replaced with '\n'. If specified, mTLS authentication will be required to authenticate user connections if it is not already required. If set to an empty string, TLS client certificates will be removed and mTLS will not be required. TLS connection may still apply, depending on the value of 'enableTls'.
339    #[serde(skip_serializing_if = "Option::is_none")]
340    pub client_ssl_certificate: Option<String>,
341
342    /// Optional. A list of client TLS/SSL certificates. If specified, mTLS authentication will be required to authenticate user connections. If set to an empty list, TLS client certificates will be removed and mTLS will not be required. TLS connection may still apply, depending on the value of 'enableTls'.
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub client_tls_certificates: Option<Vec<DatabaseCertificateSpec>>,
345
346    /// Optional. When 'true', requires TLS authentication for all connections - mTLS with valid clientTlsCertificates, regular TLS when clientTlsCertificates is not provided. If enableTls is set to 'false' while mTLS is required, it will remove the mTLS requirement and erase previously provided clientTlsCertificates.
347    #[serde(skip_serializing_if = "Option::is_none")]
348    pub enable_tls: Option<bool>,
349
350    /// Optional. Type and rate of data persistence in all regions that don't set local 'dataPersistence'.
351    #[serde(skip_serializing_if = "Option::is_none")]
352    pub global_data_persistence: Option<String>,
353
354    /// Optional. Changes the password used to access the database in all regions that don't set a local 'password'.
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub global_password: Option<String>,
357
358    /// Optional. List of source IP addresses or subnet masks to allow in all regions that don't set local 'sourceIp' settings. If set, Redis clients will be able to connect to this database only from within the specified source IP addresses ranges. Example: ['192.168.10.0/32', '192.168.12.0/24']
359    #[serde(skip_serializing_if = "Option::is_none")]
360    pub global_source_ip: Option<Vec<String>>,
361
362    /// Optional. Redis database alert settings in all regions that don't set local 'alerts'.
363    #[serde(skip_serializing_if = "Option::is_none")]
364    pub global_alerts: Option<Vec<DatabaseAlertSpec>>,
365
366    /// Optional. A list of regions and local settings to update.
367    #[serde(skip_serializing_if = "Option::is_none")]
368    pub regions: Option<Vec<LocalRegionProperties>>,
369
370    /// Optional. Data eviction policy.
371    #[serde(skip_serializing_if = "Option::is_none")]
372    pub data_eviction_policy: Option<String>,
373
374    #[serde(skip_serializing_if = "Option::is_none")]
375    pub command_type: Option<String>,
376
377    /// Additional fields from the API
378    #[serde(flatten)]
379    pub extra: Value,
380}
381
382/// Database slowlog entry
383#[derive(Debug, Clone, Serialize, Deserialize)]
384#[serde(rename_all = "camelCase")]
385pub struct DatabaseSlowLogEntry {
386    #[serde(skip_serializing_if = "Option::is_none")]
387    pub id: Option<i32>,
388
389    #[serde(skip_serializing_if = "Option::is_none")]
390    pub start_time: Option<String>,
391
392    #[serde(skip_serializing_if = "Option::is_none")]
393    pub duration: Option<i32>,
394
395    #[serde(skip_serializing_if = "Option::is_none")]
396    pub arguments: Option<String>,
397
398    /// Additional fields from the API
399    #[serde(flatten)]
400    pub extra: Value,
401}
402
403/// Database tag
404#[derive(Debug, Clone, Serialize, Deserialize)]
405#[serde(rename_all = "camelCase")]
406pub struct DatabaseTagCreateRequest {
407    /// Database tag key.
408    pub key: String,
409
410    /// Database tag value.
411    pub value: String,
412
413    #[serde(skip_serializing_if = "Option::is_none")]
414    pub subscription_id: Option<i32>,
415
416    #[serde(skip_serializing_if = "Option::is_none")]
417    pub database_id: Option<i32>,
418
419    #[serde(skip_serializing_if = "Option::is_none")]
420    pub command_type: Option<String>,
421
422    /// Additional fields from the API
423    #[serde(flatten)]
424    pub extra: Value,
425}
426
427/// Optional. Throughput measurement method.
428#[derive(Debug, Clone, Serialize, Deserialize)]
429pub struct DatabaseThroughputSpec {
430    /// Throughput measurement method. Use 'operations-per-second' for all new databases.
431    pub by: String,
432
433    /// Throughput value in the selected measurement method.
434    pub value: i64,
435
436    /// Additional fields from the API
437    #[serde(flatten)]
438    pub extra: Value,
439}
440
441/// Optional. Changes Remote backup configuration details.
442#[derive(Debug, Clone, Serialize, Deserialize)]
443#[serde(rename_all = "camelCase")]
444pub struct DatabaseBackupConfig {
445    /// Optional. Determine if backup should be active. Default: null
446    #[serde(skip_serializing_if = "Option::is_none")]
447    pub active: Option<bool>,
448
449    /// Required when active is 'true'. Defines the interval between backups. Format: 'every-x-hours', where x is one of 24, 12, 6, 4, 2, or 1. Example: "every-4-hours"
450    #[serde(skip_serializing_if = "Option::is_none")]
451    pub interval: Option<String>,
452
453    #[serde(skip_serializing_if = "Option::is_none")]
454    pub backup_interval: Option<String>,
455
456    /// Optional. Hour when the backup starts. Available only for "every-12-hours" and "every-24-hours" backup intervals. Specified as an hour in 24-hour UTC time. Example: "14:00" is 2 PM UTC.
457    #[serde(skip_serializing_if = "Option::is_none")]
458    pub time_utc: Option<String>,
459
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub database_backup_time_utc: Option<String>,
462
463    /// Required when active is 'true'. Type of storage to host backup files. Can be "aws-s3", "google-blob-storage", "azure-blob-storage", or "ftp". See [Set up backup storage locations](https://redis.io/docs/latest/operate/rc/databases/back-up-data/#set-up-backup-storage-locations) to learn how to set up backup storage locations.
464    #[serde(skip_serializing_if = "Option::is_none")]
465    pub storage_type: Option<String>,
466
467    #[serde(skip_serializing_if = "Option::is_none")]
468    pub backup_storage_type: Option<String>,
469
470    /// Required when active is 'true'. Path to the backup storage location.
471    #[serde(skip_serializing_if = "Option::is_none")]
472    pub storage_path: Option<String>,
473
474    /// Additional fields from the API
475    #[serde(flatten)]
476    pub extra: Value,
477}
478
479/// Optional. Redis advanced capabilities (also known as modules) to be provisioned in the database. Use GET /database-modules to get a list of available advanced capabilities.
480#[derive(Debug, Clone, Serialize, Deserialize)]
481pub struct DatabaseModuleSpec {
482    /// Redis advanced capability name. Use GET /database-modules for a list of available capabilities.
483    pub name: String,
484
485    /// Optional. Redis advanced capability parameters. Use GET /database-modules to get the available capabilities and their parameters.
486    #[serde(skip_serializing_if = "Option::is_none")]
487    pub parameters: Option<HashMap<String, Value>>,
488
489    /// Additional fields from the API
490    #[serde(flatten)]
491    pub extra: Value,
492}
493
494/// Optional. Changes Replica Of (also known as Active-Passive) configuration details.
495#[derive(Debug, Clone, Serialize, Deserialize)]
496#[serde(rename_all = "camelCase")]
497pub struct ReplicaOfSpec {
498    /// Optional. This database will be a replica of the specified Redis databases, provided as a list of objects with endpoint and certificate details.
499    pub sync_sources: Vec<DatabaseSyncSourceSpec>,
500
501    /// Additional fields from the API
502    #[serde(flatten)]
503    pub extra: Value,
504}
505
506/// Database backup request message
507#[derive(Debug, Clone, Serialize, Deserialize)]
508#[serde(rename_all = "camelCase")]
509pub struct DatabaseBackupRequest {
510    #[serde(skip_serializing_if = "Option::is_none")]
511    pub subscription_id: Option<i32>,
512
513    #[serde(skip_serializing_if = "Option::is_none")]
514    pub database_id: Option<i32>,
515
516    /// Required for Active-Active databases. Name of the cloud provider region to back up. When backing up an Active-Active database, you must back up each region separately.
517    #[serde(skip_serializing_if = "Option::is_none")]
518    pub region_name: Option<String>,
519
520    /// Optional. Manually backs up data to this location, instead of the set 'remoteBackup' location.
521    #[serde(skip_serializing_if = "Option::is_none")]
522    pub adhoc_backup_path: Option<String>,
523
524    #[serde(skip_serializing_if = "Option::is_none")]
525    pub command_type: Option<String>,
526
527    /// Additional fields from the API
528    #[serde(flatten)]
529    pub extra: Value,
530}
531
532/// Database
533///
534/// Represents a Redis Cloud database with all known API fields as first-class struct members.
535/// The `extra` field is reserved only for truly unknown/future fields that may be added to the API.
536#[derive(Debug, Clone, Serialize, Deserialize)]
537#[serde(rename_all = "camelCase")]
538pub struct Database {
539    /// Database ID - always present in API responses
540    pub database_id: i32,
541
542    /// Database name
543    #[serde(skip_serializing_if = "Option::is_none")]
544    pub name: Option<String>,
545
546    /// Database status (e.g., "active", "pending", "error", "draft")
547    #[serde(skip_serializing_if = "Option::is_none")]
548    pub status: Option<String>,
549
550    /// Cloud provider (e.g., "AWS", "GCP", "Azure")
551    #[serde(skip_serializing_if = "Option::is_none")]
552    pub provider: Option<String>,
553
554    /// Cloud region (e.g., "us-east-1", "europe-west1")
555    #[serde(skip_serializing_if = "Option::is_none")]
556    pub region: Option<String>,
557
558    /// Redis version (e.g., "7.2", "7.0")
559    #[serde(skip_serializing_if = "Option::is_none")]
560    pub redis_version: Option<String>,
561
562    /// Redis Serialization Protocol version
563    #[serde(skip_serializing_if = "Option::is_none")]
564    pub resp_version: Option<String>,
565
566    /// Total memory limit in GB (including replication and overhead)
567    #[serde(skip_serializing_if = "Option::is_none")]
568    pub memory_limit_in_gb: Option<f64>,
569
570    /// Dataset size in GB (actual data size, excluding replication)
571    #[serde(skip_serializing_if = "Option::is_none")]
572    pub dataset_size_in_gb: Option<f64>,
573
574    /// Memory used in MB
575    #[serde(skip_serializing_if = "Option::is_none")]
576    pub memory_used_in_mb: Option<f64>,
577
578    /// Private endpoint for database connections
579    #[serde(skip_serializing_if = "Option::is_none")]
580    pub private_endpoint: Option<String>,
581
582    /// Public endpoint for database connections (if enabled)
583    #[serde(skip_serializing_if = "Option::is_none")]
584    pub public_endpoint: Option<String>,
585
586    /// TCP port on which the database is available
587    #[serde(skip_serializing_if = "Option::is_none")]
588    pub port: Option<i32>,
589
590    /// Data eviction policy (e.g., "volatile-lru", "allkeys-lru", "noeviction")
591    #[serde(skip_serializing_if = "Option::is_none")]
592    pub data_eviction_policy: Option<String>,
593
594    /// Data persistence setting (e.g., "aof-every-1-sec", "snapshot-every-1-hour", "none")
595    #[serde(skip_serializing_if = "Option::is_none")]
596    pub data_persistence: Option<String>,
597
598    /// Whether replication is enabled
599    #[serde(skip_serializing_if = "Option::is_none")]
600    pub replication: Option<bool>,
601
602    /// Protocol used (e.g., "redis", "memcached")
603    #[serde(skip_serializing_if = "Option::is_none")]
604    pub protocol: Option<String>,
605
606    /// Support for OSS Cluster API
607    #[serde(skip_serializing_if = "Option::is_none")]
608    pub support_oss_cluster_api: Option<bool>,
609
610    /// Use external endpoint for OSS Cluster API
611    #[serde(skip_serializing_if = "Option::is_none")]
612    pub use_external_endpoint_for_oss_cluster_api: Option<bool>,
613
614    /// Whether TLS is enabled for connections
615    #[serde(skip_serializing_if = "Option::is_none")]
616    pub enable_tls: Option<bool>,
617
618    /// Throughput measurement configuration
619    #[serde(skip_serializing_if = "Option::is_none")]
620    pub throughput_measurement: Option<DatabaseThroughputSpec>,
621
622    /// Local throughput measurement for Active-Active databases
623    #[serde(skip_serializing_if = "Option::is_none")]
624    pub local_throughput_measurement: Option<Vec<LocalThroughput>>,
625
626    /// Average item size in bytes (for Auto Tiering)
627    #[serde(skip_serializing_if = "Option::is_none")]
628    pub average_item_size_in_bytes: Option<i64>,
629
630    /// Path to periodic backup storage location
631    #[serde(skip_serializing_if = "Option::is_none")]
632    pub periodic_backup_path: Option<String>,
633
634    /// Remote backup configuration
635    #[serde(skip_serializing_if = "Option::is_none")]
636    pub remote_backup: Option<Value>,
637
638    /// List of source IP addresses or subnet masks allowed to connect
639    #[serde(skip_serializing_if = "Option::is_none")]
640    pub source_ip: Option<Vec<String>>,
641
642    /// Client TLS/SSL certificate (deprecated, use client_tls_certificates)
643    #[serde(skip_serializing_if = "Option::is_none")]
644    pub client_ssl_certificate: Option<String>,
645
646    /// List of client TLS/SSL certificates for mTLS authentication
647    #[serde(skip_serializing_if = "Option::is_none")]
648    pub client_tls_certificates: Option<Vec<Value>>,
649
650    /// Database password (masked in responses for security)
651    #[serde(skip_serializing_if = "Option::is_none")]
652    pub password: Option<String>,
653
654    /// Memcached SASL username
655    #[serde(skip_serializing_if = "Option::is_none")]
656    pub sasl_username: Option<String>,
657
658    /// Memcached SASL password (masked in responses)
659    #[serde(skip_serializing_if = "Option::is_none")]
660    pub sasl_password: Option<String>,
661
662    /// Database alert configurations
663    #[serde(skip_serializing_if = "Option::is_none")]
664    pub alerts: Option<Vec<Value>>,
665
666    /// Redis modules/capabilities enabled on this database
667    #[serde(skip_serializing_if = "Option::is_none")]
668    pub modules: Option<Vec<Value>>,
669
670    /// Database hashing policy for clustering
671    #[serde(skip_serializing_if = "Option::is_none")]
672    pub sharding_type: Option<String>,
673
674    /// Query performance factor (for search and query databases)
675    #[serde(skip_serializing_if = "Option::is_none")]
676    pub query_performance_factor: Option<String>,
677
678    /// List of databases this database is a replica of
679    #[serde(skip_serializing_if = "Option::is_none")]
680    pub replica_of: Option<Vec<String>>,
681
682    /// Replica configuration
683    #[serde(skip_serializing_if = "Option::is_none")]
684    pub replica: Option<Value>,
685
686    /// Whether default Redis user is enabled
687    #[serde(skip_serializing_if = "Option::is_none")]
688    pub enable_default_user: Option<bool>,
689
690    /// Timestamp when database was activated
691    #[serde(skip_serializing_if = "Option::is_none")]
692    pub activated: Option<String>,
693
694    /// Timestamp of last modification
695    #[serde(skip_serializing_if = "Option::is_none")]
696    pub last_modified: Option<String>,
697
698    /// HATEOAS links for API navigation
699    #[serde(skip_serializing_if = "Option::is_none")]
700    pub links: Option<Vec<HashMap<String, Value>>>,
701
702    /// Only for truly unknown/future API fields. All documented fields should be first-class members above.
703    #[serde(flatten)]
704    pub extra: Value,
705}
706
707/// Optional. Changes Redis database alert details.
708#[derive(Debug, Clone, Serialize, Deserialize)]
709pub struct DatabaseAlertSpec {
710    /// Alert type. Available options depend on Plan type. See [Configure alerts](https://redis.io/docs/latest/operate/rc/databases/monitor-performance/#configure-metric-alerts) for more information.
711    pub name: String,
712
713    /// Value over which an alert will be sent. Default values and range depend on the alert type. See [Configure alerts](https://redis.io/docs/latest/operate/rc/databases/monitor-performance/#configure-metric-alerts) for more information.
714    pub value: i32,
715
716    /// Additional fields from the API
717    #[serde(flatten)]
718    pub extra: Value,
719}
720
721/// Request structure for creating a new Pro database
722///
723/// Contains all configuration options for creating a database in a Pro subscription,
724/// including memory settings, replication, persistence, modules, and networking.
725#[derive(Debug, Clone, Serialize, Deserialize)]
726#[serde(rename_all = "camelCase")]
727pub struct DatabaseCreateRequest {
728    #[serde(skip_serializing_if = "Option::is_none")]
729    pub subscription_id: Option<i32>,
730
731    /// Optional. When 'false': Creates a deployment plan and deploys it, creating any resources required by the plan. When 'true': creates a read-only deployment plan and does not create any resources. Default: 'false'
732    #[serde(skip_serializing_if = "Option::is_none")]
733    pub dry_run: Option<bool>,
734
735    /// Name of the database. Database name is limited to 40 characters or less and must include only letters, digits, and hyphens ('-'). It must start with a letter and end with a letter or digit.
736    pub name: String,
737
738    /// Optional. Database protocol. Only set to 'memcached' if you have a legacy application. Default: 'redis'
739    #[serde(skip_serializing_if = "Option::is_none")]
740    pub protocol: Option<String>,
741
742    /// Optional. TCP port on which the database is available (10000-19999). Generated automatically if not set.
743    #[serde(skip_serializing_if = "Option::is_none")]
744    pub port: Option<i32>,
745
746    /// Optional. Total memory in GB, including replication and other overhead. You cannot set both datasetSizeInGb and totalMemoryInGb.
747    #[serde(skip_serializing_if = "Option::is_none")]
748    pub memory_limit_in_gb: Option<f64>,
749
750    /// Optional. The maximum amount of data in the dataset for this database in GB. You cannot set both datasetSizeInGb and totalMemoryInGb. If ‘replication’ is 'true', the database’s total memory will be twice as large as the datasetSizeInGb. If ‘replication’ is false, the database’s total memory will be the datasetSizeInGb value.
751    #[serde(skip_serializing_if = "Option::is_none")]
752    pub dataset_size_in_gb: Option<f64>,
753
754    /// Optional. If specified, redisVersion defines the Redis database version. If omitted, the Redis version will be set to the default version (available in 'GET /subscriptions/redis-versions')
755    #[serde(skip_serializing_if = "Option::is_none")]
756    pub redis_version: Option<String>,
757
758    /// Optional. Redis Serialization Protocol version. Must be compatible with Redis version.
759    #[serde(skip_serializing_if = "Option::is_none")]
760    pub resp_version: Option<String>,
761
762    /// Optional. Support [OSS Cluster API](https://redis.io/docs/latest/operate/rc/databases/configuration/clustering/#oss-cluster-api). Default: 'false'
763    #[serde(skip_serializing_if = "Option::is_none")]
764    pub support_oss_cluster_api: Option<bool>,
765
766    /// Optional. If set to 'true', the database will use the external endpoint for OSS Cluster API. This setting blocks the database's private endpoint. Can only be set if 'supportOSSClusterAPI' is 'true'. Default: 'false'
767    #[serde(skip_serializing_if = "Option::is_none")]
768    pub use_external_endpoint_for_oss_cluster_api: Option<bool>,
769
770    /// Optional. Type and rate of data persistence in persistent storage. Default: 'none'
771    #[serde(skip_serializing_if = "Option::is_none")]
772    pub data_persistence: Option<String>,
773
774    /// Optional. Data eviction policy. Default: 'volatile-lru'
775    #[serde(skip_serializing_if = "Option::is_none")]
776    pub data_eviction_policy: Option<String>,
777
778    /// Optional. Sets database replication. Default: 'true'
779    #[serde(skip_serializing_if = "Option::is_none")]
780    pub replication: Option<bool>,
781
782    /// Optional. This database will be a replica of the specified Redis databases provided as one or more URI(s). Example: 'redis://user:password@host:port'. If the URI provided is a Redis Cloud database, only host and port should be provided. Example: ['redis://endpoint1:6379', 'redis://endpoint2:6380'].
783    #[serde(skip_serializing_if = "Option::is_none")]
784    pub replica_of: Option<Vec<String>>,
785
786    #[serde(skip_serializing_if = "Option::is_none")]
787    pub replica: Option<ReplicaOfSpec>,
788
789    #[serde(skip_serializing_if = "Option::is_none")]
790    pub throughput_measurement: Option<DatabaseThroughputSpec>,
791
792    /// Optional. Expected throughput per region for an Active-Active database. Default: 1000 read and write ops/sec for each region
793    #[serde(skip_serializing_if = "Option::is_none")]
794    pub local_throughput_measurement: Option<Vec<LocalThroughput>>,
795
796    /// Optional. Relevant only to ram-and-flash (also known as Auto Tiering) subscriptions. Estimated average size in bytes of the items stored in the database. Default: 1000
797    #[serde(skip_serializing_if = "Option::is_none")]
798    pub average_item_size_in_bytes: Option<i64>,
799
800    /// Optional. The path to a backup storage location. If specified, the database will back up every 24 hours to this location, and you can manually back up the database to this location at any time.
801    #[serde(skip_serializing_if = "Option::is_none")]
802    pub periodic_backup_path: Option<String>,
803
804    #[serde(skip_serializing_if = "Option::is_none")]
805    pub remote_backup: Option<DatabaseBackupConfig>,
806
807    /// Optional. List of source IP addresses or subnet masks to allow. If specified, Redis clients will be able to connect to this database only from within the specified source IP addresses ranges. Example: '['192.168.10.0/32', '192.168.12.0/24']'
808    #[serde(skip_serializing_if = "Option::is_none")]
809    pub source_ip: Option<Vec<String>>,
810
811    /// Optional. A public key client TLS/SSL certificate with new line characters replaced with '\n'. If specified, mTLS authentication will be required to authenticate user connections. Default: 'null'
812    #[serde(skip_serializing_if = "Option::is_none")]
813    pub client_ssl_certificate: Option<String>,
814
815    /// Optional. A list of client TLS/SSL certificates. If specified, mTLS authentication will be required to authenticate user connections.
816    #[serde(skip_serializing_if = "Option::is_none")]
817    pub client_tls_certificates: Option<Vec<DatabaseCertificateSpec>>,
818
819    /// Optional. When 'true', requires TLS authentication for all connections - mTLS with valid clientTlsCertificates, regular TLS when clientTlsCertificates is not provided. Default: 'false'
820    #[serde(skip_serializing_if = "Option::is_none")]
821    pub enable_tls: Option<bool>,
822
823    /// Optional. Password to access the database. If not set, a random 32-character alphanumeric password will be automatically generated. Can only be set if 'protocol' is 'redis'.
824    #[serde(skip_serializing_if = "Option::is_none")]
825    pub password: Option<String>,
826
827    /// Optional. Memcached (SASL) Username to access the database. If not set, the username will be set to a 'mc-' prefix followed by a random 5 character long alphanumeric. Can only be set if 'protocol' is 'memcached'.
828    #[serde(skip_serializing_if = "Option::is_none")]
829    pub sasl_username: Option<String>,
830
831    /// Optional. Memcached (SASL) Password to access the database. If not set, a random 32 character long alphanumeric password will be automatically generated. Can only be set if 'protocol' is 'memcached'.
832    #[serde(skip_serializing_if = "Option::is_none")]
833    pub sasl_password: Option<String>,
834
835    /// Optional. Redis database alert details.
836    #[serde(skip_serializing_if = "Option::is_none")]
837    pub alerts: Option<Vec<DatabaseAlertSpec>>,
838
839    /// Optional. Redis advanced capabilities (also known as modules) to be provisioned in the database. Use GET /database-modules to get a list of available advanced capabilities.
840    #[serde(skip_serializing_if = "Option::is_none")]
841    pub modules: Option<Vec<DatabaseModuleSpec>>,
842
843    /// Optional. Database [Hashing policy](https://redis.io/docs/latest/operate/rc/databases/configuration/clustering/#manage-the-hashing-policy).
844    #[serde(skip_serializing_if = "Option::is_none")]
845    pub sharding_type: Option<String>,
846
847    #[serde(skip_serializing_if = "Option::is_none")]
848    pub command_type: Option<String>,
849
850    /// Optional. The query performance factor adds extra compute power specifically for search and query databases. You can increase your queries per second by the selected factor.
851    #[serde(skip_serializing_if = "Option::is_none")]
852    pub query_performance_factor: Option<String>,
853
854    /// Additional fields from the API
855    #[serde(flatten)]
856    pub extra: Value,
857}
858
859/// Database import request
860#[derive(Debug, Clone, Serialize, Deserialize)]
861#[serde(rename_all = "camelCase")]
862pub struct DatabaseImportRequest {
863    #[serde(skip_serializing_if = "Option::is_none")]
864    pub subscription_id: Option<i32>,
865
866    #[serde(skip_serializing_if = "Option::is_none")]
867    pub database_id: Option<i32>,
868
869    /// Type of storage from which to import the database RDB file or Redis data.
870    pub source_type: String,
871
872    /// One or more paths to source data files or Redis databases, as appropriate to specified source type.
873    pub import_from_uri: Vec<String>,
874
875    #[serde(skip_serializing_if = "Option::is_none")]
876    pub command_type: Option<String>,
877
878    /// Additional fields from the API
879    #[serde(flatten)]
880    pub extra: Value,
881}
882
883/// Redis list of database tags
884#[derive(Debug, Clone, Serialize, Deserialize)]
885#[serde(rename_all = "camelCase")]
886pub struct CloudTags {
887    #[serde(skip_serializing_if = "Option::is_none")]
888    pub account_id: Option<i32>,
889
890    /// HATEOAS links
891    #[serde(skip_serializing_if = "Option::is_none")]
892    pub links: Option<Vec<HashMap<String, Value>>>,
893
894    /// Additional fields from the API
895    #[serde(flatten)]
896    pub extra: Value,
897}
898
899/// Upgrades the specified Pro database to a later Redis version.
900#[derive(Debug, Clone, Serialize, Deserialize)]
901#[serde(rename_all = "camelCase")]
902pub struct DatabaseUpgradeRedisVersionRequest {
903    #[serde(skip_serializing_if = "Option::is_none")]
904    pub database_id: Option<i32>,
905
906    #[serde(skip_serializing_if = "Option::is_none")]
907    pub subscription_id: Option<i32>,
908
909    /// The target Redis version the database will be upgraded to. Use GET /subscriptions/redis-versions to get a list of available Redis versions.
910    pub target_redis_version: String,
911
912    #[serde(skip_serializing_if = "Option::is_none")]
913    pub command_type: Option<String>,
914
915    /// Additional fields from the API
916    #[serde(flatten)]
917    pub extra: Value,
918}
919
920/// DatabaseSlowLogEntries
921#[derive(Debug, Clone, Serialize, Deserialize)]
922pub struct DatabaseSlowLogEntries {
923    #[serde(skip_serializing_if = "Option::is_none")]
924    pub entries: Option<Vec<DatabaseSlowLogEntry>>,
925
926    /// HATEOAS links
927    #[serde(skip_serializing_if = "Option::is_none")]
928    pub links: Option<Vec<HashMap<String, Value>>>,
929
930    /// Additional fields from the API
931    #[serde(flatten)]
932    pub extra: Value,
933}
934
935/// Optional. A list of regions and local settings to update.
936#[derive(Debug, Clone, Serialize, Deserialize)]
937#[serde(rename_all = "camelCase")]
938pub struct LocalRegionProperties {
939    /// Required. Name of the region to update.
940    #[serde(skip_serializing_if = "Option::is_none")]
941    pub region: Option<String>,
942
943    #[serde(skip_serializing_if = "Option::is_none")]
944    pub remote_backup: Option<DatabaseBackupConfig>,
945
946    #[serde(skip_serializing_if = "Option::is_none")]
947    pub local_throughput_measurement: Option<LocalThroughput>,
948
949    /// Optional. Type and rate of data persistence for this region. If set, 'globalDataPersistence' will not apply to this region.
950    #[serde(skip_serializing_if = "Option::is_none")]
951    pub data_persistence: Option<String>,
952
953    /// Optional. Changes the password used to access the database in this region. If set, 'globalPassword' will not apply to this region.
954    #[serde(skip_serializing_if = "Option::is_none")]
955    pub password: Option<String>,
956
957    /// Optional. List of source IP addresses or subnet masks to allow in this region. If set, Redis clients will be able to connect to the database in this region only from within the specified source IP addresses ranges, and 'globalSourceIp' will not apply to this region. Example: ['192.168.10.0/32', '192.168.12.0/24']
958    #[serde(skip_serializing_if = "Option::is_none")]
959    pub source_ip: Option<Vec<String>>,
960
961    /// Optional. Redis database alert settings for this region. If set, 'glboalAlerts' will not apply to this region.
962    #[serde(skip_serializing_if = "Option::is_none")]
963    pub alerts: Option<Vec<DatabaseAlertSpec>>,
964
965    /// Optional. Redis Serialization Protocol version for this region. Must be compatible with Redis version.
966    #[serde(skip_serializing_if = "Option::is_none")]
967    pub resp_version: Option<String>,
968
969    /// Additional fields from the API
970    #[serde(flatten)]
971    pub extra: Value,
972}
973
974/// TaskStateUpdate
975#[derive(Debug, Clone, Serialize, Deserialize)]
976#[serde(rename_all = "camelCase")]
977pub struct TaskStateUpdate {
978    #[serde(skip_serializing_if = "Option::is_none")]
979    pub task_id: Option<String>,
980
981    #[serde(skip_serializing_if = "Option::is_none")]
982    pub command_type: Option<String>,
983
984    #[serde(skip_serializing_if = "Option::is_none")]
985    pub status: Option<String>,
986
987    #[serde(skip_serializing_if = "Option::is_none")]
988    pub description: Option<String>,
989
990    #[serde(skip_serializing_if = "Option::is_none")]
991    pub timestamp: Option<String>,
992
993    #[serde(skip_serializing_if = "Option::is_none")]
994    pub response: Option<ProcessorResponse>,
995
996    /// HATEOAS links
997    #[serde(skip_serializing_if = "Option::is_none")]
998    pub links: Option<Vec<HashMap<String, Value>>>,
999
1000    /// Additional fields from the API
1001    #[serde(flatten)]
1002    pub extra: Value,
1003}
1004
1005/// Database update request
1006#[derive(Debug, Clone, Serialize, Deserialize)]
1007#[serde(rename_all = "camelCase")]
1008pub struct DatabaseUpdateRequest {
1009    #[serde(skip_serializing_if = "Option::is_none")]
1010    pub subscription_id: Option<i32>,
1011
1012    #[serde(skip_serializing_if = "Option::is_none")]
1013    pub database_id: Option<i32>,
1014
1015    /// Optional. When 'false': Creates a deployment plan and deploys it, updating any resources required by the plan. When 'true': creates a read-only deployment plan and does not update any resources. Default: 'false'
1016    #[serde(skip_serializing_if = "Option::is_none")]
1017    pub dry_run: Option<bool>,
1018
1019    /// Optional. Updated database name.
1020    #[serde(skip_serializing_if = "Option::is_none")]
1021    pub name: Option<String>,
1022
1023    /// Optional. Total memory in GB, including replication and other overhead. You cannot set both datasetSizeInGb and totalMemoryInGb.
1024    #[serde(skip_serializing_if = "Option::is_none")]
1025    pub memory_limit_in_gb: Option<f64>,
1026
1027    /// Optional. The maximum amount of data in the dataset for this database in GB. You cannot set both datasetSizeInGb and totalMemoryInGb. If ‘replication’ is 'true', the database’s total memory will be twice as large as the datasetSizeInGb.If ‘replication’ is false, the database’s total memory will be the datasetSizeInGb value.
1028    #[serde(skip_serializing_if = "Option::is_none")]
1029    pub dataset_size_in_gb: Option<f64>,
1030
1031    /// Optional. Redis Serialization Protocol version. Must be compatible with Redis version.
1032    #[serde(skip_serializing_if = "Option::is_none")]
1033    pub resp_version: Option<String>,
1034
1035    #[serde(skip_serializing_if = "Option::is_none")]
1036    pub throughput_measurement: Option<DatabaseThroughputSpec>,
1037
1038    /// Optional. Type and rate of data persistence in persistent storage.
1039    #[serde(skip_serializing_if = "Option::is_none")]
1040    pub data_persistence: Option<String>,
1041
1042    /// Optional. Data eviction policy.
1043    #[serde(skip_serializing_if = "Option::is_none")]
1044    pub data_eviction_policy: Option<String>,
1045
1046    /// Optional. Turns database replication on or off.
1047    #[serde(skip_serializing_if = "Option::is_none")]
1048    pub replication: Option<bool>,
1049
1050    /// Optional. Hashing policy Regex rules. Used only if 'shardingType' is 'custom-regex-rules'.
1051    #[serde(skip_serializing_if = "Option::is_none")]
1052    pub regex_rules: Option<Vec<String>>,
1053
1054    /// Optional. This database will be a replica of the specified Redis databases provided as one or more URI(s). Example: 'redis://user:password@host:port'. If the URI provided is a Redis Cloud database, only host and port should be provided. Example: ['redis://endpoint1:6379', 'redis://endpoint2:6380'].
1055    #[serde(skip_serializing_if = "Option::is_none")]
1056    pub replica_of: Option<Vec<String>>,
1057
1058    #[serde(skip_serializing_if = "Option::is_none")]
1059    pub replica: Option<ReplicaOfSpec>,
1060
1061    /// Optional. Support Redis [OSS Cluster API](https://redis.io/docs/latest/operate/rc/databases/configuration/clustering/#oss-cluster-api).
1062    #[serde(skip_serializing_if = "Option::is_none")]
1063    pub support_oss_cluster_api: Option<bool>,
1064
1065    /// Optional. If set to 'true', the database will use the external endpoint for OSS Cluster API. This setting blocks the database's private endpoint. Can only be set if 'supportOSSClusterAPI' is 'true'.
1066    #[serde(skip_serializing_if = "Option::is_none")]
1067    pub use_external_endpoint_for_oss_cluster_api: Option<bool>,
1068
1069    /// Optional. Changes the password used to access the database with the 'default' user. Can only be set if 'protocol' is 'redis'.
1070    #[serde(skip_serializing_if = "Option::is_none")]
1071    pub password: Option<String>,
1072
1073    /// Optional. Changes the Memcached (SASL) username to access the database. Can only be set if 'protocol' is 'memcached'.
1074    #[serde(skip_serializing_if = "Option::is_none")]
1075    pub sasl_username: Option<String>,
1076
1077    /// Optional. Changes the Memcached (SASL) password to access the database. Can only be set if 'protocol' is 'memcached'.
1078    #[serde(skip_serializing_if = "Option::is_none")]
1079    pub sasl_password: Option<String>,
1080
1081    /// Optional. List of source IP addresses or subnet masks to allow. If specified, Redis clients will be able to connect to this database only from within the specified source IP addresses ranges. Example: '['192.168.10.0/32', '192.168.12.0/24']'
1082    #[serde(skip_serializing_if = "Option::is_none")]
1083    pub source_ip: Option<Vec<String>>,
1084
1085    /// Optional. A public key client TLS/SSL certificate with new line characters replaced with '\n'. If specified, mTLS authentication will be required to authenticate user connections if it is not already required. If set to an empty string, TLS client certificates will be removed and mTLS will not be required. TLS connection may still apply, depending on the value of 'enableTls'.
1086    #[serde(skip_serializing_if = "Option::is_none")]
1087    pub client_ssl_certificate: Option<String>,
1088
1089    /// Optional. A list of client TLS/SSL certificates. If specified, mTLS authentication will be required to authenticate user connections. If set to an empty list, TLS client certificates will be removed and mTLS will not be required. TLS connection may still apply, depending on the value of 'enableTls'.
1090    #[serde(skip_serializing_if = "Option::is_none")]
1091    pub client_tls_certificates: Option<Vec<DatabaseCertificateSpec>>,
1092
1093    /// Optional. When 'true', requires TLS authentication for all connections - mTLS with valid clientTlsCertificates, regular TLS when clientTlsCertificates is not provided. If enableTls is set to 'false' while mTLS is required, it will remove the mTLS requirement and erase previously provided clientTlsCertificates.
1094    #[serde(skip_serializing_if = "Option::is_none")]
1095    pub enable_tls: Option<bool>,
1096
1097    /// Optional. When 'true', allows connecting to the database with the 'default' user. When 'false', only defined access control users can connect to the database. Can only be set if 'protocol' is 'redis'.
1098    #[serde(skip_serializing_if = "Option::is_none")]
1099    pub enable_default_user: Option<bool>,
1100
1101    /// Optional. Changes the backup location path. If specified, the database will back up every 24 hours to this location, and you can manually back up the database to this location at any time. If set to an empty string, the backup path will be removed.
1102    #[serde(skip_serializing_if = "Option::is_none")]
1103    pub periodic_backup_path: Option<String>,
1104
1105    #[serde(skip_serializing_if = "Option::is_none")]
1106    pub remote_backup: Option<DatabaseBackupConfig>,
1107
1108    /// Optional. Changes Redis database alert details.
1109    #[serde(skip_serializing_if = "Option::is_none")]
1110    pub alerts: Option<Vec<DatabaseAlertSpec>>,
1111
1112    #[serde(skip_serializing_if = "Option::is_none")]
1113    pub command_type: Option<String>,
1114
1115    /// Optional. Changes the query performance factor. The query performance factor adds extra compute power specifically for search and query databases. You can increase your queries per second by the selected factor.
1116    #[serde(skip_serializing_if = "Option::is_none")]
1117    pub query_performance_factor: Option<String>,
1118
1119    /// Additional fields from the API
1120    #[serde(flatten)]
1121    pub extra: Value,
1122}
1123
1124// ============================================================================
1125// Handler
1126// ============================================================================
1127
1128/// Handler for Pro database operations
1129///
1130/// Manages database lifecycle, configuration, backup/restore, import/export,
1131/// and monitoring for Redis Cloud Pro subscriptions.
1132pub struct DatabaseHandler {
1133    client: CloudClient,
1134}
1135
1136impl DatabaseHandler {
1137    /// Create a new handler
1138    pub fn new(client: CloudClient) -> Self {
1139        Self { client }
1140    }
1141
1142    /// Get all databases in a Pro subscription
1143    /// Gets a list of all databases in the specified Pro subscription.
1144    ///
1145    /// GET /subscriptions/{subscriptionId}/databases
1146    pub async fn get_subscription_databases(
1147        &self,
1148        subscription_id: i32,
1149        offset: Option<i32>,
1150        limit: Option<i32>,
1151    ) -> Result<AccountSubscriptionDatabases> {
1152        let mut query = Vec::new();
1153        if let Some(v) = offset {
1154            query.push(format!("offset={}", v));
1155        }
1156        if let Some(v) = limit {
1157            query.push(format!("limit={}", v));
1158        }
1159        let query_string = if query.is_empty() {
1160            String::new()
1161        } else {
1162            format!("?{}", query.join("&"))
1163        };
1164        self.client
1165            .get(&format!(
1166                "/subscriptions/{}/databases{}",
1167                subscription_id, query_string
1168            ))
1169            .await
1170    }
1171
1172    /// Create Pro database in existing subscription
1173    /// Creates a new database in an existing Pro subscription.
1174    ///
1175    /// POST /subscriptions/{subscriptionId}/databases
1176    pub async fn create_database(
1177        &self,
1178        subscription_id: i32,
1179        request: &DatabaseCreateRequest,
1180    ) -> Result<TaskStateUpdate> {
1181        self.client
1182            .post(
1183                &format!("/subscriptions/{}/databases", subscription_id),
1184                request,
1185            )
1186            .await
1187    }
1188
1189    /// Delete Pro database
1190    /// Deletes a database from a Pro subscription.
1191    ///
1192    /// DELETE /subscriptions/{subscriptionId}/databases/{databaseId}
1193    pub async fn delete_database_by_id(
1194        &self,
1195        subscription_id: i32,
1196        database_id: i32,
1197    ) -> Result<TaskStateUpdate> {
1198        let response = self
1199            .client
1200            .delete_raw(&format!(
1201                "/subscriptions/{}/databases/{}",
1202                subscription_id, database_id
1203            ))
1204            .await?;
1205        serde_json::from_value(response).map_err(Into::into)
1206    }
1207
1208    /// Get a single Pro database
1209    /// Gets details and settings of a single database in a Pro subscription.
1210    ///
1211    /// GET /subscriptions/{subscriptionId}/databases/{databaseId}
1212    pub async fn get_subscription_database_by_id(
1213        &self,
1214        subscription_id: i32,
1215        database_id: i32,
1216    ) -> Result<Database> {
1217        self.client
1218            .get(&format!(
1219                "/subscriptions/{}/databases/{}",
1220                subscription_id, database_id
1221            ))
1222            .await
1223    }
1224
1225    /// Update Pro database
1226    /// Updates an existing Pro database.
1227    ///
1228    /// PUT /subscriptions/{subscriptionId}/databases/{databaseId}
1229    pub async fn update_database(
1230        &self,
1231        subscription_id: i32,
1232        database_id: i32,
1233        request: &DatabaseUpdateRequest,
1234    ) -> Result<TaskStateUpdate> {
1235        self.client
1236            .put(
1237                &format!(
1238                    "/subscriptions/{}/databases/{}",
1239                    subscription_id, database_id
1240                ),
1241                request,
1242            )
1243            .await
1244    }
1245
1246    /// Get Pro database backup status
1247    /// Gets information on the latest backup attempt for this Pro database.
1248    ///
1249    /// GET /subscriptions/{subscriptionId}/databases/{databaseId}/backup
1250    pub async fn get_database_backup_status(
1251        &self,
1252        subscription_id: i32,
1253        database_id: i32,
1254        region_name: Option<String>,
1255    ) -> Result<TaskStateUpdate> {
1256        let mut query = Vec::new();
1257        if let Some(v) = region_name {
1258            query.push(format!("regionName={}", v));
1259        }
1260        let query_string = if query.is_empty() {
1261            String::new()
1262        } else {
1263            format!("?{}", query.join("&"))
1264        };
1265        self.client
1266            .get(&format!(
1267                "/subscriptions/{}/databases/{}/backup{}",
1268                subscription_id, database_id, query_string
1269            ))
1270            .await
1271    }
1272
1273    /// Back up Pro database
1274    /// Manually back up the specified Pro database to a backup path. By default, backups will be stored in the 'remoteBackup' location for this database.
1275    ///
1276    /// POST /subscriptions/{subscriptionId}/databases/{databaseId}/backup
1277    pub async fn backup_database(
1278        &self,
1279        subscription_id: i32,
1280        database_id: i32,
1281        request: &DatabaseBackupRequest,
1282    ) -> Result<TaskStateUpdate> {
1283        self.client
1284            .post(
1285                &format!(
1286                    "/subscriptions/{}/databases/{}/backup",
1287                    subscription_id, database_id
1288                ),
1289                request,
1290            )
1291            .await
1292    }
1293
1294    /// Get Pro database TLS certificate
1295    /// Gets the X.509 PEM (base64) encoded server certificate for TLS connection to the database. Requires 'enableTLS' to be 'true' for the database.
1296    ///
1297    /// GET /subscriptions/{subscriptionId}/databases/{databaseId}/certificate
1298    pub async fn get_subscription_database_certificate(
1299        &self,
1300        subscription_id: i32,
1301        database_id: i32,
1302    ) -> Result<DatabaseCertificate> {
1303        self.client
1304            .get(&format!(
1305                "/subscriptions/{}/databases/{}/certificate",
1306                subscription_id, database_id
1307            ))
1308            .await
1309    }
1310
1311    /// Flush Pro database
1312    /// Deletes all data from the specified Pro database.
1313    ///
1314    /// PUT /subscriptions/{subscriptionId}/databases/{databaseId}/flush
1315    pub async fn flush_crdb(
1316        &self,
1317        subscription_id: i32,
1318        database_id: i32,
1319        request: &CrdbFlushRequest,
1320    ) -> Result<TaskStateUpdate> {
1321        self.client
1322            .put(
1323                &format!(
1324                    "/subscriptions/{}/databases/{}/flush",
1325                    subscription_id, database_id
1326                ),
1327                request,
1328            )
1329            .await
1330    }
1331
1332    /// Get Pro database import status
1333    /// Gets information on the latest import attempt for this Pro database.
1334    ///
1335    /// GET /subscriptions/{subscriptionId}/databases/{databaseId}/import
1336    pub async fn get_database_import_status(
1337        &self,
1338        subscription_id: i32,
1339        database_id: i32,
1340    ) -> Result<TaskStateUpdate> {
1341        self.client
1342            .get(&format!(
1343                "/subscriptions/{}/databases/{}/import",
1344                subscription_id, database_id
1345            ))
1346            .await
1347    }
1348
1349    /// Import data to a Pro database
1350    /// Imports data from an RDB file or from a different Redis database into this Pro database. WARNING: Importing data into a database removes all existing data from the database.
1351    ///
1352    /// POST /subscriptions/{subscriptionId}/databases/{databaseId}/import
1353    pub async fn import_database(
1354        &self,
1355        subscription_id: i32,
1356        database_id: i32,
1357        request: &DatabaseImportRequest,
1358    ) -> Result<TaskStateUpdate> {
1359        self.client
1360            .post(
1361                &format!(
1362                    "/subscriptions/{}/databases/{}/import",
1363                    subscription_id, database_id
1364                ),
1365                request,
1366            )
1367            .await
1368    }
1369
1370    /// Update Active-Active database
1371    /// (Active-Active databases only) Updates database properties for an Active-Active database.
1372    ///
1373    /// PUT /subscriptions/{subscriptionId}/databases/{databaseId}/regions
1374    pub async fn update_crdb_local_properties(
1375        &self,
1376        subscription_id: i32,
1377        database_id: i32,
1378        request: &CrdbUpdatePropertiesRequest,
1379    ) -> Result<TaskStateUpdate> {
1380        self.client
1381            .put(
1382                &format!(
1383                    "/subscriptions/{}/databases/{}/regions",
1384                    subscription_id, database_id
1385                ),
1386                request,
1387            )
1388            .await
1389    }
1390
1391    /// Get database slowlog
1392    /// Gets the slowlog for a specific database.
1393    ///
1394    /// GET /subscriptions/{subscriptionId}/databases/{databaseId}/slow-log
1395    pub async fn get_slow_log(
1396        &self,
1397        subscription_id: i32,
1398        database_id: i32,
1399        region_name: Option<String>,
1400    ) -> Result<DatabaseSlowLogEntries> {
1401        let mut query = Vec::new();
1402        if let Some(v) = region_name {
1403            query.push(format!("regionName={}", v));
1404        }
1405        let query_string = if query.is_empty() {
1406            String::new()
1407        } else {
1408            format!("?{}", query.join("&"))
1409        };
1410        self.client
1411            .get(&format!(
1412                "/subscriptions/{}/databases/{}/slow-log{}",
1413                subscription_id, database_id, query_string
1414            ))
1415            .await
1416    }
1417
1418    /// Get database tags
1419    /// Gets a list of all database tags.
1420    ///
1421    /// GET /subscriptions/{subscriptionId}/databases/{databaseId}/tags
1422    pub async fn get_tags(&self, subscription_id: i32, database_id: i32) -> Result<CloudTags> {
1423        self.client
1424            .get(&format!(
1425                "/subscriptions/{}/databases/{}/tags",
1426                subscription_id, database_id
1427            ))
1428            .await
1429    }
1430
1431    /// Add a database tag
1432    /// Adds a single database tag to a database.
1433    ///
1434    /// POST /subscriptions/{subscriptionId}/databases/{databaseId}/tags
1435    pub async fn create_tag(
1436        &self,
1437        subscription_id: i32,
1438        database_id: i32,
1439        request: &DatabaseTagCreateRequest,
1440    ) -> Result<CloudTag> {
1441        self.client
1442            .post(
1443                &format!(
1444                    "/subscriptions/{}/databases/{}/tags",
1445                    subscription_id, database_id
1446                ),
1447                request,
1448            )
1449            .await
1450    }
1451
1452    /// Overwrite database tags
1453    /// Overwrites all tags on the database.
1454    ///
1455    /// PUT /subscriptions/{subscriptionId}/databases/{databaseId}/tags
1456    pub async fn update_tags(
1457        &self,
1458        subscription_id: i32,
1459        database_id: i32,
1460        request: &DatabaseTagsUpdateRequest,
1461    ) -> Result<CloudTags> {
1462        self.client
1463            .put(
1464                &format!(
1465                    "/subscriptions/{}/databases/{}/tags",
1466                    subscription_id, database_id
1467                ),
1468                request,
1469            )
1470            .await
1471    }
1472
1473    /// Delete database tag
1474    /// Removes the specified tag from the database.
1475    ///
1476    /// DELETE /subscriptions/{subscriptionId}/databases/{databaseId}/tags/{tagKey}
1477    pub async fn delete_tag(
1478        &self,
1479        subscription_id: i32,
1480        database_id: i32,
1481        tag_key: String,
1482    ) -> Result<HashMap<String, Value>> {
1483        let response = self
1484            .client
1485            .delete_raw(&format!(
1486                "/subscriptions/{}/databases/{}/tags/{}",
1487                subscription_id, database_id, tag_key
1488            ))
1489            .await?;
1490        serde_json::from_value(response).map_err(Into::into)
1491    }
1492
1493    /// Update database tag value
1494    /// Updates the value of the specified database tag.
1495    ///
1496    /// PUT /subscriptions/{subscriptionId}/databases/{databaseId}/tags/{tagKey}
1497    pub async fn update_tag(
1498        &self,
1499        subscription_id: i32,
1500        database_id: i32,
1501        tag_key: String,
1502        request: &DatabaseTagUpdateRequest,
1503    ) -> Result<CloudTag> {
1504        self.client
1505            .put(
1506                &format!(
1507                    "/subscriptions/{}/databases/{}/tags/{}",
1508                    subscription_id, database_id, tag_key
1509                ),
1510                request,
1511            )
1512            .await
1513    }
1514
1515    /// Get Pro database version upgrade status
1516    /// Gets information on the latest upgrade attempt for this Pro database.
1517    ///
1518    /// GET /subscriptions/{subscriptionId}/databases/{databaseId}/upgrade
1519    pub async fn get_database_redis_version_upgrade_status(
1520        &self,
1521        subscription_id: i32,
1522        database_id: i32,
1523    ) -> Result<BdbVersionUpgradeStatus> {
1524        self.client
1525            .get(&format!(
1526                "/subscriptions/{}/databases/{}/upgrade",
1527                subscription_id, database_id
1528            ))
1529            .await
1530    }
1531
1532    /// Upgrade Pro database version
1533    ///
1534    /// POST /subscriptions/{subscriptionId}/databases/{databaseId}/upgrade
1535    pub async fn upgrade_database_redis_version(
1536        &self,
1537        subscription_id: i32,
1538        database_id: i32,
1539        request: &DatabaseUpgradeRedisVersionRequest,
1540    ) -> Result<TaskStateUpdate> {
1541        self.client
1542            .post(
1543                &format!(
1544                    "/subscriptions/{}/databases/{}/upgrade",
1545                    subscription_id, database_id
1546                ),
1547                request,
1548            )
1549            .await
1550    }
1551}