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",
]
[[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]]
name = "jobserver"
version = "0.1.34"
@@ -6594,6 +6635,15 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "potential_utf"
version = "0.1.4"
@@ -7617,6 +7667,7 @@ dependencies = [
"hyper",
"hyper-util",
"jemalloc_pprof",
"jiff",
"libc",
"libsystemd",
"libunftp",
@@ -7959,7 +8010,7 @@ dependencies = [
"async-trait",
"base64",
"chacha20poly1305",
"chrono",
"jiff",
"md5 0.8.0",
"moka",
"rand 0.10.0-rc.6",
@@ -8220,7 +8271,7 @@ dependencies = [
"serde_json",
"serial_test",
"tempfile",
"thiserror 2.0.17",
"thiserror 2.0.18",
"time",
"tokio",
"tokio-test",
+1
View File
@@ -163,6 +163,7 @@ zeroize = { version = "1.8.2", features = ["derive"] }
# Time and Date
chrono = { version = "0.4.43", features = ["serde"] }
humantime = "2.3.0"
jiff = { version = "0.2.18", features = ["serde"] }
time = { version = "0.3.45", features = ["std", "parsing", "formatting", "macros", "serde"] }
# Utilities and Tools
+1 -1
View File
@@ -32,7 +32,7 @@ workspace = true
async-trait = { workspace = true }
tokio = { workspace = true, features = ["full"] }
uuid = { workspace = true, features = ["serde"] }
chrono = { workspace = true, features = ["serde"] }
jiff = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
tracing = { workspace = true }
+12 -11
View File
@@ -24,6 +24,7 @@ use aes_gcm::{
aead::{Aead, KeyInit},
};
use async_trait::async_trait;
use jiff::Zoned;
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -51,8 +52,8 @@ struct StoredMasterKey {
status: KeyStatus,
description: Option<String>,
metadata: HashMap<String, String>,
created_at: chrono::DateTime<chrono::Utc>,
rotated_at: Option<chrono::DateTime<chrono::Utc>>,
created_at: Zoned,
rotated_at: Option<Zoned>,
created_by: Option<String>,
/// Encrypted key material (32 bytes for AES-256)
encrypted_key_material: Vec<u8>,
@@ -69,7 +70,7 @@ struct DataKeyEnvelope {
encrypted_key: Vec<u8>,
nonce: Vec<u8>,
encryption_context: HashMap<String, String>,
created_at: chrono::DateTime<chrono::Utc>,
created_at: Zoned,
}
impl LocalKmsClient {
@@ -182,8 +183,8 @@ impl LocalKmsClient {
status: master_key.status.clone(),
description: master_key.description.clone(),
metadata: master_key.metadata.clone(),
created_at: master_key.created_at,
rotated_at: master_key.rotated_at,
created_at: master_key.created_at.clone(),
rotated_at: master_key.rotated_at.clone(),
created_by: master_key.created_by.clone(),
encrypted_key_material,
nonce,
@@ -317,7 +318,7 @@ impl KmsClient for LocalKmsClient {
encrypted_key: encrypted_key.clone(),
nonce,
encryption_context: request.encryption_context.clone(),
created_at: chrono::Utc::now(),
created_at: Zoned::now(),
};
// 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?;
master_key.version += 1;
master_key.rotated_at = Some(chrono::Utc::now());
master_key.rotated_at = Some(Zoned::now());
// Generate new key material
let key_material = Self::generate_key_material();
@@ -648,7 +649,7 @@ impl KmsBackend for LocalKmsBackend {
key_state: KeyState::Enabled,
key_usage: request.key_usage,
description: request.description,
creation_date: chrono::Utc::now(),
creation_date: Zoned::now(),
deletion_date: None,
origin: "KMS".to_string(),
key_manager: "CUSTOMER".to_string(),
@@ -768,7 +769,7 @@ impl KmsBackend for LocalKmsBackend {
key_usage: master_key.usage,
key_state: KeyState::PendingDeletion, // AWS KMS compatibility
creation_date: master_key.created_at,
deletion_date: Some(chrono::Utc::now()),
deletion_date: Some(Zoned::now()),
key_manager: "CUSTOMER".to_string(),
origin: "AWS_KMS".to_string(),
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()));
}
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;
(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!
+11 -10
View File
@@ -20,6 +20,7 @@ use crate::error::{KmsError, Result};
use crate::types::*;
use async_trait::async_trait;
use base64::{Engine as _, engine::general_purpose};
use jiff::Zoned;
use rand::RngCore;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -47,7 +48,7 @@ struct VaultKeyData {
/// Key usage type
usage: KeyUsage,
/// Key creation timestamp
created_at: chrono::DateTime<chrono::Utc>,
created_at: Zoned,
/// Key status
status: KeyStatus,
/// Key version
@@ -156,7 +157,7 @@ impl VaultKmsClient {
let key_data = VaultKeyData {
algorithm: "AES_256".to_string(),
usage: request.key_usage.clone(),
created_at: chrono::Utc::now(),
created_at: Zoned::now(),
status: KeyStatus::Active,
version: 1,
description: request.description.clone(),
@@ -252,7 +253,7 @@ impl KmsClient for VaultKmsClient {
.map_err(|e| KmsError::cryptographic_error("decode", e.to_string()))?,
key_spec: request.key_spec.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 {
algorithm: algorithm.to_string(),
usage: KeyUsage::EncryptDecrypt,
created_at: chrono::Utc::now(),
created_at: Zoned::now(),
status: KeyStatus::Active,
version: 1,
description: None,
@@ -458,7 +459,7 @@ impl KmsClient for VaultKmsClient {
description: None, // Rotate preserves existing description (would need key lookup)
metadata: key_data.metadata,
created_at: key_data.created_at,
rotated_at: Some(chrono::Utc::now()),
rotated_at: Some(Zoned::now()),
created_by: None,
};
@@ -549,7 +550,7 @@ impl KmsBackend for VaultKmsBackend {
key_state: KeyState::Enabled,
key_usage: request.key_usage,
description: request.description,
creation_date: chrono::Utc::now(),
creation_date: Zoned::now(),
deletion_date: None,
origin: "VAULT".to_string(),
key_manager: "VAULT".to_string(),
@@ -664,7 +665,7 @@ impl KmsBackend for VaultKmsBackend {
} else {
// For non-pending keys, mark as 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
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.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
self.update_key_metadata_in_storage(key_id, &key_metadata).await?;
Some(deletion_date.to_rfc3339())
Some(deletion_date.to_string())
};
Ok(DeleteKeyResponse {
+4 -3
View File
@@ -154,6 +154,7 @@ impl KmsCache {
mod tests {
use super::*;
use crate::types::{KeyState, KeyUsage};
use jiff::Zoned;
use std::time::Duration;
#[derive(Debug, Clone)]
@@ -202,7 +203,7 @@ mod tests {
key_state: KeyState::Enabled,
key_usage: KeyUsage::EncryptDecrypt,
description: Some("Test key".to_string()),
creation_date: chrono::Utc::now(),
creation_date: Zoned::now(),
deletion_date: None,
origin: "KMS".to_string(),
key_manager: "CUSTOMER".to_string(),
@@ -252,7 +253,7 @@ mod tests {
key_state: KeyState::Enabled,
key_usage: KeyUsage::EncryptDecrypt,
description: Some("TTL test key".to_string()),
creation_date: chrono::Utc::now(),
creation_date: Zoned::now(),
deletion_date: None,
origin: "KMS".to_string(),
key_manager: "CUSTOMER".to_string(),
@@ -283,7 +284,7 @@ mod tests {
key_state: KeyState::Enabled,
key_usage: KeyUsage::EncryptDecrypt,
description: None,
creation_date: chrono::Utc::now(),
creation_date: Zoned::now(),
deletion_date: None,
origin: "KMS".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::types::*;
use base64::Engine;
use jiff::Zoned;
use rand::random;
use std::collections::HashMap;
use std::io::Cursor;
@@ -339,7 +340,7 @@ impl ObjectEncryptionService {
iv,
tag: Some(tag),
encryption_context: context,
encrypted_at: chrono::Utc::now(),
encrypted_at: Zoned::now(),
original_size,
encrypted_data_key: data_key.ciphertext_blob,
};
@@ -482,7 +483,7 @@ impl ObjectEncryptionService {
iv,
tag: Some(tag),
encryption_context: context,
encrypted_at: chrono::Utc::now(),
encrypted_at: Zoned::now(),
original_size,
encrypted_data_key: Vec::new(), // Empty for SSE-C
};
@@ -695,7 +696,7 @@ impl ObjectEncryptionService {
iv,
tag,
encryption_context,
encrypted_at: chrono::Utc::now(),
encrypted_at: Zoned::now(),
original_size: 0, // Not available from headers
encrypted_data_key,
})
@@ -809,7 +810,7 @@ mod tests {
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]),
encryption_context: HashMap::from([("bucket".to_string(), "test-bucket".to_string())]),
encrypted_at: chrono::Utc::now(),
encrypted_at: Zoned::now(),
original_size: 100,
encrypted_data_key: vec![1, 2, 3, 4],
};
+12 -12
View File
@@ -14,7 +14,7 @@
//! Core type definitions for KMS operations
use chrono::{DateTime, Utc};
use jiff::Zoned;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;
@@ -37,7 +37,7 @@ pub struct DataKey {
/// Associated metadata
pub metadata: HashMap<String, String>,
/// Key creation timestamp
pub created_at: DateTime<Utc>,
pub created_at: Zoned,
}
impl DataKey {
@@ -61,7 +61,7 @@ impl DataKey {
ciphertext,
key_spec,
metadata: HashMap::new(),
created_at: Utc::now(),
created_at: Zoned::now(),
}
}
@@ -112,9 +112,9 @@ pub struct MasterKey {
/// Associated metadata
pub metadata: HashMap<String, String>,
/// Key creation timestamp
pub created_at: DateTime<Utc>,
pub created_at: Zoned,
/// Key last rotation timestamp
pub rotated_at: Option<DateTime<Utc>>,
pub rotated_at: Option<Zoned>,
/// Key creator/owner
pub created_by: Option<String>,
}
@@ -139,7 +139,7 @@ impl MasterKey {
status: KeyStatus::Active,
description: None,
metadata: HashMap::new(),
created_at: Utc::now(),
created_at: Zoned::now(),
rotated_at: None,
created_by,
}
@@ -170,7 +170,7 @@ impl MasterKey {
status: KeyStatus::Active,
description,
metadata: HashMap::new(),
created_at: Utc::now(),
created_at: Zoned::now(),
rotated_at: None,
created_by,
}
@@ -219,9 +219,9 @@ pub struct KeyInfo {
/// Key tags
pub tags: HashMap<String, String>,
/// Key creation timestamp
pub created_at: DateTime<Utc>,
pub created_at: Zoned,
/// Key last rotation timestamp
pub rotated_at: Option<DateTime<Utc>>,
pub rotated_at: Option<Zoned>,
/// Key creator
pub created_by: Option<String>,
}
@@ -612,7 +612,7 @@ pub struct EncryptionMetadata {
/// Encryption context
pub encryption_context: HashMap<String, String>,
/// Timestamp when encrypted
pub encrypted_at: DateTime<Utc>,
pub encrypted_at: Zoned,
/// Size of original data
pub original_size: u64,
/// Encrypted data key
@@ -697,9 +697,9 @@ pub struct KeyMetadata {
/// Key description
pub description: Option<String>,
/// Key creation timestamp
pub creation_date: DateTime<Utc>,
pub creation_date: Zoned,
/// Key deletion timestamp
pub deletion_date: Option<DateTime<Utc>>,
pub deletion_date: Option<Zoned>,
/// Key origin
pub origin: String,
/// Key manager
+1
View File
@@ -99,6 +99,7 @@ rustls-pemfile = { workspace = true }
# Time and Date
chrono = { workspace = true }
jiff = { workspace = true }
time = { workspace = true, features = ["parsing", "formatting", "serde"] }
# Utilities and Tools
+1 -1
View File
@@ -555,7 +555,7 @@ async fn health_check(method: Method) -> Response {
let body_json = json!({
"status": health_status,
"service": "rustfs-console",
"timestamp": chrono::Utc::now().to_rfc3339(),
"timestamp": jiff::Zoned::now().to_string(),
"version": env!("CARGO_PKG_VERSION"),
"details": details,
"uptime": std::time::SystemTime::now()
+1 -1
View File
@@ -132,7 +132,7 @@ impl Operation for HealthCheckHandler {
let health_info = json!({
"status": "ok",
"service": "rustfs-endpoint",
"timestamp": chrono::Utc::now().to_rfc3339(),
"timestamp": jiff::Zoned::now().to_string(),
"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::{admin, config, version};
use chrono::Datelike;
use rustfs_config::{DEFAULT_UPDATE_CHECK, ENV_UPDATE_CHECK};
use rustfs_ecstore::bucket::metadata_sys;
use rustfs_notify::notifier_global;
@@ -26,7 +25,7 @@ use tracing::{debug, error, info, instrument, warn};
#[instrument]
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
info!("RustFS Object Storage Server");
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]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
fn main() -> Result<()> {
fn main() {
let runtime = server::get_tokio_runtime_builder()
.build()
.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<()> {
// Parse the obtained parameters
@@ -365,9 +370,10 @@ async fn run(opt: config::Opt) -> Result<()> {
init_update_check();
println!(
"RustFS server started successfully at {}, current time: {}",
"RustFS server version: {} started successfully at {}, current time: {}",
version::get_version(),
&server_address,
chrono::offset::Utc::now().to_string()
jiff::Zoned::now()
);
info!(target: "rustfs::main::run","server started successfully at {}", &server_address);
// 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"))]
mod linux_impl {
use chrono::Utc;
use jemalloc_pprof::PROF_CTL;
use pprof::protos::Message;
use rustfs_config::{
@@ -104,7 +103,7 @@ mod linux_impl {
/// Generate timestamp string for filenames
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
+2 -2
View File
@@ -85,7 +85,7 @@ pub(crate) async fn start_audit_system() -> AuditResult<()> {
info!(
target: "rustfs::main::start_audit_system",
"Audit system started successfully with time: {}.",
chrono::Utc::now()
jiff::Zoned::now()
);
Ok(())
}
@@ -114,7 +114,7 @@ pub(crate) async fn stop_audit_system() -> AuditResult<()> {
// Prepare before stopping
system.close().await?;
// Record after stopping
info!("Audit system stopped at {}", chrono::Utc::now());
info!("Audit system stopped at {}", jiff::Zoned::now());
Ok(())
} else {
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)
let api_endpoints = format!("{protocol}://{local_ip_str}:{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 {
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();
println!(
"RustFS Worker Thread running - initializing resources time: {:?}, thread id: {:?}",
chrono::Utc::now().to_rfc3339(),
jiff::Zoned::now().to_string(),
id
);
})
@@ -140,7 +140,7 @@ pub(crate) fn get_tokio_runtime_builder() -> tokio::runtime::Builder {
let id = std::thread::current().id();
println!(
"RustFS Worker Thread stopping - cleaning up resources time: {:?}, thread id: {:?}",
chrono::Utc::now().to_rfc3339(),
jiff::Zoned::now().to_string(),
id
)
});
+7 -10
View File
@@ -34,7 +34,6 @@ use crate::storage::{
};
use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD};
use bytes::Bytes;
use chrono::{DateTime, Utc};
use datafusion::arrow::{
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(),
tag: None,
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 },
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
if tag_count > 0 {
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);
} else {
warn!("Failed to parse x-amz-tagging-count header value, skipping");
@@ -4105,9 +4104,7 @@ impl S3 for FS {
if dsc.replicate_any() {
let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-timestamp");
let now: DateTime<Utc> = Utc::now();
let formatted_time = now.to_rfc3339();
opts.user_defined.insert(k, formatted_time);
opts.user_defined.insert(k, jiff::Zoned::now().to_string());
let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-status");
opts.user_defined.insert(k, dsc.pending_status().unwrap_or_default());
}
@@ -7807,7 +7804,7 @@ mod tests {
let result = process_queue_configurations(
&mut event_rules,
Some(vec![s3s::dto::QueueConfiguration {
Some(vec![QueueConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()],
queue_arn: invalid_arn.to_string(),
filter: None,
@@ -7833,7 +7830,7 @@ mod tests {
let result = process_topic_configurations(
&mut event_rules,
Some(vec![s3s::dto::TopicConfiguration {
Some(vec![TopicConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()],
topic_arn: invalid_arn.to_string(),
filter: None,
@@ -7859,7 +7856,7 @@ mod tests {
let result = process_lambda_configurations(
&mut event_rules,
Some(vec![s3s::dto::LambdaFunctionConfiguration {
Some(vec![LambdaFunctionConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()],
lambda_function_arn: invalid_arn.to_string(),
filter: None,
@@ -7885,7 +7882,7 @@ mod tests {
let result = process_queue_configurations(
&mut event_rules,
Some(vec![s3s::dto::QueueConfiguration {
Some(vec![QueueConfiguration {
events: vec!["s3:ObjectCreated:*".to_string().into()],
queue_arn: valid_arn.to_string(),
filter: None,
+6 -8
View File
@@ -55,7 +55,7 @@ pub struct UpdateCheckResult {
/// Latest version information
pub latest_version: Option<VersionInfo>,
/// Check time
pub check_time: chrono::DateTime<chrono::Utc>,
pub check_time: jiff::Zoned,
}
/// Version checker
@@ -146,7 +146,7 @@ impl VersionChecker {
update_available,
current_version,
latest_version: Some(version_info),
check_time: chrono::Utc::now(),
check_time: jiff::Zoned::now(),
};
if result.update_available {
@@ -194,8 +194,6 @@ mod tests {
#[test]
fn test_update_check_result() {
use chrono::Utc;
// Test creating UpdateCheckResult with update available
let version_info = VersionInfo {
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()),
};
let check_time = Utc::now();
let check_time = jiff::Zoned::now();
let result = UpdateCheckResult {
update_available: true,
current_version: "1.1.0".to_string(),
latest_version: Some(version_info.clone()),
check_time,
check_time: check_time.clone(),
};
debug!("Update check result: {:?}", serde_json::to_string(&result).unwrap());
@@ -253,7 +251,7 @@ mod tests {
release_notes: None,
download_url: None,
}),
check_time: Utc::now(),
check_time: jiff::Zoned::now(),
};
assert!(!no_update_result.update_available);
@@ -264,7 +262,7 @@ mod tests {
update_available: false,
current_version: "1.1.0".to_string(),
latest_version: None,
check_time: Utc::now(),
check_time: jiff::Zoned::now(),
};
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");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
$ErrorActionPreference = "Stop"
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.
#>
# Check if static files need to be downloaded
if (-not (Test-Path .\rustfs\static\index.html)) {
# Check if ./rustfs/static/index.html exists
if (-not (Test-Path "./rustfs/static/index.html")) {
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'
Expand-Archive -Path 'tempfile.zip' -DestinationPath '.\rustfs\static' -Force
Remove-Item tempfile.zip
# Unzip
Expand-Archive -Path "tempfile.zip" -DestinationPath "./rustfs/static" -Force
# Remove temp file
Remove-Item "tempfile.zip"
}
# Check if build should be skipped
if (-not $env:SKIP_BUILD) {
cargo build -p rustfs --bins
}
$current_dir = Get-Location
Write-Host "Current directory: $current_dir"
# Create multiple test directories
$testDirs = @("test0", "test1", "test2", "test3", "test4")
foreach ($dir in $testDirs) {
$path = Join-Path -Path ".\target\volume" -ChildPath $dir
if (-not (Test-Path $path)) {
New-Item -ItemType Directory -Path $path -Force | Out-Null
}
# Create directories
1..4 | ForEach-Object {
New-Item -ItemType Directory -Force -Path "./target/volume/test$_" | Out-Null
}
# Set environment variables
if (-not $env:RUST_LOG) {
$env:RUST_BACKTRACE = 1
$env:RUST_LOG = "rustfs=debug,ecstore=debug,s3s=debug,iam=debug"
$env:RUST_BACKTRACE = "1"
$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_VOLUMES = ".\target\volume\test{0...4}"
# $env:RUSTFS_VOLUMES = ".\target\volume\test"
$env:RUSTFS_ADDRESS = "127.0.0.1:9000"
$env:RUSTFS_VOLUMES = "./target/volume/test{1...4}"
# $env:RUSTFS_VOLUMES = "./target/volume/test"
$env:RUSTFS_ADDRESS = ":9000"
$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"
# Change to the actual configuration file path, obs.example.toml is for reference only
$env:RUSTFS_OBS_CONFIG = ".\deploy\config\obs.example.toml"
# HTTPS certificate directory
# $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) {
$env:RUSTFS_VOLUMES = $args[0]
}
# Run the program
cargo run --bin rustfs
# Enable jemalloc for memory profiling
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