Files
projectsend/app/Modules/Files/Uploads
denkfabrik-li f2b705beee Keep an upload's parts until its bytes are stored
complete() holds a lock whose comment promises "the lock's TTL releases
the claim if a completion dies mid-flight, so a later retry still works".
A retry has nothing to work from but the parts, and assemble() unlinked
each one inside the loop that read it -- so everything that can fail
afterwards took the retry with it.

Measured on main, with a disk refusing the write (the case the guard forty
lines further down was written for, found against a real GCS bucket):

  first complete  → 422, 0 parts left, the half-written copy left behind
  retry           → 422 "Upload is incomplete: missing parts."

For good: listParts() is empty, so no later attempt can ever succeed, and
the client has to send the whole file again. The abandoned copy sat in the
session directory until the sweeper came round.

The parts now go when abort() clears the session directory -- which
already ran on success -- and a failure deletes only the half-written copy
it made. The cost is temp space: peak usage during assembly is the whole
file twice over rather than the file plus one part. The docblock says so.

Also checked while here: every read and every write in the concatenation.
A failing fwrite is loud in practice, since Laravel's error handler turns
the warning into an ErrorException, but loud there is a 500 carrying a PHP
message where this method's other storage failure is a sentence the person
uploading can act on. A short write arriving without a warning would be
worse: the byte count and the checksum describe the buffer that was read,
so an unchecked one records a truncated file with a checksum matching
bytes that were never stored.

Two tests: the retry after a refused write now succeeds, and a temporary
directory that refuses writes (/dev/full, skipped where it does not exist)
fails the upload with this method's own message. Without the fix both go
red.
2026-08-28 06:40:47 +02:00
..
2026-08-14 01:38:12 -03:00
2026-08-14 01:38:12 -03:00
2026-08-14 01:38:12 -03:00
2026-08-14 01:38:12 -03:00
2026-08-14 01:38:12 -03:00