feat(listobjects): add guarded metadata-fast listing (#4311)

* feat(listobjects): add phase 0 observability metrics

* perf(listobjects): reduce gather metadata decoding

* test(listobjects): add adversarial listing coverage

* feat(listobjects): add source-aware cursor fields

* feat(listobjects): define index source modes

* feat(listobjects): model index rebuild health

* feat(listobjects): add opt-in index fallback gate

* feat(listobjects): verify index candidate pages

* docs(listobjects): add rollout runbook

* docs(listobjects): untrack baseline fixtures

* feat(listobjects): add opt-in key-only provider

* feat(listobjects): add index verification metrics

* perf(listobjects): gate list metrics on get stage switch

* feat(listobjects): bind provider health generation

* feat(listobjects): add persistent key-only provider

* feat(listobjects): bind persistent provider lifecycle

* feat(listobjects): track persistent index mutations

* feat(listobjects): persist index mutation checkpoints

* fix(listobjects): aggregate benchmark metric snapshots

* feat(listobjects): store journal in system namespace

* chore(listobjects): report fallback reasons in bench

* test(listobjects): verify metadata-fast stale fallbacks

* feat(listobjects): serve metadata-fast snapshots behind guardrails

* test(listobjects): add metadata-fast chaos bench

* fix(listobjects): attribute metadata-fast fallback metrics

* test(listobjects): add metadata-fast fallback chaos probes

* test(listobjects): add quorum journal chaos guardrails

* fix(listobjects): satisfy pre-pr clippy gate

* docs(listobjects): untrack rollout runbook

* fix(ecstore): remove redundant heal error conversion

* test(filemeta): satisfy replication info clippy

----

Co-Authored-By: heihutu <heihutu@gmail.com>
This commit is contained in:
houseme
2026-07-07 01:38:52 +08:00
committed by GitHub
parent 0271abc14d
commit 25193ee6cf
9 changed files with 6033 additions and 77 deletions
File diff suppressed because it is too large Load Diff
+37 -9
View File
@@ -352,7 +352,13 @@ impl crate::storage_api_contracts::object::ObjectIO for ECStore {
}
#[instrument(level = "debug", skip(self, data))]
async fn put_object(&self, bucket: &str, object: &str, data: &mut PutObjReader, opts: &ObjectOptions) -> Result<ObjectInfo> {
enqueue_transition_after_write(self.handle_put_object(bucket, object, data, opts).await, LcEventSrc::S3PutObject).await
let result =
enqueue_transition_after_write(self.handle_put_object(bucket, object, data, opts).await, LcEventSrc::S3PutObject)
.await;
if result.is_ok() {
list_objects::observe_list_objects_mutation(self, bucket).await;
}
result
}
}
@@ -418,22 +424,34 @@ impl crate::storage_api_contracts::object::ObjectOperations for ECStore {
src_opts: &ObjectOptions,
dst_opts: &ObjectOptions,
) -> Result<ObjectInfo> {
enqueue_transition_after_write(
let result = enqueue_transition_after_write(
self.handle_copy_object(src_bucket, src_object, dst_bucket, dst_object, src_info, src_opts, dst_opts)
.await,
LcEventSrc::S3CopyObject,
)
.await
.await;
if result.is_ok() {
list_objects::observe_list_objects_mutation(self, dst_bucket).await;
}
result
}
#[instrument(skip(self))]
async fn delete_object_version(&self, bucket: &str, object: &str, fi: &FileInfo, force_del_marker: bool) -> Result<()> {
self.handle_delete_object_version(bucket, object, fi, force_del_marker).await
let result = self.handle_delete_object_version(bucket, object, fi, force_del_marker).await;
if result.is_ok() {
list_objects::observe_list_objects_mutation(self, bucket).await;
}
result
}
#[instrument(skip(self))]
async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result<ObjectInfo> {
self.handle_delete_object(bucket, object, opts).await
let result = self.handle_delete_object(bucket, object, opts).await;
if result.is_ok() {
list_objects::observe_list_objects_mutation(self, bucket).await;
}
result
}
#[instrument(skip(self))]
@@ -443,7 +461,12 @@ impl crate::storage_api_contracts::object::ObjectOperations for ECStore {
objects: Vec<ObjectToDelete>,
opts: ObjectOptions,
) -> (Vec<DeletedObject>, Vec<Option<Error>>) {
self.handle_delete_objects(bucket, objects, opts).await
let result = self.handle_delete_objects(bucket, objects, opts).await;
let success_count = result.1.iter().filter(|err| err.is_none()).count();
if success_count > 0 {
list_objects::observe_list_objects_mutations(self, bucket, success_count).await;
}
result
}
#[instrument(skip(self))]
@@ -660,12 +683,17 @@ impl crate::storage_api_contracts::multipart::MultipartOperations for ECStore {
uploaded_parts: Vec<CompletePart>,
opts: &ObjectOptions,
) -> Result<ObjectInfo> {
enqueue_transition_after_write(
self.handle_complete_multipart_upload(bucket, object, upload_id, uploaded_parts, opts)
let result = enqueue_transition_after_write(
self.clone()
.handle_complete_multipart_upload(bucket, object, upload_id, uploaded_parts, opts)
.await,
LcEventSrc::S3CompleteMultipartUpload,
)
.await
.await;
if result.is_ok() {
list_objects::observe_list_objects_mutation(self.as_ref(), bucket).await;
}
result
}
}