@@ -16,10 +16,7 @@ use futures::{
16
16
} ;
17
17
use tokio:: { sync:: OnceCell , task:: spawn_blocking, time:: sleep} ;
18
18
19
- use super :: {
20
- config:: { STREAM_THROTTLE_HISTORICAL , STREAM_THROTTLE_LIVE } ,
21
- StreamError ,
22
- } ;
19
+ use super :: { config, StreamError } ;
23
20
use crate :: { server:: DeliverPolicy , types:: StreamResponse } ;
24
21
25
22
pub type BoxedStoreItem = Result < StreamResponse , StreamError > ;
@@ -90,7 +87,7 @@ impl<R: Record> Stream<R> {
90
87
pub async fn publish (
91
88
& self ,
92
89
subject : & str ,
93
- response : & Arc < StreamResponse > ,
90
+ response : & StreamResponse ,
94
91
) -> Result < ( ) , StreamError > {
95
92
let broker = self . broker . clone ( ) ;
96
93
let response = response. clone ( ) ;
@@ -117,33 +114,41 @@ impl<R: Record> Stream<R> {
117
114
api_key_role : & ApiKeyRole ,
118
115
) -> BoxStream < ' static , Result < StreamResponse , StreamError > > {
119
116
let broker = self . broker . clone ( ) ;
120
- let subject_ref = subject. clone ( ) ;
117
+ let subject = subject. clone ( ) ;
121
118
let stream = self . clone ( ) ;
122
119
let role = api_key_role. clone ( ) ;
123
- let has_historical =
124
- role. has_scopes ( & [ ApiKeyRoleScope :: HistoricalData ] ) . is_ok ( ) ;
125
- let has_live = role. has_scopes ( & [ ApiKeyRoleScope :: LiveData ] ) . is_ok ( ) ;
126
- let throttle_historical = * STREAM_THROTTLE_HISTORICAL as u64 ;
127
- let throttle_live = * STREAM_THROTTLE_LIVE as u64 ;
128
120
let stream = async_stream:: try_stream! {
129
- if has_historical {
130
- if let DeliverPolicy :: FromBlock { block_height } = deliver_policy {
131
- let mut historical = stream. historical_streaming( subject_ref. to_owned( ) , Some ( block_height) , & role) ;
132
- while let Some ( result) = historical. next( ) . await {
133
- yield result?;
134
- sleep( Duration :: from_millis( throttle_historical) ) . await ;
121
+ match role. has_scopes( & [ ApiKeyRoleScope :: HistoricalData ] ) {
122
+ Ok ( _) => {
123
+ if let DeliverPolicy :: FromBlock { block_height } = deliver_policy {
124
+ let mut historical = stream. historical_streaming( subject. to_owned( ) , Some ( block_height) , & role) ;
125
+ while let Some ( result) = historical. next( ) . await {
126
+ yield result?;
127
+ let throttle_time = * config:: STREAM_THROTTLE_HISTORICAL ;
128
+ sleep( Duration :: from_millis( throttle_time as u64 ) ) . await ;
129
+ }
135
130
}
136
131
}
132
+ Err ( e) => {
133
+ tracing:: error!( "Error subscribing to stream: {}" , e) ;
134
+ Err ( StreamError :: from( e) ) ?;
135
+ }
137
136
}
138
137
139
- if has_live {
140
- let mut live = broker. subscribe( & subject_ref. parse( ) ) . await ?;
141
- while let Some ( msg) = live. next( ) . await {
142
- let msg = msg?;
143
- let stream_response = spawn_blocking( move || StreamResponse :: decode_json( & msg) )
144
- . await ?;
145
- yield stream_response?;
146
- sleep( Duration :: from_millis( throttle_live) ) . await ;
138
+ match role. has_scopes( & [ ApiKeyRoleScope :: LiveData ] ) {
139
+ Ok ( _) => {
140
+ let mut live = broker. subscribe( & subject. parse( ) ) . await ?;
141
+ while let Some ( msg) = live. next( ) . await {
142
+ let msg = msg?;
143
+ let stream_response = spawn_blocking( move || StreamResponse :: decode_json( & msg) ) . await ??;
144
+ yield stream_response;
145
+ let throttle_time = * config:: STREAM_THROTTLE_LIVE ;
146
+ sleep( Duration :: from_millis( throttle_time as u64 ) ) . await ;
147
+ }
148
+ }
149
+ Err ( e) => {
150
+ tracing:: error!( "Error subscribing to stream: {}" , e) ;
151
+ Err ( StreamError :: from( e) ) ?;
147
152
}
148
153
}
149
154
} ;
@@ -156,8 +161,8 @@ impl<R: Record> Stream<R> {
156
161
from_block : Option < BlockHeight > ,
157
162
role : & ApiKeyRole ,
158
163
) -> BoxStream < ' static , Result < StreamResponse , StreamError > > {
159
- let store = self . store ( ) ;
160
- let db = store. db . clone ( ) ;
164
+ let store = self . store ( ) . clone ( ) ;
165
+ let db = self . store ( ) . db . clone ( ) ;
161
166
let role = role. clone ( ) ;
162
167
let opts = if cfg ! ( any( test, feature = "test-helpers" ) ) {
163
168
QueryOptions :: default ( )
@@ -167,39 +172,35 @@ impl<R: Record> Stream<R> {
167
172
168
173
let stream = async_stream:: try_stream! {
169
174
let mut current_height = from_block. unwrap_or_default( ) ;
170
- let mut last_height = find_last_block_height( & db, opts. clone( ) ) . await ?;
171
- if let Err ( e) = role. validate_historical_limit( last_height, current_height) {
172
- tracing:: error!( "Historical limit validation failed: {}" , e) ;
173
- Err ( StreamError :: from( e) ) ?;
174
- }
175
-
176
175
let mut opts = opts. with_from_block( Some ( current_height) ) ;
176
+ let mut last_height = find_last_block_height( & db, opts. clone( ) ) . await ?;
177
177
while current_height <= last_height {
178
178
let items = store. find_many_by_subject( & subject, opts. clone( ) ) . await ?;
179
- if items. is_empty( ) {
179
+ for item in items {
180
+ let subject = item. subject_str( ) ;
181
+ let subject_id = item. subject_id( ) ;
182
+ let block_height = item. block_height( ) ;
183
+ role. validate_historical_limit( last_height, block_height) ?;
184
+ let value = item. encoded_value( ) . to_vec( ) ;
185
+ let pointer = item. into( ) ;
186
+ let response = StreamResponse :: new( subject, subject_id, & value, pointer. to_owned( ) , None ) ?;
187
+ yield response;
188
+ current_height = pointer. block_height;
189
+ }
190
+ opts. increment_offset( ) ;
191
+ // When we reach the last known height, we need to check if any new blocks
192
+ // were produced while we were processing the previous ones
193
+ if current_height == last_height {
180
194
let new_last_height = find_last_block_height( & db, opts. clone( ) ) . await ?;
181
195
if new_last_height > last_height {
196
+ // Reset current_height back to process the blocks we haven't seen yet
197
+ current_height = last_height;
182
198
last_height = new_last_height;
183
- continue ;
199
+ } else {
200
+ tracing:: debug!( "No new blocks found, stopping historical streaming on block {}" , current_height) ;
201
+ break
184
202
}
185
- tracing:: debug!( "No new blocks found, stopping historical streaming on block {}" , current_height) ;
186
- break ;
187
- }
188
-
189
- for item in items {
190
- let block_height = item. block_height( ) ;
191
- let record_pointer = item. to_owned( ) . into( ) ;
192
- let response = StreamResponse :: new(
193
- item. subject_str( ) ,
194
- item. subject_id( ) ,
195
- item. encoded_value( ) ,
196
- record_pointer,
197
- None ,
198
- ) ?;
199
- yield response;
200
- current_height = block_height;
201
203
}
202
- opts = opts. with_from_block( Some ( current_height) ) ;
203
204
}
204
205
} ;
205
206
Box :: pin ( stream)
0 commit comments