feat: retain uploaded STL files for recovery

This commit is contained in:
2026-07-22 02:24:59 +02:00
parent 238ec17155
commit f8bc737214
5 changed files with 18 additions and 11 deletions
@@ -0,0 +1 @@
ALTER TABLE "manual_upload_files" ADD COLUMN "retainedAt" TIMESTAMP(3);
+1
View File
@@ -937,6 +937,7 @@ model ManualUploadFile {
filePath String // Path on shared volume filePath String // Path on shared volume
fileSize BigInt fileSize BigInt
packageId String? // Set after processing packageId String? // Set after processing
retainedAt DateTime?
upload ManualUpload @relation(fields: [uploadId], references: [id], onDelete: Cascade) upload ManualUpload @relation(fields: [uploadId], references: [id], onDelete: Cascade)
+15 -2
View File
@@ -180,12 +180,25 @@ verify_file_references() {
local database_user="${POSTGRES_USER:-dragons}" local database_user="${POSTGRES_USER:-dragons}"
local database_name="${POSTGRES_DB:-dragonsstash}" local database_name="${POSTGRES_DB:-dragonsstash}"
docker compose exec -T db psql --no-psqlrc --tuples-only --no-align --quiet \ docker compose exec -T db psql --no-psqlrc --tuples-only --no-align --quiet \
--field-separator=$'\t' \
--username "$database_user" --dbname "$database_name" \ --username "$database_user" --dbname "$database_name" \
--command 'SELECT "filePath" FROM "manual_upload_files" ORDER BY "filePath"' | --command "SELECT 'legacy', \"filePath\" FROM \"manual_upload_files\" WHERE \"retainedAt\" IS NULL
UNION ALL
SELECT 'retained', \"filePath\" FROM \"manual_upload_files\" WHERE \"retainedAt\" IS NOT NULL
ORDER BY 2" |
docker compose --profile backup run --rm --no-deps -T --entrypoint bash \ docker compose --profile backup run --rm --no-deps -T --entrypoint bash \
-v "$uploads_volume:/data/uploads:ro" backup -ceu ' -v "$uploads_volume:/data/uploads:ro" backup -ceu '
missing=0 missing=0
while IFS= read -r file_path; do while IFS="$(printf "\t")" read -r retention file_path; do
if [[ "$retention" == "legacy" ]]; then
printf "Warning: legacy manual-upload file reference is not required because retainedAt is NULL: %s\\n" "$file_path" >&2
continue
fi
if [[ "$retention" != "retained" ]]; then
printf "Unexpected retention status for database reference: %s\\n" "$file_path" >&2
missing=1
continue
fi
case "$file_path" in case "$file_path" in
/data/uploads/*) relative_path="${file_path#/data/uploads/}" ;; /data/uploads/*) relative_path="${file_path#/data/uploads/}" ;;
*) *)
+1
View File
@@ -55,6 +55,7 @@ export async function POST(request: Request) {
fileName: file.name, fileName: file.name,
filePath, filePath,
fileSize: BigInt(file.size), fileSize: BigInt(file.size),
retainedAt: new Date(),
}, },
}); });
} }
-9
View File
@@ -1,4 +1,3 @@
import path from "path";
import { rm } from "fs/promises"; import { rm } from "fs/promises";
import { db } from "./db/client.js"; import { db } from "./db/client.js";
import { childLogger } from "./util/logger.js"; import { childLogger } from "./util/logger.js";
@@ -200,12 +199,4 @@ export async function processManualUpload(uploadId: string): Promise<void> {
data: { status: "FAILED", errorMessage: message }, data: { status: "FAILED", errorMessage: message },
}); });
} }
// Clean up uploaded files
try {
const uploadDir = path.join("/data/uploads", uploadId);
await rm(uploadDir, { recursive: true, force: true });
} catch {
// Best-effort cleanup
}
} }