@@ -487,54 +487,57 @@ replicated_partition::get_leader_epoch_last_offset_unbounded(
487487 last_local_term,
488488 is_read_replica);
489489
490- if (!is_read_replica && term > last_local_term) {
490+ if (is_read_replica) {
491+ if (!_partition->cloud_data_available ()) {
492+ // If we didn't sync the manifest yet the cloud_data_available will
493+ // return false. We can't call `get_cloud_term_last_offset` in this
494+ // case but we also can't use `first_local_offset` for read replica.
495+ co_return std::nullopt ;
496+ }
497+ auto last_offset = co_await _partition->get_cloud_term_last_offset (
498+ term);
499+ if (last_offset) {
500+ co_return last_offset;
501+ }
502+ // The term was not found in cloud storage.
503+ const auto highest_cloud_term = _partition->highest_cloud_term ();
504+ if (highest_cloud_term.has_value () && term > *highest_cloud_term) {
505+ // A read replica has no local log, so a term above the highest
506+ // cloud term is an unknown (future) epoch for it.
507+ co_return std::nullopt ;
508+ }
509+ // The term is below the earliest cloud segment; the next-highest term
510+ // still lives in cloud, so return the cloud start offset.
511+ co_return _partition->start_cloud_offset ();
512+ }
513+
514+ if (term > last_local_term) {
491515 // Request for term that is in the future
492516 co_return std::nullopt ;
493517 }
494518 // Look for the highest offset in the requested term, or the first offset
495519 // in the next term. This mirrors behavior in Kafka, see
496520 // https://github.com/apache/kafka/blob/97105a8e5812135515f5a0fa4d5ff554d80df2fe/storage/src/main/java/org/apache/kafka/storage/internals/epoch/LeaderEpochFileCache.java#L255-L281
497- if (!is_read_replica && term >= first_local_term) {
521+ if (term >= first_local_term) {
498522 auto last_offset = _partition->get_term_last_offset (term);
499523 if (last_offset) {
500524 co_return _translator->from_log_offset (*last_offset);
501525 }
502526 }
503- // The requested term falls below our earliest local segment.
504-
505- // Check cloud storage for a viable offset.
527+ // The requested term falls below our earliest local segment. Check cloud
528+ // storage for a viable offset.
506529 if (
507- is_read_replica
508- || (_partition->is_remote_fetch_enabled () && _partition->cloud_data_available ())) {
509- if (is_read_replica && !_partition->cloud_data_available ()) {
510- // If we didn't sync the manifest yet the cloud_data_available will
511- // return false. We can't call `get_cloud_term_last_offset` in this
512- // case but we also can't use `first_local_offset` for read replica.
513- co_return std::nullopt ;
514- }
530+ _partition->is_remote_fetch_enabled ()
531+ && _partition->cloud_data_available ()) {
515532 auto last_offset = co_await _partition->get_cloud_term_last_offset (
516533 term);
517534 if (last_offset) {
518535 co_return last_offset;
519536 }
520-
521- const auto highest_cloud_term = _partition->highest_cloud_term ();
522- if (is_read_replica) {
523- // The term was not found in cloud storage. A read replica has no
524- // local log, so a term above the highest cloud term is an unknown
525- // (future) epoch for it: return no value (an undefined epoch on the
526- // wire) rather than the cloud start offset, which would sit below
527- // the consumer's position and spuriously signal truncation.
528- if (highest_cloud_term.has_value () && term > *highest_cloud_term) {
529- co_return std::nullopt ;
530- }
531- // The term is below the earliest cloud segment; the next-highest
532- // term still lives in cloud, so return the cloud start offset.
533- co_return _partition->start_cloud_offset ();
534- }
535537 // The requested term is below the first local term (so its data is not
536538 // in the local log) and was not found in cloud storage. Here, we use
537539 // the highest cloud term to disambiguate two cases.
540+ const auto highest_cloud_term = _partition->highest_cloud_term ();
538541 if (highest_cloud_term.has_value () && term <= *highest_cloud_term) {
539542 // The term must be lower than the lowest cloud term: the
540543 // next-highest term still lives in cloud, so the answer is the
0 commit comments