1
1
from __future__ import annotations
2
2
3
+ import math
3
4
import tarfile
4
5
import tempfile
5
- import threading
6
6
import typing as t
7
7
import warnings
8
8
from concurrent .futures import ThreadPoolExecutor
@@ -84,6 +84,7 @@ def _do_push_bento(
84
84
threads : int = 10 ,
85
85
rest_client : RestApiClient = Provide [BentoMLContainer .rest_api_client ],
86
86
model_store : ModelStore = Provide [BentoMLContainer .model_store ],
87
+ bentoml_tmp_dir : str = Provide [BentoMLContainer .tmp_bento_store_dir ],
87
88
):
88
89
name = bento .tag .name
89
90
version = bento .tag .version
@@ -213,10 +214,11 @@ def push_model(model: Model) -> None:
213
214
presigned_upload_url = remote_bento .presigned_upload_url
214
215
215
216
def io_cb (x : int ):
216
- with io_mutex :
217
- self .spinner .transmission_progress .update (upload_task_id , advance = x )
217
+ self .spinner .transmission_progress .update (upload_task_id , advance = x )
218
218
219
- with CallbackIOWrapper (read_cb = io_cb ) as tar_io :
219
+ with NamedTemporaryFile (
220
+ prefix = "bentoml-bento-" , suffix = ".tar" , dir = bentoml_tmp_dir
221
+ ) as tar_io :
220
222
with self .spinner .spin (
221
223
text = f'Creating tar archive for bento "{ bento .tag } "..'
222
224
):
@@ -232,42 +234,38 @@ def filter_(
232
234
return tar_info
233
235
234
236
tar .add (bento .path , arcname = "./" , filter = filter_ )
235
- tar_io .seek (0 , 0 )
236
237
237
238
with self .spinner .spin (text = f'Start uploading bento "{ bento .tag } "..' ):
238
239
rest_client .v1 .start_upload_bento (
239
240
bento_repository_name = bento_repository .name , version = version
240
241
)
241
-
242
- file_size = tar_io . getbuffer (). nbytes
242
+ file_size = tar_io . tell ()
243
+ io_with_cb = CallbackIOWrapper ( tar_io , read_cb = io_cb )
243
244
244
245
self .spinner .transmission_progress .update (
245
246
upload_task_id , completed = 0 , total = file_size , visible = True
246
247
)
247
248
self .spinner .transmission_progress .start_task (upload_task_id )
248
249
249
- io_mutex = threading .Lock ()
250
-
251
250
if transmission_strategy == "proxy" :
252
251
try :
253
252
rest_client .v1 .upload_bento (
254
253
bento_repository_name = bento_repository .name ,
255
254
version = version ,
256
- data = tar_io ,
255
+ data = io_with_cb ,
257
256
)
258
257
except Exception as e : # pylint: disable=broad-except
259
258
self .spinner .log (f'[bold red]Failed to upload bento "{ bento .tag } "' )
260
259
raise e
261
260
self .spinner .log (f'[bold green]Successfully pushed bento "{ bento .tag } "' )
262
261
return
263
262
finish_req = FinishUploadBentoSchema (
264
- status = BentoUploadStatus .SUCCESS .value ,
265
- reason = "" ,
263
+ status = BentoUploadStatus .SUCCESS .value , reason = ""
266
264
)
267
265
try :
268
266
if presigned_upload_url is not None :
269
267
resp = httpx .put (
270
- presigned_upload_url , content = tar_io , timeout = 36000
268
+ presigned_upload_url , content = io_with_cb , timeout = 36000
271
269
)
272
270
if resp .status_code != 200 :
273
271
finish_req = FinishUploadBentoSchema (
@@ -289,7 +287,8 @@ def filter_(
289
287
290
288
upload_id : str = remote_bento .upload_id
291
289
292
- chunks_count = file_size // FILE_CHUNK_SIZE + 1
290
+ chunks_count = math .ceil (file_size / FILE_CHUNK_SIZE )
291
+ tar_io .file .close ()
293
292
294
293
def chunk_upload (
295
294
upload_id : str , chunk_number : int
@@ -310,18 +309,16 @@ def chunk_upload(
310
309
with self .spinner .spin (
311
310
text = f'({ chunk_number } /{ chunks_count } ) Uploading chunk of Bento "{ bento .tag } "...'
312
311
):
313
- chunk = (
314
- tar_io .getbuffer ()[
315
- (chunk_number - 1 ) * FILE_CHUNK_SIZE : chunk_number
316
- * FILE_CHUNK_SIZE
317
- ]
318
- if chunk_number < chunks_count
319
- else tar_io .getbuffer ()[
320
- (chunk_number - 1 ) * FILE_CHUNK_SIZE :
321
- ]
322
- )
312
+ with open (tar_io .name , "rb" ) as f :
313
+ chunk_io = CallbackIOWrapper (
314
+ f ,
315
+ read_cb = io_cb ,
316
+ start = (chunk_number - 1 ) * FILE_CHUNK_SIZE ,
317
+ end = chunk_number * FILE_CHUNK_SIZE
318
+ if chunk_number < chunks_count
319
+ else None ,
320
+ )
323
321
324
- with CallbackIOWrapper (chunk , read_cb = io_cb ) as chunk_io :
325
322
resp = httpx .put (
326
323
remote_bento .presigned_upload_url ,
327
324
content = chunk_io ,
@@ -588,6 +585,7 @@ def _do_push_model(
588
585
force : bool = False ,
589
586
threads : int = 10 ,
590
587
rest_client : RestApiClient = Provide [BentoMLContainer .rest_api_client ],
588
+ bentoml_tmp_dir : str = Provide [BentoMLContainer .tmp_bento_store_dir ],
591
589
):
592
590
name = model .tag .name
593
591
version = model .tag .version
@@ -663,38 +661,37 @@ def _do_push_model(
663
661
transmission_strategy = "presigned_url"
664
662
presigned_upload_url = remote_model .presigned_upload_url
665
663
666
- io_mutex = threading .Lock ()
667
-
668
664
def io_cb (x : int ):
669
- with io_mutex :
670
- self .spinner .transmission_progress .update (upload_task_id , advance = x )
665
+ self .spinner .transmission_progress .update (upload_task_id , advance = x )
671
666
672
- with CallbackIOWrapper (read_cb = io_cb ) as tar_io :
667
+ with NamedTemporaryFile (
668
+ prefix = "bentoml-model-" , suffix = ".tar" , dir = bentoml_tmp_dir
669
+ ) as tar_io :
673
670
with self .spinner .spin (
674
671
text = f'Creating tar archive for model "{ model .tag } "..'
675
672
):
676
673
with tarfile .open (fileobj = tar_io , mode = "w:" ) as tar :
677
674
tar .add (model .path , arcname = "./" )
678
- tar_io .seek (0 , 0 )
679
675
with self .spinner .spin (text = f'Start uploading model "{ model .tag } "..' ):
680
676
rest_client .v1 .start_upload_model (
681
677
model_repository_name = model_repository .name , version = version
682
678
)
683
- file_size = tar_io .getbuffer (). nbytes
679
+ file_size = tar_io .tell ()
684
680
self .spinner .transmission_progress .update (
685
681
upload_task_id ,
686
682
description = f'Uploading model "{ model .tag } "' ,
687
683
total = file_size ,
688
684
visible = True ,
689
685
)
690
686
self .spinner .transmission_progress .start_task (upload_task_id )
687
+ io_with_cb = CallbackIOWrapper (tar_io , read_cb = io_cb )
691
688
692
689
if transmission_strategy == "proxy" :
693
690
try :
694
691
rest_client .v1 .upload_model (
695
692
model_repository_name = model_repository .name ,
696
693
version = version ,
697
- data = tar_io ,
694
+ data = io_with_cb ,
698
695
)
699
696
except Exception as e : # pylint: disable=broad-except
700
697
self .spinner .log (f'[bold red]Failed to upload model "{ model .tag } "' )
@@ -708,7 +705,7 @@ def io_cb(x: int):
708
705
try :
709
706
if presigned_upload_url is not None :
710
707
resp = httpx .put (
711
- presigned_upload_url , content = tar_io , timeout = 36000
708
+ presigned_upload_url , content = io_with_cb , timeout = 36000
712
709
)
713
710
if resp .status_code != 200 :
714
711
finish_req = FinishUploadModelSchema (
@@ -730,7 +727,8 @@ def io_cb(x: int):
730
727
731
728
upload_id : str = remote_model .upload_id
732
729
733
- chunks_count = file_size // FILE_CHUNK_SIZE + 1
730
+ chunks_count = math .ceil (file_size / FILE_CHUNK_SIZE )
731
+ tar_io .file .close ()
734
732
735
733
def chunk_upload (
736
734
upload_id : str , chunk_number : int
@@ -752,18 +750,16 @@ def chunk_upload(
752
750
with self .spinner .spin (
753
751
text = f'({ chunk_number } /{ chunks_count } ) Uploading chunk of model "{ model .tag } "...'
754
752
):
755
- chunk = (
756
- tar_io .getbuffer ()[
757
- (chunk_number - 1 ) * FILE_CHUNK_SIZE : chunk_number
758
- * FILE_CHUNK_SIZE
759
- ]
760
- if chunk_number < chunks_count
761
- else tar_io .getbuffer ()[
762
- (chunk_number - 1 ) * FILE_CHUNK_SIZE :
763
- ]
764
- )
753
+ with open (tar_io .name , "rb" ) as f :
754
+ chunk_io = CallbackIOWrapper (
755
+ f ,
756
+ read_cb = io_cb ,
757
+ start = (chunk_number - 1 ) * FILE_CHUNK_SIZE ,
758
+ end = chunk_number * FILE_CHUNK_SIZE
759
+ if chunk_number < chunks_count
760
+ else None ,
761
+ )
765
762
766
- with CallbackIOWrapper (chunk , read_cb = io_cb ) as chunk_io :
767
763
resp = httpx .put (
768
764
remote_model .presigned_upload_url ,
769
765
content = chunk_io ,
0 commit comments