@@ -71,16 +71,23 @@ class AsyncMultiRangeDownloader:
7171 client, bucket_name="chandrasiri-rs", object_name="test_open9"
7272 )
7373 my_buff1 = open('my_fav_file.txt', 'wb')
74+ my_buff1 = open('my_fav_file.txt', 'wb')
7475 my_buff2 = BytesIO()
7576 my_buff3 = BytesIO()
7677 my_buff4 = any_object_which_provides_BytesIO_like_interface()
78+ results_arr, error_obj = await mrd.download_ranges(
79+ my_buff4 = any_object_which_provides_BytesIO_like_interface()
7780 results_arr, error_obj = await mrd.download_ranges(
7881 [
82+ # (start_byte, bytes_to_read, writeable_buffer)
7983 # (start_byte, bytes_to_read, writeable_buffer)
8084 (0, 100, my_buff1),
8185 (100, 20, my_buff2),
8286 (200, 123, my_buff3),
8387 (300, 789, my_buff4),
88+ (100, 20, my_buff2),
89+ (200, 123, my_buff3),
90+ (300, 789, my_buff4),
8491 ]
8592 )
8693 if error_obj:
@@ -94,6 +101,17 @@ class AsyncMultiRangeDownloader:
94101 for result in results_arr:
95102 print("downloaded bytes", result)
96103
104+ if error_obj:
105+ print("Error occurred: ")
106+ print(error_obj)
107+ print(
108+ "please issue call to `download_ranges` with updated"
109+ "`read_ranges` based on diff of (bytes_requested - bytes_written)"
110+ )
111+
112+ for result in results_arr:
113+ print("downloaded bytes", result)
114+
97115
98116 """
99117
@@ -165,7 +183,8 @@ def __init__(
165183 self .object_name = object_name
166184 self .generation_number = generation_number
167185 self .read_handle = read_handle
168- self .read_obj_str : _AsyncReadObjectStream = None
186+ self .read_obj_str : Optional [_AsyncReadObjectStream ] = None
187+ self ._is_stream_open : bool = False
169188
170189 async def open (self ) -> None :
171190 """Opens the bidi-gRPC connection to read from the object.
@@ -176,14 +195,19 @@ async def open(self) -> None:
176195 "Opening" constitutes fetching object metadata such as generation number
177196 and read handle and sets them as attributes if not already set.
178197 """
179- self .read_obj_str = _AsyncReadObjectStream (
180- client = self .client ,
181- bucket_name = self .bucket_name ,
182- object_name = self .object_name ,
183- generation_number = self .generation_number ,
184- read_handle = self .read_handle ,
185- )
198+ if self ._is_stream_open :
199+ raise ValueError ("Underlying bidi-gRPC stream is already open" )
200+
201+ if self .read_obj_str is None :
202+ self .read_obj_str = _AsyncReadObjectStream (
203+ client = self .client ,
204+ bucket_name = self .bucket_name ,
205+ object_name = self .object_name ,
206+ generation_number = self .generation_number ,
207+ read_handle = self .read_handle ,
208+ )
186209 await self .read_obj_str .open ()
210+ self ._is_stream_open = True
187211 if self .generation_number is None :
188212 self .generation_number = self .read_obj_str .generation_number
189213 self .read_handle = self .read_obj_str .read_handle
@@ -206,11 +230,15 @@ async def download_ranges(
206230 to a requested range.
207231
208232 """
233+
209234 if len (read_ranges ) > 1000 :
210235 raise ValueError (
211236 "Invalid input - length of read_ranges cannot be more than 1000"
212237 )
213238
239+ if not self ._is_stream_open :
240+ raise ValueError ("Underlying bidi-gRPC stream is not open" )
241+
214242 read_id_to_writable_buffer_dict = {}
215243 results = []
216244 for i in range (0 , len (read_ranges ), _MAX_READ_RANGES_PER_BIDI_READ_REQUEST ):
@@ -255,4 +283,18 @@ async def download_ranges(
255283 del read_id_to_writable_buffer_dict [
256284 object_data_range .read_range .read_id
257285 ]
286+
258287 return results
288+
289+ async def close (self ):
290+ """
291+ Closes the underlying bidi-gRPC connection.
292+ """
293+ if not self ._is_stream_open :
294+ raise ValueError ("Underlying bidi-gRPC stream is not open" )
295+ await self .read_obj_str .close ()
296+ self ._is_stream_open = False
297+
298+ @property
299+ def is_stream_open (self ) -> bool :
300+ return self ._is_stream_open
0 commit comments