Skip to content

[CORE-15021] Cloud Topics: Level Zero GC delete pipeline#29050

Merged
oleiman merged 5 commits into
redpanda-data:devfrom
oleiman:ct/core-15021/gc-delete-pipeline
Jan 7, 2026
Merged

[CORE-15021] Cloud Topics: Level Zero GC delete pipeline#29050
oleiman merged 5 commits into
redpanda-data:devfrom
oleiman:ct/core-15021/gc-delete-pipeline

Conversation

@oleiman

@oleiman oleiman commented Dec 18, 2025

Copy link
Copy Markdown
Member

This PR adds a work_queue for delete operation in level_zero_gc, with the general goal of overlapping list & delete. Napkin math suggests that sequential paging list operations will dominate GC latency at low to moderate throughput, so we want to hide any additional delete latency behind the usually more expensive list.

Request concurrency & memory usage of the pipeline are governed by a pair of semaphores - one to limit the memory consumption of outstanding GC-eligible object keys, the other to limit the number of in-flight delete operations going on in the background.

Since work_queue tasks are processed sequentially, if a particular task blocks waiting for the request semaphore (i.e. before being pushed to the background), subsequent tasks will stay in the queue rather than stacking up on the semaphore.

Similarly, each iteration of the GC loop will try to page through the entire level_zero/data prefix, queueing up pages of work as it goes. If the page semaphore is exhausted before we reach the last page of list results, the iteration ends and we reenter the loop after a configurable delay, giving the delete worker a chance to burn down some of the outstanding work.

Backports Required

  • none - not a bug fix
  • none - this is a backport
  • none - issue does not exist in previous branches
  • none - papercut/not impactful enough to backport
  • v25.3.x
  • v25.2.x
  • v25.1.x

Release Notes

  • none

@oleiman oleiman self-assigned this Dec 18, 2025
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from 2b52b11 to f24b2cf Compare December 18, 2025 19:55
@oleiman oleiman changed the title Ct/core 15021/gc delete pipeline [CORE-15021] Cloud Topics: Level Zero GC delete pipeline Dec 18, 2025
@oleiman oleiman marked this pull request as ready for review December 18, 2025 19:56
Copilot AI review requested due to automatic review settings December 18, 2025 19:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a pipelined delete mechanism for Level Zero garbage collection in Cloud Topics, enabling concurrent deletion operations and handling paginated object listings.

Key changes:

  • Adds concurrent delete pipeline with semaphores to control in-flight operations and memory usage
  • Implements pagination support for object listing with continuation tokens
  • Introduces work queue for managing asynchronous delete operations

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/v/cloud_topics/level_zero/gc/level_zero_gc.h Adds object_storage interface pagination support, semaphores for concurrency control, work queue, and continuation token state
src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Implements pipelined deletion with continuation token handling, page-based memory limiting, and asynchronous delete workers
src/v/cloud_topics/level_zero/gc/tests/level_zero_gc_tests.cc Adds test infrastructure for pagination simulation and new test cases for multi-page deletion, concurrent operations, and clean shutdown
src/v/cloud_topics/level_zero/gc/tests/BUILD Adds mutex dependency for test synchronization
src/v/cloud_topics/level_zero/gc/BUILD Adds semaphore and work_queue dependencies

Comment thread src/v/cloud_topics/level_zero/gc/tests/level_zero_gc_tests.cc Outdated
Comment thread src/v/cloud_topics/level_zero/gc/tests/level_zero_gc_tests.cc Outdated
Comment thread src/v/cloud_topics/level_zero/gc/tests/level_zero_gc_tests.cc Outdated
Comment thread src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Outdated
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch 3 times, most recently from 7ee19e0 to 8a894e1 Compare December 19, 2025 04:27
@oleiman oleiman requested a review from Copilot December 19, 2025 04:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Comment thread src/v/cloud_topics/level_zero/gc/tests/level_zero_gc_tests.cc
Comment thread src/v/cloud_topics/level_zero/gc/tests/level_zero_gc_tests.cc
Comment thread src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Outdated
Comment thread src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Outdated
Comment thread src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Outdated
Comment thread src/v/cloud_topics/level_zero/gc/tests/level_zero_gc_tests.cc
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from 8a894e1 to 598065d Compare December 19, 2025 06:05
@vbotbuildovich

vbotbuildovich commented Dec 19, 2025

Copy link
Copy Markdown
Collaborator

CI test results

test results on build#78192
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
MountUnmountIcebergTest test_simple_remount {"cloud_storage_type": 1} integration https://buildkite.com/redpanda/redpanda/builds/78192#019b3549-141b-4000-8e63-a1029385314b FLAKY 7/11 Test PASSES after retries.No significant increase in flaky rate(baseline=0.1822, p0=0.2693, reject_threshold=0.0100. adj_baseline=0.4531, p1=0.2595, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=MountUnmountIcebergTest&test_method=test_simple_remount
test results on build#78227
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
LogCompactionTxRemovalTest test_tx_control_batch_removal null integration https://buildkite.com/redpanda/redpanda/builds/78227#019b3830-76fe-43fa-9b85-c53d76fcd1ee FLAKY 10/11 Test PASSES after retries.No significant increase in flaky rate(baseline=0.0000, p0=1.0000, reject_threshold=0.0100. adj_baseline=0.1000, p1=0.3487, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=LogCompactionTxRemovalTest&test_method=test_tx_control_batch_removal
test results on build#78261
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
ShadowLinkingRandomOpsTest test_node_operations {"failures": true} integration https://buildkite.com/redpanda/redpanda/builds/78261#019b3eec-c6b9-4a46-9088-a60c811dbe79 FLAKY 19/21 Test PASSES after retries.No significant increase in flaky rate(baseline=0.0027, p0=0.0530, reject_threshold=0.0100. adj_baseline=0.1000, p1=0.3917, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ShadowLinkingRandomOpsTest&test_method=test_node_operations
test results on build#78427
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
NodesDecommissioningTest test_decommission_status null integration https://buildkite.com/redpanda/redpanda/builds/78427#019b61eb-9936-4e1a-b801-7b00ced276f1 FLAKY 10/11 Test PASSES after retries.No significant increase in flaky rate(baseline=0.0533, p0=1.0000, reject_threshold=0.0100. adj_baseline=0.1516, p1=0.1932, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=NodesDecommissioningTest&test_method=test_decommission_status
NodesDecommissioningTest test_flipping_decommission_recommission {"cloud_topic": true, "node_is_alive": false} integration https://buildkite.com/redpanda/redpanda/builds/78427#019b61ed-27ff-4434-8dac-8472141a0ac3 FLAKY 17/21 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0028, p0=0.0000, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=NodesDecommissioningTest&test_method=test_flipping_decommission_recommission
SIPartitionMovementTest test_cross_shard {"cloud_storage_type": 1, "num_to_upgrade": 0, "with_cloud_topics": true} integration https://buildkite.com/redpanda/redpanda/builds/78427#019b61ed-2801-4827-bdf0-190d8edcf3ea FLAKY 8/11 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0100, p0=0.0043, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=SIPartitionMovementTest&test_method=test_cross_shard
test results on build#78431
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
NodesDecommissioningTest test_decommissioning_finishes_after_manual_cancellation {"cloud_topic": true, "delete_topic": false} integration https://buildkite.com/redpanda/redpanda/builds/78431#019b6d0e-4042-4a8f-bddf-2124d9d315f2 FLAKY 9/11 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0000, p0=0.0000, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=NodesDecommissioningTest&test_method=test_decommissioning_finishes_after_manual_cancellation
NodesDecommissioningTest test_flipping_decommission_recommission {"cloud_topic": true, "node_is_alive": false} integration https://buildkite.com/redpanda/redpanda/builds/78431#019b6d0e-4038-4469-9950-8e81af5668d2 FLAKY 8/11 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0041, p0=0.0007, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=NodesDecommissioningTest&test_method=test_flipping_decommission_recommission
WriteCachingFailureInjectionE2ETest test_crash_all {"use_transactions": false} integration https://buildkite.com/redpanda/redpanda/builds/78431#019b6d0e-4038-4469-9950-8e81af5668d2 FLAKY 26/31 Test PASSES after retries.No significant increase in flaky rate(baseline=0.0723, p0=0.1684, reject_threshold=0.0100. adj_baseline=0.2016, p1=0.2482, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=WriteCachingFailureInjectionE2ETest&test_method=test_crash_all
test results on build#78590
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
CloudTopicsL0GCTest test_l0_gc {"cloud_storage_type": 2} integration https://buildkite.com/redpanda/redpanda/builds/78590#019b946d-3ee3-4c50-ab0e-9d1bc83d5fc0 FAIL 0/11 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0000, p0=0.0000, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=CloudTopicsL0GCTest&test_method=test_l0_gc
CloudTopicsL0GCTest test_l0_gc {"cloud_storage_type": 2} integration https://buildkite.com/redpanda/redpanda/builds/78590#019b946e-c1c0-4700-b440-c54059318515 FAIL 0/11 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0000, p0=0.0000, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=CloudTopicsL0GCTest&test_method=test_l0_gc
CloudTopicsL0GCTest test_l0_gc {"cloud_storage_type": 1} integration https://buildkite.com/redpanda/redpanda/builds/78590#019b946d-3ede-4eb6-806d-08997d65a593 FAIL 0/11 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0000, p0=0.0000, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=CloudTopicsL0GCTest&test_method=test_l0_gc
CloudTopicsL0GCTest test_l0_gc {"cloud_storage_type": 1} integration https://buildkite.com/redpanda/redpanda/builds/78590#019b946e-c1b5-4fa7-97dc-2a6dc95683d5 FAIL 0/11 Test FAILS after retries.Significant increase in flaky rate(baseline=0.0000, p0=0.0000, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=CloudTopicsL0GCTest&test_method=test_l0_gc
WriteCachingFailureInjectionE2ETest test_crash_all {"use_transactions": false} integration https://buildkite.com/redpanda/redpanda/builds/78590#019b946e-c1b8-4d47-9233-b2656d2e8e76 FLAKY 13/21 Test FAILS after retries.Significant increase in flaky rate(baseline=0.1175, p0=0.0060, reject_threshold=0.0100) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=WriteCachingFailureInjectionE2ETest&test_method=test_crash_all
test results on build#78600
test_class test_method test_arguments test_kind job_url test_status passed reason test_history
MountUnmountIcebergTest test_simple_remount {"cloud_storage_type": 1} integration https://buildkite.com/redpanda/redpanda/builds/78600#019b94d9-8fac-4101-a0a6-8dacf5dcaf44 FLAKY 10/11 Test PASSES after retries.No significant increase in flaky rate(baseline=0.2020, p0=1.0000, reject_threshold=0.0100. adj_baseline=0.4918, p1=0.0011, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=MountUnmountIcebergTest&test_method=test_simple_remount
ShadowLinkingRandomOpsTest test_node_operations {"failures": true} integration https://buildkite.com/redpanda/redpanda/builds/78600#019b94d8-8d0f-45c5-8daf-67c05190a578 FLAKY 18/21 Test PASSES after retries.No significant increase in flaky rate(baseline=0.0503, p0=0.2665, reject_threshold=0.0100. adj_baseline=0.1435, p1=0.4373, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=ShadowLinkingRandomOpsTest&test_method=test_node_operations
WriteCachingFailureInjectionE2ETest test_crash_all {"use_transactions": false} integration https://buildkite.com/redpanda/redpanda/builds/78600#019b94d9-8faa-4512-9787-efd7ab64a5d9 FLAKY 9/11 Test PASSES after retries.No significant increase in flaky rate(baseline=0.1160, p0=0.7087, reject_threshold=0.0100. adj_baseline=0.3093, p1=0.1354, trust_threshold=0.5000) https://redpanda.metabaseapp.com/dashboard/87-tests?tab=142-dt-individual-test-history&test_class=WriteCachingFailureInjectionE2ETest&test_method=test_crash_all

@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from 598065d to 9a76a9e Compare December 19, 2025 19:28
@oleiman oleiman requested a review from dotnwat December 19, 2025 19:28
Comment thread src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Outdated
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from 9a76a9e to 658edf0 Compare December 21, 2025 02:51
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from 658edf0 to d5af28b Compare December 27, 2025 21:57
@vbotbuildovich

vbotbuildovich commented Dec 27, 2025

Copy link
Copy Markdown
Collaborator

Retry command for Build#78427

please wait until all jobs are finished before running the slash command

/ci-repeat 1
skip-redpanda-build
skip-units
skip-rebase
tests/rptest/tests/partition_movement_test.py::SIPartitionMovementTest.test_cross_shard@{"cloud_storage_type":1,"num_to_upgrade":0,"with_cloud_topics":true}
tests/rptest/tests/nodes_decommissioning_test.py::NodesDecommissioningTest.test_flipping_decommission_recommission@{"cloud_topic":true,"node_is_alive":false}

@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from d5af28b to c1df2d6 Compare December 30, 2025 01:58
@oleiman

oleiman commented Dec 30, 2025

Copy link
Copy Markdown
Member Author

CI Failures:

@vbotbuildovich

vbotbuildovich commented Dec 30, 2025

Copy link
Copy Markdown
Collaborator

Retry command for Build#78431

please wait until all jobs are finished before running the slash command

/ci-repeat 1
skip-redpanda-build
skip-units
skip-rebase
tests/rptest/tests/nodes_decommissioning_test.py::NodesDecommissioningTest.test_decommissioning_finishes_after_manual_cancellation@{"cloud_topic":true,"delete_topic":false}
tests/rptest/tests/nodes_decommissioning_test.py::NodesDecommissioningTest.test_flipping_decommission_recommission@{"cloud_topic":true,"node_is_alive":false}

cd_log.debug,
"Received error listing objects during L0 GC: {}",
candidate_objects.error());
co_return std::unexpected(collection_error::service_error);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the comment below

/ TODO: fairly naive approach to caching the token. if the request
// fails, we start over,

what does start over mean? does it mean that here in the error case ("!candidate_objects.has_value()") that we should reset the token?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it looks like I misplaced the optional::reset while splitting out this commit from a later one.

Comment thread src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Outdated
Comment thread src/v/cloud_topics/level_zero/gc/level_zero_gc.cc Outdated
u.emplace(
seastar::consume_units(page_sem_, object_keys_total_bytes));
}
delete_worker_.submit([this,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wonder if ssx/actor.h would work here? in start create a new actor. in pause/stop you'd destroy the current actor. but similar simplification for work queue might exist?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ssx/actor

first I'm hearing of it, but at a quick glance it looks pretty close.

Comment on lines +276 to +294
ssx::work_queue delete_worker_;
// TODO: configurable limits?
// max number of in-flight delete ops
ssx::semaphore delete_sem_{5, "ct/gc/delete"};
// control (approximate) total memory held by gc-eligible list pages in
// flight (these may be queued depending on delete concurrency)
ssx::semaphore page_sem_{1_MiB, "ct/gc/page"};
seastar::abort_source delete_as_{};
seastar::gate gate_{};

seastar::future<> worker();
seastar::future<> delete_worker(
std::vector<cloud_storage_clients::client::list_bucket_item>,
ssx::semaphore_units) noexcept;
enum class collection_error : int8_t;
seastar::future<std::expected<size_t, collection_error>> try_to_collect();
seastar::future<std::expected<size_t, collection_error>>
do_try_to_collect(std::optional<cluster_epoch>&);
std::optional<ss::sstring> continuation_token_;

@dotnwat dotnwat Jan 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of having new work queue, semaphores, gates, abort sources all within this existing class, should we instead factor out paging/deletion into separate "workers" that are self-contained with a simple interface so that level_zero_gc is managing them at a higher level of abstraction (e.g. start/pause/stop)?

@oleiman oleiman Jan 5, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead factor out paging/deletion

yeah maybe so.

separate "workers" that are self-contained with a simple interface

Not sure I follow "separate workers". I rather like the work queue itself as a primitive source of backpressure, so in my mind we could just factor this new code into a separate class basically as is and expose some single-method async API to the GC loop.

Did you have something more granular in mind?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

factor this new code

or maybe this is just ssx::actor

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I follow "separate workers". I rather like the work queue itself as a primitive source of backpressure, so in my mind we could just factor this new code into a separate class basically as is and expose some single-method async API to the GC loop.

Right, nothing wrong with keeping the work queue, I'm talking about hiding the other complexity (semaphores, abort sources, gates, etc...)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool cool. yeah will do.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. if ssx::actor is the better choice it'll be a bit easier to swap that in.

@oleiman oleiman marked this pull request as draft January 6, 2026 05:03
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from c1df2d6 to 21b123c Compare January 6, 2026 05:04
@oleiman

oleiman commented Jan 6, 2026

Copy link
Copy Markdown
Member Author

force push rebase dev

- config points
- swap 'deleted' vector<object> for unordered_map<key>
- mutual exclusion for list & delete handlers

Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch 2 times, most recently from cd09435 to 8ba02b6 Compare January 6, 2026 17:26
@oleiman oleiman marked this pull request as ready for review January 6, 2026 17:27
@vbotbuildovich

vbotbuildovich commented Jan 6, 2026

Copy link
Copy Markdown
Collaborator

Retry command for Build#78590

please wait until all jobs are finished before running the slash command

/ci-repeat 1
skip-redpanda-build
skip-units
skip-rebase
tests/rptest/tests/cloud_topics/l0_gc_test.py::CloudTopicsL0GCTest.test_l0_gc@{"cloud_storage_type":1}
tests/rptest/tests/cloud_topics/l0_gc_test.py::CloudTopicsL0GCTest.test_l0_gc@{"cloud_storage_type":2}
tests/rptest/tests/write_caching_fi_e2e_test.py::WriteCachingFailureInjectionE2ETest.test_crash_all@{"use_transactions":false}

@oleiman oleiman marked this pull request as draft January 6, 2026 18:35
In general, we expect sequential list operations to dominate GC latency.
With that in mind, this commit introduces list_delete_worker to manage and
dispatch outstanding pages of GC-eligible object keys, the idea being that the
_processing_ of a page of objects should not block grabbing the next one.

This worker includes a "page semaphore" to limit the total volume of object
keys held in memory at once. Precise accounting is not the goal here.
We just want to avoid growing the backlog of delete tasks unbounded.

Delete requests are dispatched sequentially but execute in the background.
Another semaphore limits the number of background delete requests in flight
at one time.

Note that splitting a given remote::delete_objects payload into API-sized
batches is handled internally to cloud_io::remote, so we may want to rejigger
the concurrency in this layer a bit.

Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
Limited by the the semaphore in list_delete_worker.

Signed-off-by: Oren Leiman <oren.leiman@redpanda.com>
@oleiman oleiman force-pushed the ct/core-15021/gc-delete-pipeline branch from 8ba02b6 to 11f5d23 Compare January 6, 2026 19:25
@oleiman oleiman marked this pull request as ready for review January 6, 2026 19:25
Comment on lines +109 to +112
worker_.submit([this,
o = std::move(objects),
u = std::move(u).value()]() mutable {
return do_delete_objects(std::move(o), std::move(u));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's unclear to me what value the worker provides if the worker turns around and backgrounds the work you gave it. can you clarify its role?

if it because you want to be able to block on the delete_sem, then you could acquire the delete_sem in the background. that is, have many inflight background tasks that each acquire the delete_sem.

that would mean that you'd want to probably limit the number of background tasks that are created (i.e. limit the producer/paging side), but presumably that already exists otherwise the worker's queue would fill up (maybe that is the !delete_worker_->has_capacity())?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

want to be able to block on the delete_sem

yes, that

what value the worker provides...[vs having] many inflight background tasks that each acquire the delete_sem

just erring on the side of fewer background fibers I guess. it feels subjectively better to stack pending work up on a queue we control vs having an arbitrary number of blocked tasks in the background, but I'm not sure there's an empirical reason to prefer one or the other.

I think we had an issue in tiered storage where we pushed some work into the background, wrongly assuming that some higher level concurrency control would supply enough back pressure. But maybe blocking on delete_sem is good enough for this use case.

std::optional<cluster_epoch> max_gc_epoch;
size_t total_eligible{0};
while (delete_worker_->has_capacity()) {
auto res = co_await do_try_to_collect(std::ref(max_gc_epoch));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of introducing an input/output reference parameter, can we pull the max_gc_epoch query out into this function and pass it in as a value? from the looks of it do_try_collect won't recompute it, so a single query here reused across invocations would be equivalent?

@oleiman oleiman Jan 6, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

single query here reused across invocations would be equivalent?

fair enough. i assumed that putting the epoch after the LIST request was deliberate to avoid wasting an expensive computation, but I suppose reusing it across several pages is a good enough hedge against LIST failure.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeh makes sense. i'm fine with whatever, just always a fan of avoiding input/output parameters when possible.

@oleiman oleiman merged commit 41e0d59 into redpanda-data:dev Jan 7, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants