@@ -13,7 +13,8 @@ use alloc::{boxed::Box, collections::VecDeque};
13
13
use anyhow:: anyhow;
14
14
use async_trait:: async_trait;
15
15
16
- /// The frame queue stage of the derivation pipeline.
16
+ /// The [FrameQueue] stage of the derivation pipeline.
17
+ /// This stage takes the output of the [L1Retrieval] stage and parses it into frames.
17
18
#[ derive( Debug ) ]
18
19
pub struct FrameQueue < DAP , CP , T >
19
20
where
@@ -35,28 +36,33 @@ where
35
36
CP : ChainProvider + Debug ,
36
37
T : TelemetryProvider + Debug ,
37
38
{
38
- /// Create a new frame queue stage.
39
+ /// Create a new [FrameQueue] stage with the given previous [L1Retrieval] stage.
39
40
pub fn new ( prev : L1Retrieval < DAP , CP , T > , telemetry : T ) -> Self {
40
41
Self { prev, telemetry, queue : VecDeque :: new ( ) }
41
42
}
42
43
43
- /// Returns the L1 origin [BlockInfo].
44
+ /// Returns the L1 [BlockInfo] origin .
44
45
pub fn origin ( & self ) -> Option < & BlockInfo > {
45
46
self . prev . origin ( )
46
47
}
47
48
48
- /// Fetches the next frame from the frame queue .
49
+ /// Fetches the next frame from the [FrameQueue] .
49
50
pub async fn next_frame ( & mut self ) -> StageResult < Frame > {
50
51
if self . queue . is_empty ( ) {
51
52
match self . prev . next_data ( ) . await {
52
53
Ok ( data) => {
53
- // TODO: what do we do with frame parsing errors?
54
54
if let Ok ( frames) = Frame :: parse_frames ( data. as_ref ( ) ) {
55
55
self . queue . extend ( frames) ;
56
+ } else {
57
+ // TODO: log parsing frame error
58
+ // Failed to parse frames, but there may be more frames in the queue for
59
+ // the pipeline to advance, so don't return an error here.
56
60
}
57
61
}
58
62
Err ( e) => {
59
- return Err ( anyhow ! ( "Error fetching next data: {e}" ) . into ( ) ) ;
63
+ // TODO: log retrieval error
64
+ // The error must be bubbled up without a wrapper in case it's an EOF error.
65
+ return Err ( e) ;
60
66
}
61
67
}
62
68
}
68
74
) ,
69
75
LogLevel :: Debug ,
70
76
) ;
71
- return Err ( anyhow ! ( "Not enough data" ) . into ( ) ) ;
77
+ return Err ( StageError :: NotEnoughData ) ;
72
78
}
73
79
74
80
self . queue . pop_front ( ) . ok_or_else ( || anyhow ! ( "Frame queue is impossibly empty." ) . into ( ) )
92
98
pub ( crate ) mod tests {
93
99
use super :: * ;
94
100
use crate :: {
95
- stages:: l1_traversal:: tests:: new_test_traversal ,
101
+ stages:: l1_traversal:: tests:: new_populated_test_traversal ,
96
102
traits:: test_utils:: { TestDAP , TestTelemetry } ,
97
103
DERIVATION_VERSION_0 ,
98
104
} ;
@@ -123,71 +129,71 @@ pub(crate) mod tests {
123
129
#[ tokio:: test]
124
130
async fn test_frame_queue_empty_bytes ( ) {
125
131
let telemetry = TestTelemetry :: new ( ) ;
126
- let traversal = new_test_traversal ( true , true ) ;
132
+ let traversal = new_populated_test_traversal ( ) ;
127
133
let results = vec ! [ Ok ( Bytes :: from( vec![ 0x00 ] ) ) ] ;
128
134
let dap = TestDAP { results } ;
129
135
let retrieval = L1Retrieval :: new ( traversal, dap, TestTelemetry :: new ( ) ) ;
130
136
let mut frame_queue = FrameQueue :: new ( retrieval, telemetry) ;
131
137
let err = frame_queue. next_frame ( ) . await . unwrap_err ( ) ;
132
- assert_eq ! ( err, anyhow! ( "Not enough data" ) . into ( ) ) ;
138
+ assert_eq ! ( err, StageError :: NotEnoughData ) ;
133
139
}
134
140
135
141
#[ tokio:: test]
136
142
async fn test_frame_queue_no_frames_decoded ( ) {
137
143
let telemetry = TestTelemetry :: new ( ) ;
138
- let traversal = new_test_traversal ( true , true ) ;
144
+ let traversal = new_populated_test_traversal ( ) ;
139
145
let results = vec ! [ Err ( StageError :: Eof ) , Ok ( Bytes :: default ( ) ) ] ;
140
146
let dap = TestDAP { results } ;
141
147
let retrieval = L1Retrieval :: new ( traversal, dap, TestTelemetry :: new ( ) ) ;
142
148
let mut frame_queue = FrameQueue :: new ( retrieval, telemetry) ;
143
149
let err = frame_queue. next_frame ( ) . await . unwrap_err ( ) ;
144
- assert_eq ! ( err, anyhow! ( "Not enough data" ) . into ( ) ) ;
150
+ assert_eq ! ( err, StageError :: NotEnoughData ) ;
145
151
}
146
152
147
153
#[ tokio:: test]
148
154
async fn test_frame_queue_wrong_derivation_version ( ) {
149
155
let telemetry = TestTelemetry :: new ( ) ;
150
- let traversal = new_test_traversal ( true , true ) ;
156
+ let traversal = new_populated_test_traversal ( ) ;
151
157
let results = vec ! [ Ok ( Bytes :: from( vec![ 0x01 ] ) ) ] ;
152
158
let dap = TestDAP { results } ;
153
159
let retrieval = L1Retrieval :: new ( traversal, dap, TestTelemetry :: new ( ) ) ;
154
160
let mut frame_queue = FrameQueue :: new ( retrieval, telemetry) ;
155
161
let err = frame_queue. next_frame ( ) . await . unwrap_err ( ) ;
156
- assert_eq ! ( err, anyhow! ( "Unsupported derivation version" ) . into ( ) ) ;
162
+ assert_eq ! ( err, StageError :: NotEnoughData ) ;
157
163
}
158
164
159
165
#[ tokio:: test]
160
166
async fn test_frame_queue_frame_too_short ( ) {
161
167
let telemetry = TestTelemetry :: new ( ) ;
162
- let traversal = new_test_traversal ( true , true ) ;
168
+ let traversal = new_populated_test_traversal ( ) ;
163
169
let results = vec ! [ Ok ( Bytes :: from( vec![ 0x00 , 0x01 ] ) ) ] ;
164
170
let dap = TestDAP { results } ;
165
171
let retrieval = L1Retrieval :: new ( traversal, dap, TestTelemetry :: new ( ) ) ;
166
172
let mut frame_queue = FrameQueue :: new ( retrieval, telemetry) ;
167
173
let err = frame_queue. next_frame ( ) . await . unwrap_err ( ) ;
168
- assert_eq ! ( err, anyhow! ( "Frame too short to decode" ) . into ( ) ) ;
174
+ assert_eq ! ( err, StageError :: NotEnoughData ) ;
169
175
}
170
176
171
177
#[ tokio:: test]
172
178
async fn test_frame_queue_single_frame ( ) {
173
179
let data = new_encoded_test_frames ( 1 ) ;
174
180
let telemetry = TestTelemetry :: new ( ) ;
175
- let traversal = new_test_traversal ( true , true ) ;
181
+ let traversal = new_populated_test_traversal ( ) ;
176
182
let dap = TestDAP { results : vec ! [ Ok ( data) ] } ;
177
183
let retrieval = L1Retrieval :: new ( traversal, dap, TestTelemetry :: new ( ) ) ;
178
184
let mut frame_queue = FrameQueue :: new ( retrieval, telemetry) ;
179
185
let frame_decoded = frame_queue. next_frame ( ) . await . unwrap ( ) ;
180
186
let frame = new_test_frames ( 1 ) ;
181
187
assert_eq ! ( frame[ 0 ] , frame_decoded) ;
182
188
let err = frame_queue. next_frame ( ) . await . unwrap_err ( ) ;
183
- assert_eq ! ( err, anyhow! ( "Not enough data" ) . into ( ) ) ;
189
+ assert_eq ! ( err, StageError :: Eof ) ;
184
190
}
185
191
186
192
#[ tokio:: test]
187
193
async fn test_frame_queue_multiple_frames ( ) {
188
194
let telemetry = TestTelemetry :: new ( ) ;
189
195
let data = new_encoded_test_frames ( 3 ) ;
190
- let traversal = new_test_traversal ( true , true ) ;
196
+ let traversal = new_populated_test_traversal ( ) ;
191
197
let dap = TestDAP { results : vec ! [ Ok ( data) ] } ;
192
198
let retrieval = L1Retrieval :: new ( traversal, dap, TestTelemetry :: new ( ) ) ;
193
199
let mut frame_queue = FrameQueue :: new ( retrieval, telemetry) ;
@@ -196,6 +202,6 @@ pub(crate) mod tests {
196
202
assert_eq ! ( frame_decoded. number, i) ;
197
203
}
198
204
let err = frame_queue. next_frame ( ) . await . unwrap_err ( ) ;
199
- assert_eq ! ( err, anyhow! ( "Not enough data" ) . into ( ) ) ;
205
+ assert_eq ! ( err, StageError :: Eof ) ;
200
206
}
201
207
}
0 commit comments