Skip to main content

krabka_remote_storage/
metadata_manager.rs

1//! The [`RemoteLogMetadataManager`] SPI, which stores and queries
2//! remote-segment metadata.
3
4use {
5    crate::{
6        error::RemoteStorageError,
7        metadata::{
8            RemoteLogSegmentMetadata, RemoteLogSegmentMetadataUpdate,
9            RemotePartitionDeleteMetadata, TopicIdPartition,
10        },
11    },
12    krabka_ids::LeaderEpoch,
13};
14
15/// SPI for the store that holds metadata about remote log segments.
16///
17/// The reference implementation is
18/// [`InmemoryRemoteLogMetadataManager`](crate::InmemoryRemoteLogMetadataManager);
19/// a production implementation stores the metadata in an internal topic, as
20/// Kafka's `TopicBasedRemoteLogMetadataManager` does. Implementations must be
21/// `Send + Sync`.
22///
23/// The lifecycle invariants every implementation enforces:
24///
25/// - The caller introduces a segment with
26///   [`add_remote_log_segment_metadata`](RemoteLogMetadataManager::add_remote_log_segment_metadata)
27///   in state
28///   [`CopySegmentStarted`](crate::RemoteLogSegmentState::CopySegmentStarted).
29/// - Every later change is an
30///   [`update_remote_log_segment_metadata`](RemoteLogMetadataManager::update_remote_log_segment_metadata)
31///   that follows a valid state transition.
32/// - Only
33///   [`CopySegmentFinished`](crate::RemoteLogSegmentState::CopySegmentFinished)
34///   segments are visible to the offset/epoch queries.
35pub trait RemoteLogMetadataManager: Send + Sync {
36    /// Records a newly-started segment copy. The metadata's state must be
37    /// [`CopySegmentStarted`](crate::RemoteLogSegmentState::CopySegmentStarted)
38    /// and its id must not already be known.
39    ///
40    /// # Errors
41    ///
42    /// Returns [`RemoteStorageError::InvalidAdd`] if the starting state is
43    /// wrong or the segment id is a duplicate.
44    fn add_remote_log_segment_metadata(
45        &self,
46        metadata: RemoteLogSegmentMetadata,
47    ) -> Result<(), RemoteStorageError>;
48
49    /// Advances a known segment's lifecycle state.
50    ///
51    /// # Errors
52    ///
53    /// Returns [`RemoteStorageError::SegmentNotFound`] if the segment is
54    /// unknown, or [`RemoteStorageError::InvalidSegmentTransition`] if the
55    /// transition is not permitted.
56    fn update_remote_log_segment_metadata(
57        &self,
58        update: RemoteLogSegmentMetadataUpdate,
59    ) -> Result<(), RemoteStorageError>;
60
61    /// Finds the finished segment that contains `offset` for the given
62    /// `leader_epoch`, if any.
63    ///
64    /// # Errors
65    ///
66    /// Returns [`RemoteStorageError`] only on an underlying store failure;
67    /// a simple "no such segment" is `Ok(None)`.
68    fn remote_log_segment_metadata(
69        &self,
70        topic_id_partition: &TopicIdPartition,
71        leader_epoch: LeaderEpoch,
72        offset: i64,
73    ) -> Result<Option<RemoteLogSegmentMetadata>, RemoteStorageError>;
74
75    /// The highest offset that the remote tier holds for `leader_epoch`.
76    ///
77    /// This is the maximum `end_offset` across the finished segments that
78    /// carry that epoch.
79    ///
80    /// # Errors
81    ///
82    /// Returns [`RemoteStorageError`] only on an underlying store failure.
83    fn highest_offset_for_epoch(
84        &self,
85        topic_id_partition: &TopicIdPartition,
86        leader_epoch: LeaderEpoch,
87    ) -> Result<Option<i64>, RemoteStorageError>;
88
89    /// All segments known for a partition, in `start_offset` order. The
90    /// state does not matter.
91    ///
92    /// # Errors
93    ///
94    /// Returns [`RemoteStorageError`] only on an underlying store failure.
95    fn list_remote_log_segments(
96        &self,
97        topic_id_partition: &TopicIdPartition,
98    ) -> Result<Vec<RemoteLogSegmentMetadata>, RemoteStorageError>;
99
100    /// All segments that carry `leader_epoch`, in `start_offset` order. The
101    /// state does not matter.
102    ///
103    /// # Errors
104    ///
105    /// Returns [`RemoteStorageError`] only on an underlying store failure.
106    fn list_remote_log_segments_by_epoch(
107        &self,
108        topic_id_partition: &TopicIdPartition,
109        leader_epoch: LeaderEpoch,
110    ) -> Result<Vec<RemoteLogSegmentMetadata>, RemoteStorageError>;
111
112    /// Records a partition-delete lifecycle event.
113    ///
114    /// # Errors
115    ///
116    /// Returns [`RemoteStorageError::InvalidPartitionDeleteTransition`] if
117    /// the transition is not permitted from the partition's current
118    /// delete-state.
119    fn put_remote_partition_delete_metadata(
120        &self,
121        metadata: RemotePartitionDeleteMetadata,
122    ) -> Result<(), RemoteStorageError>;
123
124    /// Whether this manager has applied every metadata event for
125    /// `topic_id_partition` that the metadata store had committed when the
126    /// call began.
127    ///
128    /// This is a read-your-peers'-writes check. Another broker can publish
129    /// an event, for example a `DeleteSegmentStarted` update, and wait for
130    /// the store to acknowledge it. A read on this manager that follows a
131    /// `true` answer sees that event. A `false` answer means the local view
132    /// can be stale, so the caller must not judge from it. A manager that
133    /// does not consume the partition's metadata answers `false`, because
134    /// it cannot vouch for the view.
135    ///
136    /// # Errors
137    ///
138    /// Returns [`RemoteStorageError::NotReady`] while the manager is still
139    /// catching up after it took on the partition, and
140    /// [`RemoteStorageError::Io`] if it cannot read the store's committed
141    /// position.
142    fn caught_up(&self, topic_id_partition: &TopicIdPartition) -> Result<bool, RemoteStorageError>;
143}