refactor: replace chrono with jiff for time handling (#1582)

Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
heihutu
2026-01-22 17:24:56 +08:00
committed by GitHub
parent 6631407416
commit db253c01a9
20 changed files with 307 additions and 117 deletions
Generated
+53 -2
View File
@@ -4915,6 +4915,47 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "jiff"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67e8da4c49d6d9909fe03361f9b620f58898859f5c7aded68351e85e71ecf50"
dependencies = [
"jiff-static",
"jiff-tzdb-platform",
"log",
"portable-atomic",
"portable-atomic-util",
"serde_core",
"windows-sys 0.61.2",
]
[[package]]
name = "jiff-static"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c84ee7f197eca9a86c6fd6cb771e55eb991632f15f2bc3ca6ec838929e6e78"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
]
[[package]]
name = "jiff-tzdb"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2"
[[package]]
name = "jiff-tzdb-platform"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
dependencies = [
"jiff-tzdb",
]
[[package]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.34" version = "0.1.34"
@@ -6594,6 +6635,15 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950"
[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]
[[package]] [[package]]
name = "potential_utf" name = "potential_utf"
version = "0.1.4" version = "0.1.4"
@@ -7617,6 +7667,7 @@ dependencies = [
"hyper", "hyper",
"hyper-util", "hyper-util",
"jemalloc_pprof", "jemalloc_pprof",
"jiff",
"libc", "libc",
"libsystemd", "libsystemd",
"libunftp", "libunftp",
@@ -7959,7 +8010,7 @@ dependencies = [
"async-trait", "async-trait",
"base64", "base64",
"chacha20poly1305", "chacha20poly1305",
"chrono", "jiff",
"md5 0.8.0", "md5 0.8.0",
"moka", "moka",
"rand 0.10.0-rc.6", "rand 0.10.0-rc.6",
@@ -8220,7 +8271,7 @@ dependencies = [
"serde_json", "serde_json",
"serial_test", "serial_test",
"tempfile", "tempfile",
"thiserror 2.0.17", "thiserror 2.0.18",
"time", "time",
"tokio", "tokio",
"tokio-test", "tokio-test",
+1
View File
@@ -163,6 +163,7 @@ zeroize = { version = "1.8.2", features = ["derive"] }
# Time and Date # Time and Date
chrono = { version = "0.4.43", features = ["serde"] } chrono = { version = "0.4.43", features = ["serde"] }
humantime = "2.3.0" humantime = "2.3.0"
jiff = { version = "0.2.18", features = ["serde"] }
time = { version = "0.3.45", features = ["std", "parsing", "formatting", "macros", "serde"] } time = { version = "0.3.45", features = ["std", "parsing", "formatting", "macros", "serde"] }
# Utilities and Tools # Utilities and Tools
+1 -1
View File
@@ -32,7 +32,7 @@ workspace = true
async-trait = { workspace = true } async-trait = { workspace = true }
tokio = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] }
uuid = { workspace = true, features = ["serde"] } uuid = { workspace = true, features = ["serde"] }
chrono = { workspace = true, features = ["serde"] } jiff = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
+12 -11
View File
@@ -24,6 +24,7 @@ use aes_gcm::{
aead::{Aead, KeyInit}, aead::{Aead, KeyInit},
}; };
use async_trait::async_trait; use async_trait::async_trait;
use jiff::Zoned;
use rand::Rng; use rand::Rng;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
@@ -51,8 +52,8 @@ struct StoredMasterKey {
status: KeyStatus, status: KeyStatus,
description: Option<String>, description: Option<String>,
metadata: HashMap<String, String>, metadata: HashMap<String, String>,
created_at: chrono::DateTime<chrono::Utc>, created_at: Zoned,
rotated_at: Option<chrono::DateTime<chrono::Utc>>, rotated_at: Option<Zoned>,
created_by: Option<String>, created_by: Option<String>,
/// Encrypted key material (32 bytes for AES-256) /// Encrypted key material (32 bytes for AES-256)
encrypted_key_material: Vec<u8>, encrypted_key_material: Vec<u8>,
@@ -69,7 +70,7 @@ struct DataKeyEnvelope {
encrypted_key: Vec<u8>, encrypted_key: Vec<u8>,
nonce: Vec<u8>, nonce: Vec<u8>,
encryption_context: HashMap<String, String>, encryption_context: HashMap<String, String>,
created_at: chrono::DateTime<chrono::Utc>, created_at: Zoned,
} }
impl LocalKmsClient { impl LocalKmsClient {
@@ -182,8 +183,8 @@ impl LocalKmsClient {
status: master_key.status.clone(), status: master_key.status.clone(),
description: master_key.description.clone(), description: master_key.description.clone(),
metadata: master_key.metadata.clone(), metadata: master_key.metadata.clone(),
created_at: master_key.created_at, created_at: master_key.created_at.clone(),
rotated_at: master_key.rotated_at, rotated_at: master_key.rotated_at.clone(),
created_by: master_key.created_by.clone(), created_by: master_key.created_by.clone(),
encrypted_key_material, encrypted_key_material,
nonce, nonce,
@@ -317,7 +318,7 @@ impl KmsClient for LocalKmsClient {
encrypted_key: encrypted_key.clone(), encrypted_key: encrypted_key.clone(),
nonce, nonce,
encryption_context: request.encryption_context.clone(), encryption_context: request.encryption_context.clone(),
created_at: chrono::Utc::now(), created_at: Zoned::now(),
}; };
// Serialize the envelope as the ciphertext // Serialize the envelope as the ciphertext
@@ -561,7 +562,7 @@ impl KmsClient for LocalKmsClient {
let mut master_key = self.load_master_key(key_id).await?; let mut master_key = self.load_master_key(key_id).await?;
master_key.version += 1; master_key.version += 1;
master_key.rotated_at = Some(chrono::Utc::now()); master_key.rotated_at = Some(Zoned::now());
// Generate new key material // Generate new key material
let key_material = Self::generate_key_material(); let key_material = Self::generate_key_material();
@@ -648,7 +649,7 @@ impl KmsBackend for LocalKmsBackend {
key_state: KeyState::Enabled, key_state: KeyState::Enabled,
key_usage: request.key_usage, key_usage: request.key_usage,
description: request.description, description: request.description,
creation_date: chrono::Utc::now(), creation_date: Zoned::now(),
deletion_date: None, deletion_date: None,
origin: "KMS".to_string(), origin: "KMS".to_string(),
key_manager: "CUSTOMER".to_string(), key_manager: "CUSTOMER".to_string(),
@@ -768,7 +769,7 @@ impl KmsBackend for LocalKmsBackend {
key_usage: master_key.usage, key_usage: master_key.usage,
key_state: KeyState::PendingDeletion, // AWS KMS compatibility key_state: KeyState::PendingDeletion, // AWS KMS compatibility
creation_date: master_key.created_at, creation_date: master_key.created_at,
deletion_date: Some(chrono::Utc::now()), deletion_date: Some(Zoned::now()),
key_manager: "CUSTOMER".to_string(), key_manager: "CUSTOMER".to_string(),
origin: "AWS_KMS".to_string(), origin: "AWS_KMS".to_string(),
tags: master_key.metadata, tags: master_key.metadata,
@@ -786,10 +787,10 @@ impl KmsBackend for LocalKmsBackend {
return Err(KmsError::invalid_parameter("pending_window_in_days must be between 7 and 30".to_string())); return Err(KmsError::invalid_parameter("pending_window_in_days must be between 7 and 30".to_string()));
} }
let deletion_date = chrono::Utc::now() + chrono::Duration::days(days as i64); let deletion_date = Zoned::now() + jiff::Span::new().days(days as i64);
master_key.status = KeyStatus::PendingDeletion; master_key.status = KeyStatus::PendingDeletion;
(Some(deletion_date.to_rfc3339()), Some(deletion_date)) (Some(deletion_date.to_string()), Some(deletion_date))
}; };
// Save the updated key to disk - preserve existing key material! // Save the updated key to disk - preserve existing key material!
+11 -10
View File
@@ -20,6 +20,7 @@ use crate::error::{KmsError, Result};
use crate::types::*; use crate::types::*;
use async_trait::async_trait; use async_trait::async_trait;
use base64::{Engine as _, engine::general_purpose}; use base64::{Engine as _, engine::general_purpose};
use jiff::Zoned;
use rand::RngCore; use rand::RngCore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
@@ -47,7 +48,7 @@ struct VaultKeyData {
/// Key usage type /// Key usage type
usage: KeyUsage, usage: KeyUsage,
/// Key creation timestamp /// Key creation timestamp
created_at: chrono::DateTime<chrono::Utc>, created_at: Zoned,
/// Key status /// Key status
status: KeyStatus, status: KeyStatus,
/// Key version /// Key version
@@ -156,7 +157,7 @@ impl VaultKmsClient {
let key_data = VaultKeyData { let key_data = VaultKeyData {
algorithm: "AES_256".to_string(), algorithm: "AES_256".to_string(),
usage: request.key_usage.clone(), usage: request.key_usage.clone(),
created_at: chrono::Utc::now(), created_at: Zoned::now(),
status: KeyStatus::Active, status: KeyStatus::Active,
version: 1, version: 1,
description: request.description.clone(), description: request.description.clone(),
@@ -252,7 +253,7 @@ impl KmsClient for VaultKmsClient {
.map_err(|e| KmsError::cryptographic_error("decode", e.to_string()))?, .map_err(|e| KmsError::cryptographic_error("decode", e.to_string()))?,
key_spec: request.key_spec.clone(), key_spec: request.key_spec.clone(),
metadata: request.encryption_context.clone(), metadata: request.encryption_context.clone(),
created_at: chrono::Utc::now(), created_at: Zoned::now(),
}) })
} }
@@ -302,7 +303,7 @@ impl KmsClient for VaultKmsClient {
let key_data = VaultKeyData { let key_data = VaultKeyData {
algorithm: algorithm.to_string(), algorithm: algorithm.to_string(),
usage: KeyUsage::EncryptDecrypt, usage: KeyUsage::EncryptDecrypt,
created_at: chrono::Utc::now(), created_at: Zoned::now(),
status: KeyStatus::Active, status: KeyStatus::Active,
version: 1, version: 1,
description: None, description: None,
@@ -458,7 +459,7 @@ impl KmsClient for VaultKmsClient {
description: None, // Rotate preserves existing description (would need key lookup) description: None, // Rotate preserves existing description (would need key lookup)
metadata: key_data.metadata, metadata: key_data.metadata,
created_at: key_data.created_at, created_at: key_data.created_at,
rotated_at: Some(chrono::Utc::now()), rotated_at: Some(Zoned::now()),
created_by: None, created_by: None,
}; };
@@ -549,7 +550,7 @@ impl KmsBackend for VaultKmsBackend {
key_state: KeyState::Enabled, key_state: KeyState::Enabled,
key_usage: request.key_usage, key_usage: request.key_usage,
description: request.description, description: request.description,
creation_date: chrono::Utc::now(), creation_date: Zoned::now(),
deletion_date: None, deletion_date: None,
origin: "VAULT".to_string(), origin: "VAULT".to_string(),
key_manager: "VAULT".to_string(), key_manager: "VAULT".to_string(),
@@ -664,7 +665,7 @@ impl KmsBackend for VaultKmsBackend {
} else { } else {
// For non-pending keys, mark as PendingDeletion // For non-pending keys, mark as PendingDeletion
key_metadata.key_state = KeyState::PendingDeletion; key_metadata.key_state = KeyState::PendingDeletion;
key_metadata.deletion_date = Some(chrono::Utc::now()); key_metadata.deletion_date = Some(Zoned::now());
// Update the key metadata in Vault storage to reflect the new state // Update the key metadata in Vault storage to reflect the new state
self.update_key_metadata_in_storage(key_id, &key_metadata).await?; self.update_key_metadata_in_storage(key_id, &key_metadata).await?;
@@ -680,14 +681,14 @@ impl KmsBackend for VaultKmsBackend {
)); ));
} }
let deletion_date = chrono::Utc::now() + chrono::Duration::days(days as i64); let deletion_date = Zoned::now() + jiff::Span::new().days(days as i64);
key_metadata.key_state = KeyState::PendingDeletion; key_metadata.key_state = KeyState::PendingDeletion;
key_metadata.deletion_date = Some(deletion_date); key_metadata.deletion_date = Some(deletion_date.clone());
// Update the key metadata in Vault storage to reflect the new state // Update the key metadata in Vault storage to reflect the new state
self.update_key_metadata_in_storage(key_id, &key_metadata).await?; self.update_key_metadata_in_storage(key_id, &key_metadata).await?;
Some(deletion_date.to_rfc3339()) Some(deletion_date.to_string())
}; };
Ok(DeleteKeyResponse { Ok(DeleteKeyResponse {
+4 -3
View File
@@ -154,6 +154,7 @@ impl KmsCache {
mod tests { mod tests {
use super::*; use super::*;
use crate::types::{KeyState, KeyUsage}; use crate::types::{KeyState, KeyUsage};
use jiff::Zoned;
use std::time::Duration; use std::time::Duration;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -202,7 +203,7 @@ mod tests {
key_state: KeyState::Enabled, key_state: KeyState::Enabled,
key_usage: KeyUsage::EncryptDecrypt, key_usage: KeyUsage::EncryptDecrypt,
description: Some("Test key".to_string()), description: Some("Test key".to_string()),
creation_date: chrono::Utc::now(), creation_date: Zoned::now(),
deletion_date: None, deletion_date: None,
origin: "KMS".to_string(), origin: "KMS".to_string(),
key_manager: "CUSTOMER".to_string(), key_manager: "CUSTOMER".to_string(),
@@ -252,7 +253,7 @@ mod tests {
key_state: KeyState::Enabled, key_state: KeyState::Enabled,
key_usage: KeyUsage::EncryptDecrypt, key_usage: KeyUsage::EncryptDecrypt,
description: Some("TTL test key".to_string()), description: Some("TTL test key".to_string()),
creation_date: chrono::Utc::now(), creation_date: Zoned::now(),
deletion_date: None, deletion_date: None,
origin: "KMS".to_string(), origin: "KMS".to_string(),
key_manager: "CUSTOMER".to_string(), key_manager: "CUSTOMER".to_string(),
@@ -283,7 +284,7 @@ mod tests {
key_state: KeyState::Enabled, key_state: KeyState::Enabled,
key_usage: KeyUsage::EncryptDecrypt, key_usage: KeyUsage::EncryptDecrypt,
description: None, description: None,
creation_date: chrono::Utc::now(), creation_date: Zoned::now(),
deletion_date: None, deletion_date: None,
origin: "KMS".to_string(), origin: "KMS".to_string(),
key_manager: "CUSTOMER".to_string(), key_manager: "CUSTOMER".to_string(),
+5 -4
View File
@@ -19,6 +19,7 @@ use crate::error::{KmsError, Result};
use crate::manager::KmsManager; use crate::manager::KmsManager;
use crate::types::*; use crate::types::*;
use base64::Engine; use base64::Engine;
use jiff::Zoned;
use rand::random; use rand::random;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Cursor; use std::io::Cursor;
@@ -339,7 +340,7 @@ impl ObjectEncryptionService {
iv, iv,
tag: Some(tag), tag: Some(tag),
encryption_context: context, encryption_context: context,
encrypted_at: chrono::Utc::now(), encrypted_at: Zoned::now(),
original_size, original_size,
encrypted_data_key: data_key.ciphertext_blob, encrypted_data_key: data_key.ciphertext_blob,
}; };
@@ -482,7 +483,7 @@ impl ObjectEncryptionService {
iv, iv,
tag: Some(tag), tag: Some(tag),
encryption_context: context, encryption_context: context,
encrypted_at: chrono::Utc::now(), encrypted_at: Zoned::now(),
original_size, original_size,
encrypted_data_key: Vec::new(), // Empty for SSE-C encrypted_data_key: Vec::new(), // Empty for SSE-C
}; };
@@ -695,7 +696,7 @@ impl ObjectEncryptionService {
iv, iv,
tag, tag,
encryption_context, encryption_context,
encrypted_at: chrono::Utc::now(), encrypted_at: Zoned::now(),
original_size: 0, // Not available from headers original_size: 0, // Not available from headers
encrypted_data_key, encrypted_data_key,
}) })
@@ -809,7 +810,7 @@ mod tests {
iv: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], iv: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
tag: Some(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]), tag: Some(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
encryption_context: HashMap::from([("bucket".to_string(), "test-bucket".to_string())]), encryption_context: HashMap::from([("bucket".to_string(), "test-bucket".to_string())]),
encrypted_at: chrono::Utc::now(), encrypted_at: Zoned::now(),
original_size: 100, original_size: 100,
encrypted_data_key: vec![1, 2, 3, 4], encrypted_data_key: vec![1, 2, 3, 4],
}; };
+12 -12
View File
@@ -14,7 +14,7 @@
//! Core type definitions for KMS operations //! Core type definitions for KMS operations
use chrono::{DateTime, Utc}; use jiff::Zoned;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use uuid::Uuid; use uuid::Uuid;
@@ -37,7 +37,7 @@ pub struct DataKey {
/// Associated metadata /// Associated metadata
pub metadata: HashMap<String, String>, pub metadata: HashMap<String, String>,
/// Key creation timestamp /// Key creation timestamp
pub created_at: DateTime<Utc>, pub created_at: Zoned,
} }
impl DataKey { impl DataKey {
@@ -61,7 +61,7 @@ impl DataKey {
ciphertext, ciphertext,
key_spec, key_spec,
metadata: HashMap::new(), metadata: HashMap::new(),
created_at: Utc::now(), created_at: Zoned::now(),
} }
} }
@@ -112,9 +112,9 @@ pub struct MasterKey {
/// Associated metadata /// Associated metadata
pub metadata: HashMap<String, String>, pub metadata: HashMap<String, String>,
/// Key creation timestamp /// Key creation timestamp
pub created_at: DateTime<Utc>, pub created_at: Zoned,
/// Key last rotation timestamp /// Key last rotation timestamp
pub rotated_at: Option<DateTime<Utc>>, pub rotated_at: Option<Zoned>,
/// Key creator/owner /// Key creator/owner
pub created_by: Option<String>, pub created_by: Option<String>,
} }
@@ -139,7 +139,7 @@ impl MasterKey {
status: KeyStatus::Active, status: KeyStatus::Active,
description: None, description: None,
metadata: HashMap::new(), metadata: HashMap::new(),
created_at: Utc::now(), created_at: Zoned::now(),
rotated_at: None, rotated_at: None,
created_by, created_by,
} }
@@ -170,7 +170,7 @@ impl MasterKey {
status: KeyStatus::Active, status: KeyStatus::Active,
description, description,
metadata: HashMap::new(), metadata: HashMap::new(),
created_at: Utc::now(), created_at: Zoned::now(),
rotated_at: None, rotated_at: None,
created_by, created_by,
} }
@@ -219,9 +219,9 @@ pub struct KeyInfo {
/// Key tags /// Key tags
pub tags: HashMap<String, String>, pub tags: HashMap<String, String>,
/// Key creation timestamp /// Key creation timestamp
pub created_at: DateTime<Utc>, pub created_at: Zoned,
/// Key last rotation timestamp /// Key last rotation timestamp
pub rotated_at: Option<DateTime<Utc>>, pub rotated_at: Option<Zoned>,
/// Key creator /// Key creator
pub created_by: Option<String>, pub created_by: Option<String>,
} }
@@ -612,7 +612,7 @@ pub struct EncryptionMetadata {
/// Encryption context /// Encryption context
pub encryption_context: HashMap<String, String>, pub encryption_context: HashMap<String, String>,
/// Timestamp when encrypted /// Timestamp when encrypted
pub encrypted_at: DateTime<Utc>, pub encrypted_at: Zoned,
/// Size of original data /// Size of original data
pub original_size: u64, pub original_size: u64,
/// Encrypted data key /// Encrypted data key
@@ -697,9 +697,9 @@ pub struct KeyMetadata {
/// Key description /// Key description
pub description: Option<String>, pub description: Option<String>,
/// Key creation timestamp /// Key creation timestamp
pub creation_date: DateTime<Utc>, pub creation_date: Zoned,
/// Key deletion timestamp /// Key deletion timestamp
pub deletion_date: Option<DateTime<Utc>>, pub deletion_date: Option<Zoned>,
/// Key origin /// Key origin
pub origin: String, pub origin: String,
/// Key manager /// Key manager
+1
View File
@@ -99,6 +99,7 @@ rustls-pemfile = { workspace = true }
# Time and Date # Time and Date
chrono = { workspace = true } chrono = { workspace = true }
jiff = { workspace = true }
time = { workspace = true, features = ["parsing", "formatting", "serde"] } time = { workspace = true, features = ["parsing", "formatting", "serde"] }
# Utilities and Tools # Utilities and Tools
+1 -1
View File
@@ -555,7 +555,7 @@ async fn health_check(method: Method) -> Response {
let body_json = json!({ let body_json = json!({
"status": health_status, "status": health_status,
"service": "rustfs-console", "service": "rustfs-console",
"timestamp": chrono::Utc::now().to_rfc3339(), "timestamp": jiff::Zoned::now().to_string(),
"version": env!("CARGO_PKG_VERSION"), "version": env!("CARGO_PKG_VERSION"),
"details": details, "details": details,
"uptime": std::time::SystemTime::now() "uptime": std::time::SystemTime::now()
+1 -1
View File
@@ -132,7 +132,7 @@ impl Operation for HealthCheckHandler {
let health_info = json!({ let health_info = json!({
"status": "ok", "status": "ok",
"service": "rustfs-endpoint", "service": "rustfs-endpoint",
"timestamp": chrono::Utc::now().to_rfc3339(), "timestamp": jiff::Zoned::now().to_string(),
"version": env!("CARGO_PKG_VERSION") "version": env!("CARGO_PKG_VERSION")
}); });
+1 -2
View File
@@ -14,7 +14,6 @@
use crate::storage::ecfs::{process_lambda_configurations, process_queue_configurations, process_topic_configurations}; use crate::storage::ecfs::{process_lambda_configurations, process_queue_configurations, process_topic_configurations};
use crate::{admin, config, version}; use crate::{admin, config, version};
use chrono::Datelike;
use rustfs_config::{DEFAULT_UPDATE_CHECK, ENV_UPDATE_CHECK}; use rustfs_config::{DEFAULT_UPDATE_CHECK, ENV_UPDATE_CHECK};
use rustfs_ecstore::bucket::metadata_sys; use rustfs_ecstore::bucket::metadata_sys;
use rustfs_notify::notifier_global; use rustfs_notify::notifier_global;
@@ -26,7 +25,7 @@ use tracing::{debug, error, info, instrument, warn};
#[instrument] #[instrument]
pub(crate) fn print_server_info() { pub(crate) fn print_server_info() {
let current_year = chrono::Utc::now().year(); let current_year = jiff::Zoned::now().year();
// Use custom macros to print server information // Use custom macros to print server information
info!("RustFS Object Storage Server"); info!("RustFS Object Storage Server");
info!("Copyright: 2024-{} RustFS, Inc", current_year); info!("Copyright: 2024-{} RustFS, Inc", current_year);
+10 -4
View File
@@ -71,11 +71,16 @@ static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
#[global_allocator] #[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
fn main() -> Result<()> { fn main() {
let runtime = server::get_tokio_runtime_builder() let runtime = server::get_tokio_runtime_builder()
.build() .build()
.expect("Failed to build Tokio runtime"); .expect("Failed to build Tokio runtime");
runtime.block_on(async_main()) let result = runtime.block_on(async_main());
if let Err(ref e) = result {
eprintln!("{} Server encountered an error and is shutting down: {}", jiff::Zoned::now(), e);
error!("Server encountered an error and is shutting down: {}", e);
std::process::exit(1);
}
} }
async fn async_main() -> Result<()> { async fn async_main() -> Result<()> {
// Parse the obtained parameters // Parse the obtained parameters
@@ -365,9 +370,10 @@ async fn run(opt: config::Opt) -> Result<()> {
init_update_check(); init_update_check();
println!( println!(
"RustFS server started successfully at {}, current time: {}", "RustFS server version: {} started successfully at {}, current time: {}",
version::get_version(),
&server_address, &server_address,
chrono::offset::Utc::now().to_string() jiff::Zoned::now()
); );
info!(target: "rustfs::main::run","server started successfully at {}", &server_address); info!(target: "rustfs::main::run","server started successfully at {}", &server_address);
// 4. Mark as Full Ready now that critical components are warm // 4. Mark as Full Ready now that critical components are warm
+1 -2
View File
@@ -54,7 +54,6 @@ pub async fn dump_memory_pprof_now() -> Result<std::path::PathBuf, String> {
#[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))] #[cfg(all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))]
mod linux_impl { mod linux_impl {
use chrono::Utc;
use jemalloc_pprof::PROF_CTL; use jemalloc_pprof::PROF_CTL;
use pprof::protos::Message; use pprof::protos::Message;
use rustfs_config::{ use rustfs_config::{
@@ -104,7 +103,7 @@ mod linux_impl {
/// Generate timestamp string for filenames /// Generate timestamp string for filenames
fn ts() -> String { fn ts() -> String {
Utc::now().format("%Y%m%dT%H%M%S").to_string() jiff::Zoned::now().strftime("%Y%m%dT%H%M%S").to_string()
} }
/// Write pprof report to file in protobuf format /// Write pprof report to file in protobuf format
+2 -2
View File
@@ -85,7 +85,7 @@ pub(crate) async fn start_audit_system() -> AuditResult<()> {
info!( info!(
target: "rustfs::main::start_audit_system", target: "rustfs::main::start_audit_system",
"Audit system started successfully with time: {}.", "Audit system started successfully with time: {}.",
chrono::Utc::now() jiff::Zoned::now()
); );
Ok(()) Ok(())
} }
@@ -114,7 +114,7 @@ pub(crate) async fn stop_audit_system() -> AuditResult<()> {
// Prepare before stopping // Prepare before stopping
system.close().await?; system.close().await?;
// Record after stopping // Record after stopping
info!("Audit system stopped at {}", chrono::Utc::now()); info!("Audit system stopped at {}", jiff::Zoned::now());
Ok(()) Ok(())
} else { } else {
warn!("Audit system not initialized, cannot stop"); warn!("Audit system not initialized, cannot stop");
+1 -1
View File
@@ -169,7 +169,7 @@ pub async fn start_http_server(
// Detailed endpoint information (showing all API endpoints) // Detailed endpoint information (showing all API endpoints)
let api_endpoints = format!("{protocol}://{local_ip_str}:{server_port}"); let api_endpoints = format!("{protocol}://{local_ip_str}:{server_port}");
let localhost_endpoint = format!("{protocol}://127.0.0.1:{server_port}"); let localhost_endpoint = format!("{protocol}://127.0.0.1:{server_port}");
let now_time = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); let now_time = jiff::Zoned::now().strftime("%Y-%m-%d %H:%M:%S").to_string();
if opt.console_enable { if opt.console_enable {
admin::console::init_console_cfg(local_ip, server_port); admin::console::init_console_cfg(local_ip, server_port);
+2 -2
View File
@@ -132,7 +132,7 @@ pub(crate) fn get_tokio_runtime_builder() -> tokio::runtime::Builder {
let id = std::thread::current().id(); let id = std::thread::current().id();
println!( println!(
"RustFS Worker Thread running - initializing resources time: {:?}, thread id: {:?}", "RustFS Worker Thread running - initializing resources time: {:?}, thread id: {:?}",
chrono::Utc::now().to_rfc3339(), jiff::Zoned::now().to_string(),
id id
); );
}) })
@@ -140,7 +140,7 @@ pub(crate) fn get_tokio_runtime_builder() -> tokio::runtime::Builder {
let id = std::thread::current().id(); let id = std::thread::current().id();
println!( println!(
"RustFS Worker Thread stopping - cleaning up resources time: {:?}, thread id: {:?}", "RustFS Worker Thread stopping - cleaning up resources time: {:?}, thread id: {:?}",
chrono::Utc::now().to_rfc3339(), jiff::Zoned::now().to_string(),
id id
) )
}); });
+7 -10
View File
@@ -34,7 +34,6 @@ use crate::storage::{
}; };
use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD}; use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD};
use bytes::Bytes; use bytes::Bytes;
use chrono::{DateTime, Utc};
use datafusion::arrow::{ use datafusion::arrow::{
csv::WriterBuilder as CsvWriterBuilder, json::WriterBuilder as JsonWriterBuilder, json::writer::JsonArray, csv::WriterBuilder as CsvWriterBuilder, json::WriterBuilder as JsonWriterBuilder, json::writer::JsonArray,
}; };
@@ -319,7 +318,7 @@ async fn create_managed_encryption_material(
iv: data_key.nonce.to_vec(), iv: data_key.nonce.to_vec(),
tag: None, tag: None,
encryption_context: context.encryption_context.clone(), encryption_context: context.encryption_context.clone(),
encrypted_at: Utc::now(), encrypted_at: jiff::Zoned::now(),
original_size: if original_size >= 0 { original_size as u64 } else { 0 }, original_size: if original_size >= 0 { original_size as u64 } else { 0 },
encrypted_data_key, encrypted_data_key,
}; };
@@ -3360,7 +3359,7 @@ impl S3 for FS {
// Per S3 API spec, this header should be present in HEAD object response when tags exist // Per S3 API spec, this header should be present in HEAD object response when tags exist
if tag_count > 0 { if tag_count > 0 {
let header_name = http::HeaderName::from_static(AMZ_TAG_COUNT); let header_name = http::HeaderName::from_static(AMZ_TAG_COUNT);
if let Ok(header_value) = tag_count.to_string().parse::<http::HeaderValue>() { if let Ok(header_value) = tag_count.to_string().parse::<HeaderValue>() {
response.headers.insert(header_name, header_value); response.headers.insert(header_name, header_value);
} else { } else {
warn!("Failed to parse x-amz-tagging-count header value, skipping"); warn!("Failed to parse x-amz-tagging-count header value, skipping");
@@ -4105,9 +4104,7 @@ impl S3 for FS {
if dsc.replicate_any() { if dsc.replicate_any() {
let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-timestamp"); let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-timestamp");
let now: DateTime<Utc> = Utc::now(); opts.user_defined.insert(k, jiff::Zoned::now().to_string());
let formatted_time = now.to_rfc3339();
opts.user_defined.insert(k, formatted_time);
let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-status"); let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-status");
opts.user_defined.insert(k, dsc.pending_status().unwrap_or_default()); opts.user_defined.insert(k, dsc.pending_status().unwrap_or_default());
} }
@@ -7807,7 +7804,7 @@ mod tests {
let result = process_queue_configurations( let result = process_queue_configurations(
&mut event_rules, &mut event_rules,
Some(vec![s3s::dto::QueueConfiguration { Some(vec![QueueConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()], events: vec!["s3:ObjectCreated:*".to_string().into()],
queue_arn: invalid_arn.to_string(), queue_arn: invalid_arn.to_string(),
filter: None, filter: None,
@@ -7833,7 +7830,7 @@ mod tests {
let result = process_topic_configurations( let result = process_topic_configurations(
&mut event_rules, &mut event_rules,
Some(vec![s3s::dto::TopicConfiguration { Some(vec![TopicConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()], events: vec!["s3:ObjectCreated:*".to_string().into()],
topic_arn: invalid_arn.to_string(), topic_arn: invalid_arn.to_string(),
filter: None, filter: None,
@@ -7859,7 +7856,7 @@ mod tests {
let result = process_lambda_configurations( let result = process_lambda_configurations(
&mut event_rules, &mut event_rules,
Some(vec![s3s::dto::LambdaFunctionConfiguration { Some(vec![LambdaFunctionConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()], events: vec!["s3:ObjectCreated:*".to_string().into()],
lambda_function_arn: invalid_arn.to_string(), lambda_function_arn: invalid_arn.to_string(),
filter: None, filter: None,
@@ -7885,7 +7882,7 @@ mod tests {
let result = process_queue_configurations( let result = process_queue_configurations(
&mut event_rules, &mut event_rules,
Some(vec![s3s::dto::QueueConfiguration { Some(vec![QueueConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()], events: vec!["s3:ObjectCreated:*".to_string().into()],
queue_arn: valid_arn.to_string(), queue_arn: valid_arn.to_string(),
filter: None, filter: None,
+6 -8
View File
@@ -55,7 +55,7 @@ pub struct UpdateCheckResult {
/// Latest version information /// Latest version information
pub latest_version: Option<VersionInfo>, pub latest_version: Option<VersionInfo>,
/// Check time /// Check time
pub check_time: chrono::DateTime<chrono::Utc>, pub check_time: jiff::Zoned,
} }
/// Version checker /// Version checker
@@ -146,7 +146,7 @@ impl VersionChecker {
update_available, update_available,
current_version, current_version,
latest_version: Some(version_info), latest_version: Some(version_info),
check_time: chrono::Utc::now(), check_time: jiff::Zoned::now(),
}; };
if result.update_available { if result.update_available {
@@ -194,8 +194,6 @@ mod tests {
#[test] #[test]
fn test_update_check_result() { fn test_update_check_result() {
use chrono::Utc;
// Test creating UpdateCheckResult with update available // Test creating UpdateCheckResult with update available
let version_info = VersionInfo { let version_info = VersionInfo {
version: "1.2.0".to_string(), version: "1.2.0".to_string(),
@@ -204,12 +202,12 @@ mod tests {
download_url: Some("https://github.com/rustfs/rustfs/releases/tag/v1.2.0".to_string()), download_url: Some("https://github.com/rustfs/rustfs/releases/tag/v1.2.0".to_string()),
}; };
let check_time = Utc::now(); let check_time = jiff::Zoned::now();
let result = UpdateCheckResult { let result = UpdateCheckResult {
update_available: true, update_available: true,
current_version: "1.1.0".to_string(), current_version: "1.1.0".to_string(),
latest_version: Some(version_info.clone()), latest_version: Some(version_info.clone()),
check_time, check_time: check_time.clone(),
}; };
debug!("Update check result: {:?}", serde_json::to_string(&result).unwrap()); debug!("Update check result: {:?}", serde_json::to_string(&result).unwrap());
@@ -253,7 +251,7 @@ mod tests {
release_notes: None, release_notes: None,
download_url: None, download_url: None,
}), }),
check_time: Utc::now(), check_time: jiff::Zoned::now(),
}; };
assert!(!no_update_result.update_available); assert!(!no_update_result.update_available);
@@ -264,7 +262,7 @@ mod tests {
update_available: false, update_available: false,
current_version: "1.1.0".to_string(), current_version: "1.1.0".to_string(),
latest_version: None, latest_version: None,
check_time: Utc::now(), check_time: jiff::Zoned::now(),
}; };
assert!(!error_result.update_available); assert!(!error_result.update_available);
+175 -41
View File
@@ -1,67 +1,201 @@
<# # Copyright 2024 RustFS Team
Copyright 2024 RustFS Team #
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Licensed under the Apache License, Version 2.0 (the "License"); $ErrorActionPreference = "Stop"
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 # Check if ./rustfs/static/index.html exists
if (-not (Test-Path "./rustfs/static/index.html")) {
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#>
# Check if static files need to be downloaded
if (-not (Test-Path .\rustfs\static\index.html)) {
Write-Host "Downloading rustfs-console-latest.zip" Write-Host "Downloading rustfs-console-latest.zip"
# Download rustfs-console-latest.zip
Invoke-WebRequest -Uri "https://dl.rustfs.com/artifacts/console/rustfs-console-latest.zip" -OutFile "tempfile.zip"
Invoke-WebRequest -Uri "https://dl.rustfs.com/artifacts/console/rustfs-console-latest.zip" -OutFile 'tempfile.zip' # Unzip
Expand-Archive -Path 'tempfile.zip' -DestinationPath '.\rustfs\static' -Force Expand-Archive -Path "tempfile.zip" -DestinationPath "./rustfs/static" -Force
Remove-Item tempfile.zip
# Remove temp file
Remove-Item "tempfile.zip"
} }
# Check if build should be skipped
if (-not $env:SKIP_BUILD) { if (-not $env:SKIP_BUILD) {
cargo build -p rustfs --bins cargo build -p rustfs --bins
} }
$current_dir = Get-Location $current_dir = Get-Location
Write-Host "Current directory: $current_dir"
# Create multiple test directories # Create directories
$testDirs = @("test0", "test1", "test2", "test3", "test4") 1..4 | ForEach-Object {
foreach ($dir in $testDirs) { New-Item -ItemType Directory -Force -Path "./target/volume/test$_" | Out-Null
$path = Join-Path -Path ".\target\volume" -ChildPath $dir
if (-not (Test-Path $path)) {
New-Item -ItemType Directory -Path $path -Force | Out-Null
}
} }
# Set environment variables
if (-not $env:RUST_LOG) { if (-not $env:RUST_LOG) {
$env:RUST_BACKTRACE = 1 $env:RUST_BACKTRACE = "1"
$env:RUST_LOG = "rustfs=debug,ecstore=debug,s3s=debug,iam=debug" $env:RUST_LOG = "rustfs=debug,ecstore=info,s3s=debug,iam=info,notify=info"
} }
# The following environment variables are commented out, uncomment them if needed # $env:RUSTFS_ERASURE_SET_DRIVE_COUNT = "5"
# $env:RUSTFS_ERASURE_SET_DRIVE_COUNT = 5
# $env:RUSTFS_STORAGE_CLASS_INLINE_BLOCK = "512 KB" # $env:RUSTFS_STORAGE_CLASS_INLINE_BLOCK = "512 KB"
$env:RUSTFS_VOLUMES = ".\target\volume\test{0...4}" $env:RUSTFS_VOLUMES = "./target/volume/test{1...4}"
# $env:RUSTFS_VOLUMES = ".\target\volume\test" # $env:RUSTFS_VOLUMES = "./target/volume/test"
$env:RUSTFS_ADDRESS = "127.0.0.1:9000" $env:RUSTFS_ADDRESS = ":9000"
$env:RUSTFS_CONSOLE_ENABLE = "true" $env:RUSTFS_CONSOLE_ENABLE = "true"
$env:RUSTFS_CONSOLE_ADDRESS = "127.0.0.1:9002" $env:RUSTFS_CONSOLE_ADDRESS = ":9001"
# $env:RUSTFS_SERVER_DOMAINS = "localhost:9000" # $env:RUSTFS_SERVER_DOMAINS = "localhost:9000"
# Change to the actual configuration file path, obs.example.toml is for reference only # HTTPS certificate directory
$env:RUSTFS_OBS_CONFIG = ".\deploy\config\obs.example.toml" # $env:RUSTFS_TLS_PATH = "./deploy/certs"
# Observability related configuration
# $env:RUSTFS_OBS_ENDPOINT = "http://localhost:4318" # OpenTelemetry Collector address
# RustFS OR OTEL exporter configuration
# $env:RUSTFS_OBS_TRACE_ENDPOINT = "http://localhost:4318/v1/traces" # OpenTelemetry Collector trace address
# $env:OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = "http://localhost:14318/v1/traces"
# $env:RUSTFS_OBS_METRIC_ENDPOINT = "http://localhost:9090/api/v1/otlp/v1/metrics" # OpenTelemetry Collector metric address
# $env:OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = "http://localhost:9090/api/v1/otlp/v1/metrics"
# $env:RUSTFS_OBS_LOG_ENDPOINT = "http://loki:3100/otlp/v1/logs" # OpenTelemetry Collector logs address
# $env:OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = "http://loki:3100/otlp/v1/logs"
# $env:RUSTFS_OBS_USE_STDOUT = "true" # Whether to use standard output
# $env:RUSTFS_OBS_SAMPLE_RATIO = "2.0" # Sample ratio, between 0.0-1.0
# $env:RUSTFS_OBS_METER_INTERVAL = "1" # Sampling interval in seconds
# $env:RUSTFS_OBS_SERVICE_NAME = "rustfs" # Service name
# $env:RUSTFS_OBS_SERVICE_VERSION = "0.1.0" # Service version
$env:RUSTFS_OBS_ENVIRONMENT = "develop" # Environment name
$env:RUSTFS_OBS_LOGGER_LEVEL = "info" # Log level
$env:RUSTFS_OBS_LOG_STDOUT_ENABLED = "false" # Whether to enable local stdout logging
$env:RUSTFS_OBS_LOG_DIRECTORY = "$current_dir/deploy/logs" # Log directory
$env:RUSTFS_OBS_LOG_ROTATION_TIME = "hour" # Log rotation time unit
$env:RUSTFS_OBS_LOG_ROTATION_SIZE_MB = "100" # Log rotation size in MB
$env:RUSTFS_OBS_LOG_POOL_CAPA = "10240" # Log pool capacity
$env:RUSTFS_OBS_LOG_MESSAGE_CAPA = "32768" # Log message capacity
$env:RUSTFS_OBS_LOG_FLUSH_MS = "300" # Log flush interval in milliseconds
# tokio runtime
$env:RUSTFS_RUNTIME_WORKER_THREADS = "16"
$env:RUSTFS_RUNTIME_MAX_BLOCKING_THREADS = "1024"
$env:RUSTFS_RUNTIME_THREAD_PRINT_ENABLED = "false"
$env:RUSTFS_RUNTIME_THREAD_STACK_SIZE = 1024 * 1024
$env:RUSTFS_RUNTIME_THREAD_KEEP_ALIVE = "60"
$env:RUSTFS_RUNTIME_GLOBAL_QUEUE_INTERVAL = "31"
$env:OTEL_INSTRUMENTATION_NAME = "rustfs"
$env:OTEL_INSTRUMENTATION_VERSION = "0.1.1"
$env:OTEL_INSTRUMENTATION_SCHEMA_URL = "https://opentelemetry.io/schemas/1.31.0"
$env:OTEL_INSTRUMENTATION_ATTRIBUTES = "env=production"
# notify
# $env:RUSTFS_NOTIFY_WEBHOOK_ENABLE = "on"
# $env:RUSTFS_NOTIFY_WEBHOOK_ENDPOINT = "http://[::]:3020/webhook"
# $env:RUSTFS_NOTIFY_WEBHOOK_QUEUE_DIR = "$current_dir/deploy/logs/notify"
# $env:RUSTFS_NOTIFY_WEBHOOK_ENABLE_PRIMARY = "on"
# $env:RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY = "http://[::]:3020/webhook"
# $env:RUSTFS_NOTIFY_WEBHOOK_QUEUE_DIR_PRIMARY = "$current_dir/deploy/logs/notify"
# $env:RUSTFS_NOTIFY_WEBHOOK_ENABLE_MASTER = "on"
# $env:RUSTFS_NOTIFY_WEBHOOK_ENDPOINT_MASTER = "http://[::]:3020/webhook"
# $env:RUSTFS_NOTIFY_WEBHOOK_QUEUE_DIR_MASTER = "$current_dir/deploy/logs/notify"
# $env:RUSTFS_AUDIT_WEBHOOK_ENABLE = "on"
# $env:RUSTFS_AUDIT_WEBHOOK_ENDPOINT = "http://[::]:3020/webhook"
# $env:RUSTFS_AUDIT_WEBHOOK_QUEUE_DIR = "$current_dir/deploy/logs/audit"
# $env:RUSTFS_AUDIT_WEBHOOK_ENABLE_PRIMARY = "on"
# $env:RUSTFS_AUDIT_WEBHOOK_ENDPOINT_PRIMARY = "http://[::]:3020/webhook"
# $env:RUSTFS_AUDIT_WEBHOOK_QUEUE_DIR_PRIMARY = "$current_dir/deploy/logs/audit"
# $env:RUSTFS_AUDIT_WEBHOOK_ENABLE_MASTER = "on"
# $env:RUSTFS_AUDIT_WEBHOOK_ENDPOINT_MASTER = "http://[::]:3020/webhook"
# $env:RUSTFS_AUDIT_WEBHOOK_QUEUE_DIR_MASTER = "$current_dir/deploy/logs/audit"
# $env:RUSTFS_POLICY_PLUGIN_URL = "http://localhost:8181/v1/data/rustfs/authz/allow"
# $env:RUSTFS_POLICY_PLUGIN_AUTH_TOKEN = "your-opa-token"
$env:RUSTFS_NS_SCANNER_INTERVAL = "60"
# $env:RUSTFS_SKIP_BACKGROUND_TASK = "true"
# Storage level compression
# $env:RUSTFS_COMPRESSION_ENABLED = "true"
# HTTP Response Compression
# $env:RUSTFS_COMPRESS_ENABLE = "on"
# Example 1: Compress text files and logs
# $env:RUSTFS_COMPRESS_ENABLE = "on"
# $env:RUSTFS_COMPRESS_EXTENSIONS = ".txt,.log,.csv"
# $env:RUSTFS_COMPRESS_MIME_TYPES = "text/*"
# $env:RUSTFS_COMPRESS_MIN_SIZE = "1000"
# Example 2: Compress JSON and XML API responses
# $env:RUSTFS_COMPRESS_ENABLE = "on"
# $env:RUSTFS_COMPRESS_EXTENSIONS = ".json,.xml"
# $env:RUSTFS_COMPRESS_MIME_TYPES = "application/json,application/xml"
# $env:RUSTFS_COMPRESS_MIN_SIZE = "1000"
# Example 3: Comprehensive web content compression
# $env:RUSTFS_COMPRESS_ENABLE = "on"
# $env:RUSTFS_COMPRESS_EXTENSIONS = ".html,.css,.js,.json,.xml,.txt,.svg"
# $env:RUSTFS_COMPRESS_MIME_TYPES = "text/*,application/json,application/xml,application/javascript,image/svg+xml"
# $env:RUSTFS_COMPRESS_MIN_SIZE = "1000"
# Example 4: Compress only large text files
# $env:RUSTFS_COMPRESS_ENABLE = "on"
# $env:RUSTFS_COMPRESS_EXTENSIONS = ".txt,.log"
# $env:RUSTFS_COMPRESS_MIME_TYPES = "text/*"
# $env:RUSTFS_COMPRESS_MIN_SIZE = "10240"
# $env:RUSTFS_REGION = "us-east-1"
$env:RUSTFS_ENABLE_SCANNER = "false"
$env:RUSTFS_ENABLE_HEAL = "false"
# Object cache configuration
$env:RUSTFS_OBJECT_CACHE_ENABLE = "true"
# Profiling configuration
$env:RUSTFS_ENABLE_PROFILING = "false"
# Heal configuration queue size
$env:RUSTFS_HEAL_QUEUE_SIZE = "10000"
# rustfs trust system CA certificates
$env:RUSTFS_TRUST_SYSTEM_CA = "true"
# Enable FTP server
$env:RUSTFS_FTPS_ENABLE = "false"
# Increase timeout for high-latency network storage
# $env:RUSTFS_LOCK_ACQUIRE_TIMEOUT = "120"
# Reduce timeout for low-latency local storage
$env:RUSTFS_LOCK_ACQUIRE_TIMEOUT = "30"
# Check command line arguments
if ($args.Count -gt 0) { if ($args.Count -gt 0) {
$env:RUSTFS_VOLUMES = $args[0] $env:RUSTFS_VOLUMES = $args[0]
} }
# Run the program # Enable jemalloc for memory profiling
cargo run --bin rustfs if (-not $env:MALLOC_CONF) {
$env:MALLOC_CONF = "prof:true,prof_active:true,lg_prof_sample:16,log:true,narenas:2,lg_chunk:21,background_thread:true,dirty_decay_ms:1000,muzzy_decay_ms:1000"
}
# Start webhook server
# Start-Process cargo -ArgumentList "run --example webhook -p rustfs-notify" -NoNewWindow
# Start main service
# To run with profiling enabled:
# cargo run --profile profiling --bin rustfs
# To run in release mode:
# cargo run --profile release --bin rustfs
# To run in debug mode:
cargo run --bin rustfs