Skip to content

Commit 79837f8

Browse files
committed
fix: Throw ModelFetch errors on lock timeout
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
1 parent 5e7b760 commit 79837f8

1 file changed

Lines changed: 49 additions & 43 deletions

File tree

nc_py_api/ex_app/integration_fastapi.py

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
status,
2121
)
2222
from fastapi.responses import JSONResponse, PlainTextResponse
23-
from filelock import SoftFileLock
23+
from filelock import SoftFileLock, Timeout
2424
from starlette.requests import HTTPConnection, Request
2525
from starlette.types import ASGIApp, Receive, Scope, Send
2626

@@ -210,44 +210,47 @@ def __fetch_model_as_file(
210210
) -> str:
211211
result_path = download_options.pop("save_path", urlparse(model_path).path.split("/")[-1])
212212
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
251254

252255
return result_path
253256

@@ -277,10 +280,13 @@ def display(self, msg=None, pos=None):
277280
if sep:
278281
safe_model_name = safe_model_name.replace(sep, "_")
279282
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
284290

285291

286292
def __nc_app(request: HTTPConnection) -> dict:

0 commit comments

Comments
 (0)