27
27
from dandi .dandiapi import RemoteAsset , RemoteDandiset , RESTFullAPIClient
28
28
from dandi .metadata .core import get_default_metadata
29
29
from dandi .misctypes import DUMMY_DANDI_ETAG , Digest , LocalReadableFile , P
30
- from dandi .utils import yaml_load
30
+ from dandi .utils import post_upload_size_check , pre_upload_size_check , yaml_load
31
31
from dandi .validate_types import Scope , Severity , ValidationOrigin , ValidationResult
32
32
33
33
lgr = dandi .get_logger ()
@@ -350,7 +350,7 @@ def iter_upload(
350
350
)
351
351
yield {"status" : "initiating upload" }
352
352
lgr .debug ("%s: Beginning upload" , asset_path )
353
- total_size = self .size
353
+ total_size = pre_upload_size_check ( self .filepath )
354
354
try :
355
355
resp = client .post (
356
356
"/uploads/initialize/" ,
@@ -370,73 +370,80 @@ def iter_upload(
370
370
else :
371
371
raise
372
372
else :
373
- upload_id = resp ["upload_id" ]
374
- parts = resp ["parts" ]
375
- if len (parts ) != etagger .part_qty :
376
- raise RuntimeError (
377
- f"Server and client disagree on number of parts for upload;"
378
- f" server says { len (parts )} , client says { etagger .part_qty } "
379
- )
380
- parts_out = []
381
- bytes_uploaded = 0
382
- lgr .debug ("Uploading %s in %d parts" , self .filepath , len (parts ))
383
- with RESTFullAPIClient ("http://nil.nil" ) as storage :
384
- with self .filepath .open ("rb" ) as fp :
385
- with ThreadPoolExecutor (max_workers = jobs or 5 ) as executor :
386
- lock = Lock ()
387
- futures = [
388
- executor .submit (
389
- _upload_blob_part ,
390
- storage_session = storage ,
391
- fp = fp ,
392
- lock = lock ,
393
- etagger = etagger ,
394
- asset_path = asset_path ,
395
- part = part ,
373
+ try :
374
+ upload_id = resp ["upload_id" ]
375
+ parts = resp ["parts" ]
376
+ if len (parts ) != etagger .part_qty :
377
+ raise RuntimeError (
378
+ f"Server and client disagree on number of parts for upload;"
379
+ f" server says { len (parts )} , client says { etagger .part_qty } "
380
+ )
381
+ parts_out = []
382
+ bytes_uploaded = 0
383
+ lgr .debug ("Uploading %s in %d parts" , self .filepath , len (parts ))
384
+ with RESTFullAPIClient ("http://nil.nil" ) as storage :
385
+ with self .filepath .open ("rb" ) as fp :
386
+ with ThreadPoolExecutor (max_workers = jobs or 5 ) as executor :
387
+ lock = Lock ()
388
+ futures = [
389
+ executor .submit (
390
+ _upload_blob_part ,
391
+ storage_session = storage ,
392
+ fp = fp ,
393
+ lock = lock ,
394
+ etagger = etagger ,
395
+ asset_path = asset_path ,
396
+ part = part ,
397
+ )
398
+ for part in parts
399
+ ]
400
+ for fut in as_completed (futures ):
401
+ out_part = fut .result ()
402
+ bytes_uploaded += out_part ["size" ]
403
+ yield {
404
+ "status" : "uploading" ,
405
+ "upload" : 100 * bytes_uploaded / total_size ,
406
+ "current" : bytes_uploaded ,
407
+ }
408
+ parts_out .append (out_part )
409
+ lgr .debug ("%s: Completing upload" , asset_path )
410
+ resp = client .post (
411
+ f"/uploads/{ upload_id } /complete/" ,
412
+ json = {"parts" : parts_out },
413
+ )
414
+ lgr .debug (
415
+ "%s: Announcing completion to %s" ,
416
+ asset_path ,
417
+ resp ["complete_url" ],
418
+ )
419
+ r = storage .post (
420
+ resp ["complete_url" ], data = resp ["body" ], json_resp = False
421
+ )
422
+ lgr .debug (
423
+ "%s: Upload completed. Response content: %s" ,
424
+ asset_path ,
425
+ r .content ,
426
+ )
427
+ rxml = fromstring (r .text )
428
+ m = re .match (r"\{.+?\}" , rxml .tag )
429
+ ns = m .group (0 ) if m else ""
430
+ final_etag = rxml .findtext (f"{ ns } ETag" )
431
+ if final_etag is not None :
432
+ final_etag = final_etag .strip ('"' )
433
+ if final_etag != filetag :
434
+ raise RuntimeError (
435
+ "Server and client disagree on final ETag of"
436
+ f" uploaded file; server says { final_etag } ,"
437
+ f" client says { filetag } "
396
438
)
397
- for part in parts
398
- ]
399
- for fut in as_completed (futures ):
400
- out_part = fut .result ()
401
- bytes_uploaded += out_part ["size" ]
402
- yield {
403
- "status" : "uploading" ,
404
- "upload" : 100 * bytes_uploaded / total_size ,
405
- "current" : bytes_uploaded ,
406
- }
407
- parts_out .append (out_part )
408
- lgr .debug ("%s: Completing upload" , asset_path )
409
- resp = client .post (
410
- f"/uploads/{ upload_id } /complete/" ,
411
- json = {"parts" : parts_out },
412
- )
413
- lgr .debug (
414
- "%s: Announcing completion to %s" ,
415
- asset_path ,
416
- resp ["complete_url" ],
417
- )
418
- r = storage .post (
419
- resp ["complete_url" ], data = resp ["body" ], json_resp = False
420
- )
421
- lgr .debug (
422
- "%s: Upload completed. Response content: %s" ,
423
- asset_path ,
424
- r .content ,
425
- )
426
- rxml = fromstring (r .text )
427
- m = re .match (r"\{.+?\}" , rxml .tag )
428
- ns = m .group (0 ) if m else ""
429
- final_etag = rxml .findtext (f"{ ns } ETag" )
430
- if final_etag is not None :
431
- final_etag = final_etag .strip ('"' )
432
- if final_etag != filetag :
433
- raise RuntimeError (
434
- "Server and client disagree on final ETag of uploaded file;"
435
- f" server says { final_etag } , client says { filetag } "
436
- )
437
- # else: Error? Warning?
438
- resp = client .post (f"/uploads/{ upload_id } /validate/" )
439
- blob_id = resp ["blob_id" ]
439
+ # else: Error? Warning?
440
+ resp = client .post (f"/uploads/{ upload_id } /validate/" )
441
+ blob_id = resp ["blob_id" ]
442
+ except Exception :
443
+ post_upload_size_check (self .filepath , total_size , True )
444
+ raise
445
+ else :
446
+ post_upload_size_check (self .filepath , total_size , False )
440
447
lgr .debug ("%s: Assigning asset blob to dandiset & version" , asset_path )
441
448
yield {"status" : "producing asset" }
442
449
if replacing is not None :
0 commit comments