@@ -197,6 +197,17 @@ T handle_error(
197197 std::to_underlying (result.error ())));
198198}
199199
200+ class counting_metastore : public cloud_topics ::l1::simple_metastore {
201+ public:
202+ ss::future<std::expected<void , errc>> set_start_offset (
203+ const model::topic_id_partition& tidp, kafka::offset o) override {
204+ ++set_start_offset_calls;
205+ return simple_metastore::set_start_offset (tidp, o);
206+ }
207+
208+ size_t set_start_offset_calls{0 };
209+ };
210+
200211} // namespace
201212
202213using namespace std ::chrono_literals;
@@ -224,6 +235,10 @@ class HousekeeperTest : public testing::Test {
224235 _l0_metastore.set_max_allowed_start_offset (offset);
225236 }
226237
238+ size_t l1_set_start_offset_calls () const {
239+ return _l1_metastore.set_start_offset_calls ;
240+ }
241+
227242 kafka::offset l1_start_offset () {
228243 auto result = _l1_metastore.get_offsets (_tidp).get ();
229244 if (!result.has_value ()) {
@@ -289,7 +304,7 @@ class HousekeeperTest : public testing::Test {
289304 model::topic_id_partition _tidp{
290305 model::create_topic_id (), model::partition_id{0 }};
291306 fake_l0_metastore _l0_metastore{_tidp, kafka::offset{0 }};
292- cloud_topics::l1::simple_metastore _l1_metastore;
307+ counting_metastore _l1_metastore;
293308 std::unique_ptr<retention_config_impl> _config_impl;
294309};
295310
@@ -848,3 +863,21 @@ TEST_F(HousekeeperTest, BumpEpochMultipleIdleCycles) {
848863 EXPECT_EQ (advance_epoch_calls ()[0 ], cloud_topics::cluster_epoch{10 });
849864 EXPECT_EQ (sync_to_next_placeholder_calls (), 1 );
850865}
866+
867+ TEST_F (HousekeeperTest, SyncStartOffsetSkipsRedundantRPC) {
868+ auto housekeeper = make_housekeeper ({});
869+ add_object ({.records = 100 , .size = 1_MiB});
870+ set_start_offset (kafka::offset{50 });
871+
872+ housekeeper.do_housekeeping ().get ();
873+ EXPECT_EQ (l1_set_start_offset_calls (), 1 );
874+
875+ // No change — should skip the call.
876+ housekeeper.do_housekeeping ().get ();
877+ EXPECT_EQ (l1_set_start_offset_calls (), 1 );
878+
879+ // Changed offset — should sync again.
880+ set_start_offset (kafka::offset{75 });
881+ housekeeper.do_housekeeping ().get ();
882+ EXPECT_EQ (l1_set_start_offset_calls (), 2 );
883+ }
0 commit comments