@@ -20,9 +20,9 @@ use tracing::{debug, error, warn};
2020
2121use restate_core:: ShutdownError ;
2222use restate_rocksdb:: RocksDbReadPerfGuard ;
23- use restate_types:: logs:: { KeyFilter , LogletOffset , OffsetWatch , SequenceNumber , TailState } ;
23+ use restate_types:: logs:: { KeyFilter , LogletOffset , OffsetWatch , SequenceNumber } ;
2424
25- use crate :: loglet:: { Loglet , LogletReadStream , OperationError } ;
25+ use crate :: loglet:: { LogletReadStream , OperationError } ;
2626use crate :: providers:: local_loglet:: LogStoreError ;
2727use crate :: providers:: local_loglet:: record_format:: decode_and_filter_record;
2828use crate :: { LogEntry , Result } ;
@@ -37,12 +37,9 @@ pub(crate) struct LocalLogletReadStream {
3737 serde_buffer : BytesMut ,
3838 // the next record this stream will attempt to read
3939 read_pointer : LogletOffset ,
40- /// stop when read_pointer is at or beyond this offset
41- last_known_tail : LogletOffset ,
4240 readable_tail_watch : BoxStream < ' static , LogletOffset > ,
4341 readable_tail : LogletOffset ,
4442 iterator : DBRawIteratorWithThreadMode < ' static , DB > ,
45- tail_watch : BoxStream < ' static , TailState < LogletOffset > > ,
4643 terminated : bool ,
4744 // IMPORTANT: Do not reorder, this should be dropped last since `iterator` holds a reference
4845 // into the underlying database.
@@ -64,7 +61,7 @@ unsafe fn ignore_iterator_lifetime<'a>(
6461}
6562
6663impl LocalLogletReadStream {
67- pub ( crate ) async fn create (
64+ pub ( crate ) fn create (
6865 loglet : Arc < LocalLoglet > ,
6966 filter : KeyFilter ,
7067 from_offset : LogletOffset ,
@@ -95,12 +92,6 @@ impl LocalLogletReadStream {
9592 ) ;
9693
9794 let log_store = & loglet. log_store ;
98- let mut tail_watch = loglet. watch_tail ( ) ;
99- let last_known_tail = tail_watch
100- . next ( )
101- . await
102- . expect ( "loglet watch returns tail pointer" )
103- . offset ( ) ;
10495
10596 // ## Safety:
10697 // the iterator is guaranteed to be dropped before the loglet is dropped, we hold to the
@@ -123,8 +114,6 @@ impl LocalLogletReadStream {
123114 read_pointer : from_offset,
124115 iterator : iter,
125116 terminated : false ,
126- tail_watch,
127- last_known_tail,
128117 readable_tail_watch : Box :: pin ( readable_tail. to_stream ( ) ) ,
129118 readable_tail : readable_tail. get ( ) ,
130119 } )
@@ -154,8 +143,15 @@ impl Stream for LocalLogletReadStream {
154143 }
155144
156145 let perf_guard = RocksDbReadPerfGuard :: new ( "local-loglet-next" ) ;
146+ let mut filtered_from = None ;
157147 loop {
158148 if self . read_pointer >= self . readable_tail {
149+ if let Some ( filtered_from) = filtered_from {
150+ return Poll :: Ready ( Some ( Ok ( LogEntry :: new_filtered_gap (
151+ filtered_from,
152+ self . read_pointer . prev ( ) ,
153+ ) ) ) ) ;
154+ }
159155 let maybe_readable_tail = match self . readable_tail_watch . poll_next_unpin ( cx) {
160156 Poll :: Ready ( tail) => tail,
161157 Poll :: Pending => {
@@ -174,36 +170,6 @@ impl Stream for LocalLogletReadStream {
174170 }
175171 }
176172 }
177- // Are we reading after commit offset?
178- // We are at tail. We need to wait until new records have been released.
179- if self . read_pointer >= self . last_known_tail {
180- let maybe_tail_state = match self . tail_watch . poll_next_unpin ( cx) {
181- Poll :: Ready ( t) => t,
182- Poll :: Pending => {
183- perf_guard. forget ( ) ;
184- return Poll :: Pending ;
185- }
186- } ;
187-
188- match maybe_tail_state {
189- Some ( tail_state) => {
190- // tail has been updated.
191- self . last_known_tail = tail_state. offset ( ) ;
192- continue ;
193- }
194- None => {
195- // system shutdown. Or that the loglet has been unexpectedly shutdown.
196- self . terminated = true ;
197- return Poll :: Ready ( Some ( Err ( OperationError :: Shutdown ( ShutdownError ) ) ) ) ;
198- }
199- }
200- }
201- // tail has been updated.
202- let last_known_tail = self . last_known_tail ;
203-
204- // assert that we are behind tail
205- assert ! ( last_known_tail > self . read_pointer) ;
206-
207173 // Trim point is the slot **before** the first readable record (if it exists)
208174 // trim point might have been updated since last time.
209175 let trim_point =
@@ -213,10 +179,11 @@ impl Stream for LocalLogletReadStream {
213179 assert ! ( self . read_pointer > LogletOffset :: from( 0 ) ) ;
214180
215181 if self . read_pointer < head_offset {
216- let trim_gap = LogEntry :: new_trim_gap ( self . read_pointer , trim_point) ;
182+ let gap_to = trim_point. min ( self . readable_tail . prev ( ) ) ;
183+ let trim_gap = LogEntry :: new_trim_gap ( self . read_pointer , gap_to) ;
217184 // next record should be beyond at the head
218- self . read_pointer = head_offset ;
219- let key = RecordKey :: new ( self . loglet_id , trim_point ) ;
185+ self . read_pointer = gap_to . next ( ) ;
186+ let key = RecordKey :: new ( self . loglet_id , gap_to ) ;
220187 // park the iterator at the trim point, next iteration will seek it forward.
221188 let key_bytes = key. encode_and_split ( & mut self . serde_buffer ) ;
222189 self . iterator . seek ( key_bytes) ;
@@ -251,7 +218,7 @@ impl Stream for LocalLogletReadStream {
251218 loglet_id = self . loglet_id,
252219 read_pointer = %self . read_pointer,
253220 trim_point = %potentially_different_trim_point,
254- last_known_tail = %self . last_known_tail ,
221+ readable_tail = %self . readable_tail ,
255222 "poll_next() has moved to a non-existent record, that should not happen!"
256223 ) ;
257224 panic ! ( "poll_next() has moved to a non-existent record, that should not happen!" ) ;
@@ -283,7 +250,7 @@ impl Stream for LocalLogletReadStream {
283250 if let Some ( record) = maybe_record {
284251 return Poll :: Ready ( Some ( Ok ( LogEntry :: new_data ( key. offset , record) ) ) ) ;
285252 }
286- // Didn't match, loop and read the next record if possible.
253+ filtered_from . get_or_insert ( key . offset ) ;
287254 }
288255 }
289256}
0 commit comments