@@ -166,36 +166,39 @@ impl<R> ThrottleWrapper<R> {
166166 }
167167}
168168
169+ async fn wait_for_quota ( limiter : & SharedRateLimiter , len : usize ) -> Result < ( ) > {
170+ if len == 0 {
171+ return Ok ( ( ) ) ;
172+ }
173+
174+ if len > u32:: MAX as usize {
175+ return Err ( Error :: new (
176+ ErrorKind :: RateLimited ,
177+ "request size exceeds throttle quota capacity" ,
178+ ) ) ;
179+ }
180+
181+ let buf_length = NonZeroU32 :: new ( len as u32 ) . expect ( "len is non-zero so NonZeroU32 must exist" ) ;
182+
183+ limiter. until_n_ready ( buf_length) . await . map_err ( |_| {
184+ Error :: new (
185+ ErrorKind :: RateLimited ,
186+ "burst size is smaller than the request size" ,
187+ )
188+ } )
189+ }
190+
169191impl < R : oio:: Read > oio:: Read for ThrottleWrapper < R > {
170192 async fn read ( & mut self ) -> Result < Buffer > {
171- self . inner . read ( ) . await
193+ let bs = self . inner . read ( ) . await ?;
194+ wait_for_quota ( & self . limiter , bs. len ( ) ) . await ?;
195+ Ok ( bs)
172196 }
173197}
174198
175199impl < R : oio:: Write > oio:: Write for ThrottleWrapper < R > {
176200 async fn write ( & mut self , bs : Buffer ) -> Result < ( ) > {
177- let len = bs. len ( ) ;
178- if len == 0 {
179- return self . inner . write ( bs) . await ;
180- }
181-
182- if len > u32:: MAX as usize {
183- return Err ( Error :: new (
184- ErrorKind :: RateLimited ,
185- "request size exceeds throttle quota capacity" ,
186- ) ) ;
187- }
188-
189- let buf_length =
190- NonZeroU32 :: new ( len as u32 ) . expect ( "len is non-zero so NonZeroU32 must exist" ) ;
191-
192- self . limiter . until_n_ready ( buf_length) . await . map_err ( |_| {
193- Error :: new (
194- ErrorKind :: RateLimited ,
195- "burst size is smaller than the request size" ,
196- )
197- } ) ?;
198-
201+ wait_for_quota ( & self . limiter , bs. len ( ) ) . await ?;
199202 self . inner . write ( bs) . await
200203 }
201204
@@ -207,3 +210,55 @@ impl<R: oio::Write> oio::Write for ThrottleWrapper<R> {
207210 self . inner . close ( ) . await
208211 }
209212}
213+
214+ #[ cfg( test) ]
215+ mod tests {
216+ use super :: * ;
217+ use opendal_core:: raw:: oio:: Read ;
218+
219+ struct SingleRead {
220+ data : Option < Buffer > ,
221+ }
222+
223+ impl oio:: Read for SingleRead {
224+ async fn read ( & mut self ) -> Result < Buffer > {
225+ Ok ( self . data . take ( ) . unwrap_or_default ( ) )
226+ }
227+ }
228+
229+ fn new_limiter ( bandwidth : u32 , burst : u32 ) -> SharedRateLimiter {
230+ Arc :: new ( RateLimiter :: direct (
231+ Quota :: per_second ( NonZeroU32 :: new ( bandwidth) . unwrap ( ) )
232+ . allow_burst ( NonZeroU32 :: new ( burst) . unwrap ( ) ) ,
233+ ) )
234+ }
235+
236+ #[ tokio:: test]
237+ async fn read_allows_chunks_within_burst ( ) {
238+ let mut reader = ThrottleWrapper :: new (
239+ SingleRead {
240+ data : Some ( Buffer :: from ( vec ! [ 0 ; 2 ] ) ) ,
241+ } ,
242+ new_limiter ( 2 , 2 ) ,
243+ ) ;
244+
245+ let bs = reader. read ( ) . await . expect ( "read should pass throttle" ) ;
246+ assert_eq ! ( bs. len( ) , 2 ) ;
247+ }
248+
249+ #[ tokio:: test]
250+ async fn read_rejects_chunks_larger_than_burst ( ) {
251+ let mut reader = ThrottleWrapper :: new (
252+ SingleRead {
253+ data : Some ( Buffer :: from ( vec ! [ 0 ; 2 ] ) ) ,
254+ } ,
255+ new_limiter ( 1 , 1 ) ,
256+ ) ;
257+
258+ let err = reader
259+ . read ( )
260+ . await
261+ . expect_err ( "chunk larger than burst should fail" ) ;
262+ assert_eq ! ( err. kind( ) , ErrorKind :: RateLimited ) ;
263+ }
264+ }
0 commit comments