uploader: resume a session interrupted before it ever reached publish - #29
Open
Chris-Schnaufer wants to merge 5 commits into
Open
uploader: resume a session interrupted before it ever reached publish#29Chris-Schnaufer wants to merge 5 commits into
Chris-Schnaufer wants to merge 5 commits into
Conversation
beginResume awaited loadSession(batch.id) — an IndexedDB read — before touching the folder handle's requestPermission(), the native directory picker, or the hidden <input> fallback's .click(). Firefox and Safari require those to fire within the click's transient user-activation window; an unrelated await ahead of them silently breaks it, so Resume appeared to do nothing: no prompt, no error, no network activity. Kick the session load off in parallel instead of awaiting it up front, so the gated call is always the first await in the handler. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…esume Resuming re-hashes every recorded file's content against the reselected folder before anything else happens (reconcileReselect -> hashAll), with no feedback on screen while that runs. For a batch of thousands of files this takes real, noticeable time, and looked exactly like Resume doing nothing. Root-caused live: a 17,952-file resume reached the re-hash step and simply had no further observable state change until it finished. Thread an optional, ~150ms-throttled onProgress callback from hashAll up through reconcileReselect and restoreFromHandle, and surface it in History as "Verifying N of M files against the original folder…". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Was a page-level note above the whole list; move it into the specific batch's row (next to its Resume/Discard buttons), and label the button "Verifying…" during that phase — matches "Resuming…" for the run itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ounts Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A streamed upload cancelled before its blob queue closed (e.g. navigating to History mid-upload) has no bundle yet — resumeUpload used to flatly refuse and tell the user to start a fresh upload, but a fresh upload stamps a brand-new destination prefix and doesn't skip anything already sitting under the abandoned one, wasting a full re-upload of a large batch. Add resume.ts's ensureBundle: for a bundle-less session, resolve every still-`awaiting-processing` record from the same re-hash pass reconciliation already does (reconcileReselect/restoreFromHandle now expose full Inspect- equivalent results, not just sha256), persist them, and build+attach the bundle — reusing the original persisted uploadPrefix verbatim, never a new stamp. A file whose hash couldn't be resolved, or whose only capture-time source was a manual Assign entry (unrecoverable here — never persisted for a file that hadn't finished Inspect), surfaces as a blocking problem instead of silently publishing incomplete metadata. - bundle.ts: extract namingForUploadPath (same sanitize/collision logic as resolveBatchNaming, against a fixed prefix instead of a fresh stamp) and add buildBundleFromRecords (bundle payloads from persisted record metadata alone, no file bytes needed). - db.ts: add updateFileRecords for one bulk write instead of one transaction per file. - History.tsx: all three resume entry points call ensureBundle first. - upload.ts: resumeUpload's "no bundle" error is now a rare fallback; reworded since it no longer tells the user to start a fresh upload. - New tests: naming reconstructed from persisted records matches the original run exactly (including a collision case), and buildBundleFromRecords emits a valid bundle. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Juli4nG
requested changes
Aug 12, 2026
Juli4nG
left a comment
Collaborator
There was a problem hiding this comment.
Really like this one. Three things before merge:
- ensureBundle only checks capture times on files that never finished Inspect. A no-EXIF file that did finish gets saved with an empty time, slips through, and publishes an empty timestamp column. Anything missing a time should block, not just the unfinished ones.
- If ensureBundle fails, the tile stays stuck on "Verifying…".
- This writes an empty observations.csv but #17 changes that to one row per file. Whichever merges second has to match the other. Left the same note there.
(reviewed with fable 5 + gpt-5.6-sol)
This was referenced Aug 12, 2026
5 tasks
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.
A streamed upload cancelled before its blob queue closed (e.g. navigating to History mid-upload) has no bundle yet —
resumeUploadused to flatly refuse and tell the user to start a fresh upload, but a fresh upload stamps a brand-new destination prefix and doesn't skip anything already sitting under the abandoned one, wasting a full re-upload of a large batch.resume.ts's newensureBundle: for a bundle-less session, resolves every still-awaiting-processingrecord from the same re-hash pass reconciliation already does (reconcileReselect/restoreFromHandlenow expose full Inspect-equivalent results, not just sha256), persists them, and builds+attaches the bundle — reusing the original persisteduploadPrefixverbatim, never a new stamp. A file whose hash couldn't be resolved, or whose only capture-time source was a manual Assign entry (unrecoverable here), surfaces as a blocking problem instead of silently publishing incomplete metadata.bundle.ts: extractednamingForUploadPathand addedbuildBundleFromRecords(bundle payloads from persisted record metadata alone).db.ts: addedupdateFileRecordsfor one bulk write instead of one transaction per file.History.tsx: all three resume entry points callensureBundlefirst.upload.ts:resumeUpload's "no bundle" error is now a rare fallback, reworded since it no longer tells the user to start a fresh upload.buildBundleFromRecordsemits a valid bundle.Verified live against a real interrupted 17,952-file batch — resume now completes instead of erroring out.
Depends on #27 and #28 (both not yet merged) — this branch is based on top of
fix/resume-large-batch-verify-progress, which is based onfix/resume-permission-lost-user-activation.