@@ -41,8 +41,13 @@ def load_cached_manifests():
4141 return None
4242
4343 return cache_data .get ('manifests' , [])
44- except (json .JSONDecodeError , FileNotFoundError ):
44+ except (json .JSONDecodeError , FileNotFoundError , UnicodeDecodeError ):
4545 print ("Cache file corrupted or missing, will refetch..." )
46+ try :
47+ if os .path .exists (MANIFEST_CACHE_FILE ):
48+ os .remove (MANIFEST_CACHE_FILE )
49+ except Exception :
50+ pass
4651 return None
4752
4853def save_manifests_to_cache (manifests ):
@@ -136,36 +141,53 @@ def download_files(client, cdn_client, files, destination):
136141
137142 print ("All files downloaded successfully." )
138143
139- def _download_single_file (file ):
144+ def _download_single_file (file , max_retries = 3 ):
140145 if file .local and os .path .dirname (file .local ) != "" :
141146 os .makedirs (os .path .dirname (file .local ), exist_ok = True )
142147
143148 chunk_size = 1024 * 1024 # 1MB chunks
144- downloaded = 0
145- failed = False
149+ retry_count = 0
146150
147- with open (file .local , 'wb' ) as f :
148- while downloaded < file .size :
149- remaining = file .size - downloaded
150- read_size = min (chunk_size , remaining )
151-
152- chunk = file .read (read_size )
153- if not chunk :
154- break
151+ while retry_count <= max_retries :
152+ try :
153+ downloaded = 0
155154
156- f .write (chunk )
157- downloaded += len (chunk )
155+ with open (file .local , 'wb' ) as f :
156+ while downloaded < file .size :
157+ remaining = file .size - downloaded
158+ read_size = min (chunk_size , remaining )
159+
160+ chunk = file .read (read_size )
161+ if not chunk :
162+ break
163+
164+ f .write (chunk )
165+ downloaded += len (chunk )
166+
167+ if downloaded % (10 * 1024 * 1024 ) == 0 :
168+ percent = (downloaded / file .size ) * 100
169+ print (f" Progress: { percent :.1f} % ({ downloaded } /{ file .size } bytes)" )
158170
159- if downloaded % (10 * 1024 * 1024 ) == 0 :
160- percent = (downloaded / file .size ) * 100
161- print (f" Progress: { percent :.1f} % ({ downloaded } /{ file .size } bytes)" )
162-
163- if failed :
164- print (f"Failed to download { file .filename } " )
165- else :
166- if file .is_executable :
167- os .chmod (file .local , 0o755 )
168- print (f"✓ Downloaded { file .filename } " )
171+ # Success - break out of retry loop
172+ if file .is_executable :
173+ os .chmod (file .local , 0o755 )
174+ print (f"✓ Downloaded { file .filename } " )
175+ return
176+
177+ except Exception as e :
178+ retry_count += 1
179+ if retry_count > max_retries :
180+ print (f"✗ Failed to download { file .filename } after { max_retries } retries: { str (e )} " )
181+ raise
182+
183+ wait_time = 2 ** retry_count # Exponential backoff: 2, 4, 8 seconds
184+ print (f" Download failed: { str (e )} " )
185+ print (f" Retrying in { wait_time } seconds... (attempt { retry_count } /{ max_retries } )" )
186+ time .sleep (wait_time )
187+
188+ # Reset file for retry
189+ if os .path .exists (file .local ):
190+ os .remove (file .local )
169191
170192if __name__ == "__main__" :
171193 import os
0 commit comments