@@ -87,11 +87,12 @@ pub async fn get_events(
8787 // The database query for 3 and 4 is combined into one step.
8888 //
8989 // 4 requires some additional logic to handle some edge cases:
90- // a) Query database
91- // b) if full page -> return page
90+ // a) if from_block_number > pending_block_number -> return empty result
91+ // b) Query database
92+ // c) if full page -> return page
9293 // check if there are matching events in the pending block
9394 // and return a continuation token for the pending block
94- // c ) else if empty / partially full -> append events from start of pending
95+ // d ) else if empty / partially full -> append events from start of pending
9596 // if there are more pending events return a continuation token
9697 // with the appropriate offset within the pending block
9798
@@ -134,27 +135,43 @@ pub async fn get_events(
134135 . transaction ( )
135136 . context ( "Creating database transaction" ) ?;
136137
137- // Handle the trivial (1) and (2 ) cases.
138+ // Handle the trivial (1), (2) and (4a ) cases.
138139 match ( & request. from_block , & request. to_block ) {
139- ( Some ( Pending ) , non_pending ) if * non_pending != Some ( Pending ) => {
140+ ( Some ( Pending ) , id ) if ! matches ! ( id , Some ( Pending ) | None ) => {
140141 return Ok ( types:: GetEventsResult {
141142 events : Vec :: new ( ) ,
142143 continuation_token : None ,
143144 } ) ;
144145 }
145- ( Some ( Pending ) , Some ( Pending ) ) => {
146+ ( Some ( Pending ) , Some ( Pending ) | None ) => {
146147 let pending = context
147148 . pending_data
148149 . get ( & transaction)
149150 . context ( "Querying pending data" ) ?;
150151 return get_pending_events ( & request, & pending, continuation_token) ;
151152 }
153+ ( Some ( BlockId :: Number ( from_block) ) , Some ( BlockId :: Pending ) ) => {
154+ let pending = context
155+ . pending_data
156+ . get ( & transaction)
157+ . context ( "Querying pending data" ) ?;
158+
159+ // `from_block` is larger than or equal to pending block's number
160+ if from_block >= & pending. number {
161+ return Ok ( types:: GetEventsResult {
162+ events : Vec :: new ( ) ,
163+ continuation_token : None ,
164+ } ) ;
165+ }
166+ }
152167 _ => { }
153168 }
154169
155170 let from_block = map_from_block_to_number ( & transaction, request. from_block ) ?;
156171 let to_block = map_to_block_to_number ( & transaction, request. to_block ) ?;
157172
173+ // Handle cases (3) and (4) where `from_block` is non-pending.
174+
158175 let ( from_block, requested_offset) = match continuation_token {
159176 Some ( token) => token. start_block_and_offset ( from_block) ?,
160177 None => ( from_block, 0 ) ,
@@ -460,10 +477,11 @@ impl std::fmt::Display for ContinuationToken {
460477
461478impl ContinuationToken {
462479 fn offset_in_block ( & self , block_number : BlockNumber ) -> Result < usize , GetEventsError > {
463- if self . block_number == block_number {
464- Ok ( self . offset )
465- } else {
466- Err ( GetEventsError :: InvalidContinuationToken )
480+ use std:: cmp:: Ordering ;
481+ match Ord :: cmp ( & self . block_number , & block_number) {
482+ Ordering :: Equal => Ok ( self . offset ) ,
483+ Ordering :: Less => Ok ( 0 ) ,
484+ Ordering :: Greater => Err ( GetEventsError :: InvalidContinuationToken ) ,
467485 }
468486 }
469487
@@ -959,6 +977,14 @@ mod tests {
959977 assert_eq ! ( result. events, & all[ 3 ..4 ] ) ;
960978 assert_eq ! ( result. continuation_token, None ) ;
961979
980+ // continuing from a page that does exist, should return all events (even from
981+ // pending)
982+ input. filter . chunk_size = 123 ;
983+ input. filter . continuation_token = Some ( "0-0" . to_string ( ) ) ;
984+ let result = get_events ( context. clone ( ) , input. clone ( ) ) . await . unwrap ( ) ;
985+ assert_eq ! ( result. events, all) ;
986+ assert_eq ! ( result. continuation_token, None ) ;
987+
962988 // nonexistent page: offset too large
963989 input. filter . chunk_size = 123 ; // Does not matter
964990 input. filter . continuation_token = Some ( "3-3" . to_string ( ) ) ; // Points to after the last event
@@ -1039,5 +1065,37 @@ mod tests {
10391065 . events ;
10401066 assert_eq ! ( events, & all[ 1 ..2 ] ) ;
10411067 }
1068+
1069+ #[ tokio:: test]
1070+ async fn from_block_past_pending ( ) {
1071+ let context = RpcContext :: for_tests_with_pending ( ) . await ;
1072+
1073+ let input = GetEventsInput {
1074+ filter : EventFilter {
1075+ from_block : Some ( BlockId :: Number ( BlockNumber :: new_or_panic ( 4 ) ) ) ,
1076+ to_block : Some ( BlockId :: Pending ) ,
1077+ chunk_size : 100 ,
1078+ ..Default :: default ( )
1079+ } ,
1080+ } ;
1081+ let result = get_events ( context, input) . await . unwrap ( ) ;
1082+ assert ! ( result. events. is_empty( ) ) ;
1083+ }
1084+
1085+ #[ tokio:: test]
1086+ async fn from_block_pending_to_block_none ( ) {
1087+ let context = RpcContext :: for_tests_with_pending ( ) . await ;
1088+
1089+ let input = GetEventsInput {
1090+ filter : EventFilter {
1091+ from_block : Some ( BlockId :: Pending ) ,
1092+ to_block : None ,
1093+ chunk_size : 100 ,
1094+ ..Default :: default ( )
1095+ } ,
1096+ } ;
1097+ let result = get_events ( context, input) . await . unwrap ( ) ;
1098+ assert ! ( !result. events. is_empty( ) ) ;
1099+ }
10421100 }
10431101}
0 commit comments