|
20 | 20 | status, |
21 | 21 | ) |
22 | 22 | from fastapi.responses import JSONResponse, PlainTextResponse |
23 | | -from filelock import SoftFileLock |
| 23 | +from filelock import SoftFileLock, Timeout |
24 | 24 | from starlette.requests import HTTPConnection, Request |
25 | 25 | from starlette.types import ASGIApp, Receive, Scope, Send |
26 | 26 |
|
@@ -210,44 +210,47 @@ def __fetch_model_as_file( |
210 | 210 | ) -> str: |
211 | 211 | result_path = download_options.pop("save_path", urlparse(model_path).path.split("/")[-1]) |
212 | 212 | temp_path = result_path + ".tmp" |
213 | | - with SoftFileLock(result_path + ".lock", timeout=LOCK_TIMEOUT): |
214 | | - with niquests.get(model_path, stream=True) as response: |
215 | | - if not response.ok: |
216 | | - raise ModelFetchError( |
217 | | - f"Downloading of '{model_path}' failed, returned ({response.status_code}) {response.text}" |
218 | | - ) |
219 | | - downloaded_size = 0 |
220 | | - linked_etag = "" |
221 | | - for each_history in response.history: |
222 | | - linked_etag = each_history.headers.get("X-Linked-ETag", "") |
223 | | - if linked_etag: |
224 | | - break |
225 | | - if not linked_etag: |
226 | | - linked_etag = response.headers.get("X-Linked-ETag", response.headers.get("ETag", "")) |
227 | | - total_size = int(response.headers.get("Content-Length")) |
228 | | - try: |
229 | | - existing_size = os.path.getsize(result_path) |
230 | | - except OSError: |
231 | | - existing_size = 0 |
232 | | - if linked_etag and total_size == existing_size: |
233 | | - with builtins.open(result_path, "rb") as file: |
234 | | - sha256_hash = hashlib.sha256() |
235 | | - for byte_block in iter(lambda: file.read(4096), b""): |
236 | | - sha256_hash.update(byte_block) |
237 | | - if f'"{sha256_hash.hexdigest()}"' == linked_etag: |
238 | | - nc.set_init_status(min(current_progress + progress_for_task, 99)) |
239 | | - return result_path |
240 | | - |
241 | | - with builtins.open(temp_path, "wb") as file: |
242 | | - last_progress = current_progress |
243 | | - for chunk in response.iter_raw(-1): |
244 | | - downloaded_size += file.write(chunk) |
245 | | - if total_size: |
246 | | - new_progress = min(current_progress + int(progress_for_task * downloaded_size / total_size), 99) |
247 | | - if new_progress != last_progress: |
248 | | - nc.set_init_status(new_progress) |
249 | | - last_progress = new_progress |
250 | | - os.replace(temp_path, result_path) |
| 213 | + try: |
| 214 | + with SoftFileLock(result_path + ".lock", timeout=LOCK_TIMEOUT): |
| 215 | + with niquests.get(model_path, stream=True) as response: |
| 216 | + if not response.ok: |
| 217 | + raise ModelFetchError( |
| 218 | + f"Downloading of '{model_path}' failed, returned ({response.status_code}) {response.text}" |
| 219 | + ) |
| 220 | + downloaded_size = 0 |
| 221 | + linked_etag = "" |
| 222 | + for each_history in response.history: |
| 223 | + linked_etag = each_history.headers.get("X-Linked-ETag", "") |
| 224 | + if linked_etag: |
| 225 | + break |
| 226 | + if not linked_etag: |
| 227 | + linked_etag = response.headers.get("X-Linked-ETag", response.headers.get("ETag", "")) |
| 228 | + total_size = int(response.headers.get("Content-Length")) |
| 229 | + try: |
| 230 | + existing_size = os.path.getsize(result_path) |
| 231 | + except OSError: |
| 232 | + existing_size = 0 |
| 233 | + if linked_etag and total_size == existing_size: |
| 234 | + with builtins.open(result_path, "rb") as file: |
| 235 | + sha256_hash = hashlib.sha256() |
| 236 | + for byte_block in iter(lambda: file.read(4096), b""): |
| 237 | + sha256_hash.update(byte_block) |
| 238 | + if f'"{sha256_hash.hexdigest()}"' == linked_etag: |
| 239 | + nc.set_init_status(min(current_progress + progress_for_task, 99)) |
| 240 | + return result_path |
| 241 | + |
| 242 | + with builtins.open(temp_path, "wb") as file: |
| 243 | + last_progress = current_progress |
| 244 | + for chunk in response.iter_raw(-1): |
| 245 | + downloaded_size += file.write(chunk) |
| 246 | + if total_size: |
| 247 | + new_progress = min(current_progress + int(progress_for_task * downloaded_size / total_size), 99) |
| 248 | + if new_progress != last_progress: |
| 249 | + nc.set_init_status(new_progress) |
| 250 | + last_progress = new_progress |
| 251 | + os.replace(temp_path, result_path) |
| 252 | + except Timeout as e: |
| 253 | + raise ModelFetchError(f"Timeout acquiring lock for '{model_path}'") from e |
251 | 254 |
|
252 | 255 | return result_path |
253 | 256 |
|
@@ -277,10 +280,13 @@ def display(self, msg=None, pos=None): |
277 | 280 | if sep: |
278 | 281 | safe_model_name = safe_model_name.replace(sep, "_") |
279 | 282 | lock_path = os.path.join(cache, f"{safe_model_name}.lock") |
280 | | - with SoftFileLock(lock_path, timeout=LOCK_TIMEOUT): |
281 | | - return snapshot_download( |
282 | | - model_name, tqdm_class=TqdmProgress, **download_options, max_workers=workers, cache_dir=cache |
283 | | - ) |
| 283 | + try: |
| 284 | + with SoftFileLock(lock_path, timeout=LOCK_TIMEOUT): |
| 285 | + return snapshot_download( |
| 286 | + model_name, tqdm_class=TqdmProgress, **download_options, max_workers=workers, cache_dir=cache |
| 287 | + ) |
| 288 | + except Timeout as e: |
| 289 | + raise ModelFetchError(f"Timeout acquiring lock for model '{model_name}'") from e |
284 | 290 |
|
285 | 291 |
|
286 | 292 | def __nc_app(request: HTTPConnection) -> dict: |
|
0 commit comments