feat: enhance GCS upload handling with async support and improved error logging#619
Merged
feat: enhance GCS upload handling with async support and improved error logging#619
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves Google Cloud Storage (GCS) asset upload behavior in the API by moving blocking GCS operations off the event loop, adding configurable timeouts, and making signed URL generation failures non-fatal (with logging) so asset reads don’t hard-fail on transient GCS issues.
Changes:
- Run synchronous
gcs_uploadin a threadpool from the async/asset/uploadendpoint to avoid blocking the event loop. - Add cached GCS client/bucket helpers and configurable lookup/upload timeouts for GCS calls.
- Wrap signed URL generation in
try/exceptand emit a warning log on failure while returningsigned_url=None.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
services/gcs_helper.py |
Adds caching for client/bucket, introduces timeout env vars for GCS operations, and improves signed URL failure handling with logging. |
api/asset.py |
Uses run_in_threadpool to call the synchronous GCS upload from an async route handler. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes backend lock-up behavior seen during batch field-sheet export when asset-related GCS operations hang.
Problem
During
Well Batch Export, the UI loads asset data for each well before PDF generation. If GCS calls stall (upload/check/signing), API requests can hang long enough to make the export appear frozen.Root Cause
POST /asset/uploadruns synchronous GCS work directly inside anasyncroute.What Changed
1) Prevent async event-loop blocking for uploads
api/asset.pyupload_assetnow runsgcs_upload(...)viarun_in_threadpool(...).2) Reduce repeated GCS setup overhead
services/gcs_helper.py@lru_cachefor storage client and default bucket access.3) Add bounded GCS operations + fail-safe signed URLs
services/gcs_helper.pyGCS_LOOKUP_TIMEOUT_SECS(default15)GCS_UPLOAD_TIMEOUT_SECS(default120)bucket.get_blob(...)andblob.upload_from_file(...).generate_signed_url(...)intry/except; logs warning and returnssigned_url=Noneinstead of hanging/failing entire response.Why This Helps
Batch export depends on many asset calls. These changes make those paths more resilient and less likely to stall the request lifecycle, preventing full-export lockups from backend GCS slowness.
Validation
black api/asset.py services/gcs_helper.py(pass)flake8 --extend-ignore=E501 api/asset.py services/gcs_helper.py(pass)pytest tests/test_asset.py -qcould not be executed in this environment due DB connectivity restrictions (localhost:5432blocked in sandbox).Notes
No API contract changes. Behavior change is defensive: when signing fails, responses still succeed with
signed_url: nullinstead of blocking/failing.