fix(backend): replace hardcoded /tmp paths with Python tempfile module#775
Open
m4cd4r4 wants to merge 6 commits intohotosm:devfrom
Open
fix(backend): replace hardcoded /tmp paths with Python tempfile module#775m4cd4r4 wants to merge 6 commits intohotosm:devfrom
m4cd4r4 wants to merge 6 commits intohotosm:devfrom
Conversation
Refs hotosm#597. Every backend write to a hardcoded /tmp/... path is replaced with tempfile-managed temporary files and directories: - GCP upload: NamedTemporaryFile + finally-unlink around the S3 put - Waypoint flightplan generation (terrain-follow + plain): one tempfile.mkdtemp per request, cleaned up synchronously on the non-download path, or via a FileResponse BackgroundTask after the stream completes on the download path - generate-kmz endpoint: same mkdtemp + BackgroundTask pattern - project_logic.process_waypoints_and_waylines + terrain-follow DEM path: TemporaryDirectory context managers (cleanup on exceptions) - jaxa/upload_dem worker: tempfile.mkdtemp + finally shutil.rmtree, replacing the hand-rolled per-project cleanup - image_processing ODM download: tempfile.mkdtemp (existing rmtree cleanup in finally was already correct) - reflight download endpoint: tempfile.mkdtemp + BackgroundTask flightplan_output.build_flightplan_download_response gains an optional cleanup BackgroundTask parameter so routes that write into a temp dir can hand the directory's lifetime over to Starlette. This keeps the download endpoints from having to choose between "leak the file" and "delete it before FileResponse can read it". The vendored drone-flightplan package still has /tmp defaults in its output writers - that will be addressed in a follow-up PR against hotosm/drone-flightplan directly to keep this PR reviewable.
spwoodcock
reviewed
Apr 8, 2026
Member
spwoodcock
left a comment
There was a problem hiding this comment.
Cool! I've wanted to see this for ages - thank you 😁
Only comment so far, without a good review, is that the drone-flightplan package is actually in this repo too, under src/backend/packages/drone-flightplan, so could be updated too =)
Member
|
This is really useful & appreciated, but I just realised it was made against It's significantly out of sync now - sorry! |
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.
Fixes #597 (backend portion).
Summary
Every backend write to a hardcoded
/tmp/...path is replaced with temporary files and directories managed by thetempfilemodule. This stops the server's disk from filling up over time because temporary files are now cleaned up automatically (either via context managers,finallyblocks, or StarletteBackgroundTasks).Changes
app/gcp/gcp_routes.py-save_gcp_filenow writes the upload viatempfile.NamedTemporaryFile(delete=False)and unlinks the file in afinallyblock once the S3 put returns.app/waypoints/waypoint_routes.py- bothgenerate_waypointandgenerate_wmpl_kmzroute flightplan generation through onetempfile.mkdtempdirectory per request. For the download path the temp dir's lifetime is handed toFileResponseas aBackgroundTask(shutil.rmtree) so the file can still stream before being removed. For the non-download path the temp dir is removed synchronously. Errors during generation wipe the temp dir immediately. Thegenerate_kmz_with_placemarksendpoint follows the same mkdtemp + BackgroundTask pattern.app/waypoints/flightplan_output.py-build_flightplan_download_responsegets an optionalcleanup: BackgroundTaskparameter that it passes through toFileResponse(background=...). This keeps the download endpoints from having to choose between "leak the file" and "delete it before FileResponse can read it".app/projects/project_logic.py- the terrain-follow DEM path insideupdate_projects_flight_metricsand theprocess_waypoints_and_waylineshelper both usetempfile.TemporaryDirectorycontext managers. Cleanup now happens automatically, including on exceptions, replacing the hand-rolledos.makedirs+try/finally shutil.rmtree.app/jaxa/upload_dem.py- the DEM download worker replacesPath(f"/tmp/tif_processing/{project_id}")withtempfile.mkdtemp(prefix=f"dtm-dem-{project_id}-")and a simplefinally: shutil.rmtree(...). The previous hand-rolled glob-and-unlink cleanup is gone.app/images/image_processing.py- ODM asset download now usestempfile.mkdtemp(prefix=\"dtm-odm-\"). The existingfinallyblock already removed the directory, so behaviour is preserved.app/projects/classification_routes.py- the reflight download endpoint now writes the KMZ inside atempfile.mkdtempdirectory and schedulesshutil.rmtreeas aBackgroundTaskinstead ofos.removeon the single file.Not in this PR
The vendored
drone-flightplanpackage undersrc/backend/packages/drone-flightplan/still has/tmpdefaults in its output writers (mavlink.py,litchi.py,dji.py,qgroundcontrol.py,create_flightplan.py). Those belong upstream at hotosm/drone-flightplan and will be addressed in a follow-up PR there so this one stays reviewable.Verification
python -m py_compilepasses on all seven touched filesruff checkpasses with no findings on all seven touched filesgrep -rn "/tmp/" src/backend/app/returns no matches other than a comment line referencing the system temp rootTest plan
POST /waypoint/task/{task_id}/withdownload=true- file should be served and the temp dir should be gone from the server after the stream