Repository navigation
CAS GC: cut batch deletes to the storage's batch-delete limit - #2484
Conversation
GC sent a write-once cohort (up to `gc_bulk_delete_chunk_keys`, 1000) as one `removeManyWriteOnce`, ignoring `objects_chunk_size_to_delete` on S3 and the single-key reality of storages without `DeleteObjects`. Add `IObjectStorage::batchDeleteKeyLimit` and `Backend::bulkDeleteKeyLimit` (forwarded by every decorator). `Gc::bulkDeleteChunkKeys` takes the smaller of the setting and that limit; `removeCohortWriteOnce` cuts the `manifest_deletes` and `cleanupRefObjects` cohorts into requests of that size. The cohort, its budget accounting and the one `authorityHolds` read per cohort are unchanged. The S3 delete paths also pass the store's error name into `S3Exception`: `isRefreshableCredentialError` recognises SDK-unmodelled errors only by `getExceptionName`. Tests: `CASBulkDeleteBackend` limit forwarding and clamping, GC cut for `manifest_deletes` and ref cleanup (no extra `gc/state` reads), and `CASS3BatchDelete` for the S3 limit and error names. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Mikhail Filimonov <mfilimonov@altinity.com>
PR #2484 CI TriageNo CI failure is caused by this PR. GitHub is red, and every red check is a pre-existing failure or an image scan. The pull request is already merged.
GitHub reports 344 successful checks, 129 skipped, and 45 failures. The 45 failures are duplicate commit-status contexts of 22 jobs, plus the aggregate
|
| Job | Test | What the log shows |
|---|---|---|
amd_binary, cas storage |
01164_detach_attach_partition_race |
Stderr warning CasWriteRetryLater: promote of detached/attaching_all_13_13_1 hit the unique-ref invariant. That string is already at CasPartWriteTxn.cpp:970 on the base. The diff does not touch it. amd_binary cas s3 storage passed, so this test passed there. 05008_cas_gc_snapshot_prune passed in the same job. |
amd_tsan, cas s3, 1/2 |
03823_optimize_dry_run_projections, 04033_tpc_ds_q37 |
Stdout matches the expected result. The fail reason is stderr: ConnectionGroup: Too many active sessions in group Disk. Same warning #2483 recorded on 04033. |
amd_tsan, cas s3, 2/2 |
04056_mutation_session_timezone_datetime_literals, 04338_async_insert_current_user, 02884_create_view_with_sql_security_option, 01164_detach_attach_partition_race |
Same ConnectionGroup stderr warning. Stdout for the mutation, async-insert, and view tests is the expected result. |
amd_msan, cas s3, 1/3 |
01019_alter_materialized_view_consistent |
Reference expects 1, the run printed 0, and inconsistencies stayed 0. The same test passed on the release, ASan, TSan, and arm CAS stateless jobs in this run. Upstream: 1 fail in 273,303 runs over 60 days. |
arm_asan_ubsan, azure |
02354_vector_search_rescoring_distance_in_select_list |
Float32 distance 0.1875 where the reference expects 0.203125. Same two numbers as #2483, whose merge-base failed this test 3 of 3. Upstream: 0 fails in 274,857 runs. The diff does not touch vector search. |
Sanitizer rows marked BROKEN in these jobs (Timeout! Processes left in process group, exit 159) matched the known sanitizer-timeout rule and did not fail the jobs on their own.
Stress and Grype
Stress test (arm_asan_ubsan):Hung check failed.fatal.logis empty. The server accepted00001_select_1. The hung query is a cancelled AST-fuzzer mutation of01730_distributed_group_by_no_merge_order_by_long(max_memory_usage100MB, elapsed ~699s). The other stress jobs in this run passed, includingarm_asan_ubsanwith S3 and everyamd_*CAS S3 stress job. #2483 failed this same job on a ready-probe timeout, a different mechanism.- Grype: alpine server image and keeper image. Base-image findings (zlib
CVE-2026-85091on the alpine server image; keeper also flags OpenSSL CVEs). The diff does not change image dependencies.infrastructure.
Coverage of the change
Unit tests passed under ASan, TSan, and MSan. 05008_cas_gc_snapshot_prune passed. CAS stress on S3 passed for amd debug, ASan, TSan, and MSan. Release and aarch64 CAS suites for engines, atomic insert, lightweight delete, and the other alter jobs passed.
The 60-day gh-data rates for this run were not re-queried. The CAS rates above are the measurements already recorded for #2437, #2351, and #2483 on the same error text. Stateless rates are from upstream default.checks plus the other CAS jobs in this run.
PR #2484 Distributed-Systems Audit
SummaryNo confirmed distributed-systems defects in the reviewed scope. A write-once cohort is still licensed once, then sent as consecutive requests of at most Model assumptions
Evidence
Coverage summary
LimitsStatic review of head The accepted tradeoffs, not scored as defects because a missed delete leaks storage and a repeated delete is the same key:
Operational ReadinessScope: GC phases 15 and 17 after PR #2484, head Primary flows (ranked by expected usage)
IssuesFlow 2: a store with a small batch limit2.1 The effective batch size is not in the GC log
Readiness verdict
Operator guidance
Recommended fixes
|
CAS GC sent a write-once delete cohort (up to
cas_gc_bulk_delete_chunk_keys, 1000 keys) as one request, ignoringobjects_chunk_size_to_deleteon S3 and the one-key limit of a storage withoutDeleteObjects. GC now cuts each cohort into requests of the storage's batch-delete limit. The S3 delete paths also keep the store's error name inS3Exception.Changes
IObjectStorage::batchDeleteKeyLimit(default 1).S3ObjectStoragereturnsobjects_chunk_size_to_delete, or 1 onceDeleteObjectsis known unsupported.Cas::Backend::bulkDeleteKeyLimit, forwarded by every decorator;kBulkDeleteMaxKeysfor the in-memory and the emulated backend.Gc::bulkDeleteChunkKeysis the smaller of the setting and that limit. Themanifest_deletesphase andcleanupRefObjectscut a cohort into requests of that size through the existingremoveChunkWriteOnceOrOneByOne. The cohort, its budget accounting and the oneauthorityHoldsread per cohort are unchanged.S3ObjectStorage::removeObjectsIfExistImplanddeleteFileFromS3pass the store's error name intoS3Exception:isRefreshableCredentialErrorrecognises errors the SDK does not model only bygetExceptionName.Risks / notes
IObjectStorage.h, one override and twothrowsites inS3ObjectStorage.cpp, onethrowsite insrc/IO/S3/deleteFileFromS3.cpp. The exception type and message are the same; only the name is added.objects_chunk_size_to_deletebelow 1000 now gets more, smallerDeleteObjectsrequests from GC phases 15 and 17.Testing
CAS*gate, debug and ASan. New:CASBulkDeleteBackendlimit forwarding and clamping (5 tests),CASGCManifestBulkDelete.StorageLimitCutsTheCohortIntoRequestsOfAtMostThatManyKeys,CASRefGc.RefObjectCleanupCutsRequestsToTheStorageLimitWithoutExtraAuthorityReads,CASS3BatchDelete(the S3 limit; error names for a whole-request error and for a per-key error in a 200 reply). WithbulkDeleteChunkKeysignoring the backend limit, both GC-level tests and twoCASBulkDeleteBackendtests fail.CASS3BatchDeleteerror-name test was not run against the oldthrowsites; no integration run on RustFS or S3.Related: #2483
Related: #2468
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
CAS GC batch deletes respect the storage's batch-delete limit (
objects_chunk_size_to_deleteon S3), and S3 delete errors keep the store's error name.Documentation entry for user-facing changes
docs/en/antalya/cas/configuration.md)CI/CD Options
Regression jobs to run: