refactor(targets): unify queue/connectivity handling and coverage (#2953)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: marshawcoco <marshawcoco@gmail.com>
This commit is contained in:
houseme
2026-05-14 12:31:23 +08:00
committed by GitHub
parent bdb98598d2
commit 81754d80b3
64 changed files with 9613 additions and 2800 deletions
+15 -45
View File
@@ -13,13 +13,13 @@
// limitations under the License.
use crate::{
StoreError, Target, TargetLog,
StoreError, Target,
arn::TargetID,
error::TargetError,
store::{Key, QueueStore, Store},
store::{Key, Store},
target::{
ChannelTargetType, EntityTarget, QueuedPayload, QueuedPayloadMeta, TargetDeliveryCounters, TargetDeliverySnapshot,
TargetType, queue_store_subdir_name,
TargetType, build_queued_payload_with_records, open_target_queue_store, persist_queued_payload_to_store,
},
};
use async_trait::async_trait;
@@ -30,7 +30,7 @@ use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use tracing::{error, info, instrument};
use tracing::{info, instrument};
#[derive(Debug, Clone)]
pub struct NATSArgs {
@@ -195,22 +195,14 @@ where
pub fn new(id: String, args: NATSArgs) -> Result<Self, TargetError> {
args.validate()?;
let target_id = TargetID::new(id, ChannelTargetType::Nats.as_str().to_string());
let queue_store = if !args.queue_dir.is_empty() {
let base_path = PathBuf::from(&args.queue_dir);
let specific_queue_path = base_path.join(queue_store_subdir_name(ChannelTargetType::Nats.as_str(), &target_id.id));
let extension = match args.target_type {
TargetType::AuditLog => rustfs_config::audit::AUDIT_STORE_EXTENSION,
TargetType::NotifyEvent => rustfs_config::notify::NOTIFY_STORE_EXTENSION,
};
let store = QueueStore::<QueuedPayload>::new(specific_queue_path, args.queue_limit, extension);
if let Err(e) = store.open() {
error!(target_id = %target_id, error = %e, "Failed to open store for NATS target");
return Err(TargetError::Storage(format!("{e}")));
}
Some(Box::new(store) as Box<dyn Store<QueuedPayload, Error = StoreError, Key = Key> + Send + Sync>)
} else {
None
};
let queue_store = open_target_queue_store(
&args.queue_dir,
args.queue_limit,
args.target_type,
ChannelTargetType::Nats.as_str(),
&target_id,
"Failed to open store for NATS target",
)?;
Ok(Self {
id: target_id,
@@ -241,22 +233,7 @@ where
}
fn build_queued_payload(&self, event: &EntityTarget<E>) -> Result<QueuedPayload, TargetError> {
let object_name = crate::target::decode_object_name(&event.object_name)?;
let key = format!("{}/{}", event.bucket_name, object_name);
let log = TargetLog {
event_name: event.event_name,
key,
records: vec![event.clone()],
};
let body = serde_json::to_vec(&log).map_err(|e| TargetError::Serialization(format!("Failed to serialize event: {e}")))?;
let meta = QueuedPayloadMeta::new(
event.event_name,
event.bucket_name.clone(),
event.object_name.clone(),
"application/json",
body.len(),
);
Ok(QueuedPayload::new(meta, body))
build_queued_payload_with_records(event, vec![event.clone()])
}
async fn send_body(&self, body: Vec<u8>) -> Result<(), TargetError> {
@@ -298,16 +275,9 @@ where
};
if let Some(store) = &self.store {
let encoded = match queued.encode() {
Ok(encoded) => encoded,
Err(err) => {
self.delivery_counters.record_final_failure();
return Err(TargetError::Storage(format!("Failed to encode queued payload: {err}")));
}
};
if let Err(e) = store.put_raw(&encoded) {
if let Err(e) = persist_queued_payload_to_store(store.as_ref(), &queued) {
self.delivery_counters.record_final_failure();
return Err(TargetError::Storage(format!("Failed to save event to store: {e}")));
return Err(e);
}
Ok(())
} else {