Skip to content

Release v9 bytes no row owns, and reuse the v9 blob on a replace - #51

Open
dmurphy5 wants to merge 1 commit into
dylan/v10-7-ios-unreadable-filefrom
dylan/v10-8-adoption-fixes
Open

dmurphy5 wants to merge 1 commit into
dylan/v10-7-ios-unreadable-filefrom
dylan/v10-8-adoption-fixes

Conversation

@dmurphy5

@dmurphy5 dmurphy5 commented Oct 1, 2026

Copy link
Copy Markdown

Description

Two fixes for apps that upgrade from v9 with a chunked upload still pending. Diana's v10 cutover resumes those uploads with a same-id mutate() over the v9 manifest, so both paths matter at release.

  • cancel(id) on an id with no row now deletes the id's directory when it has no entry file. A v9 chunked upload that was still running at the upgrade gets no legacy row, so before this its manifest and blob could never be released.
  • A same-id mutate() over a legacy row whose v9 manifest could not be read now runs over the v9 blob. Before, it ignored the blob and failed with E_FILE_MISSING once the caller's source was gone. A caller file that exists still takes priority. Fixed on Android and iOS.

What to look at

  • QueueStore.removeUnowned on both platforms: what counts as unowned, and that it runs under the store lock on Android and on the coordinator's queue on iOS.
  • The legacy fallback in Android QueueController.decideAndCommit and iOS QueueCoordinator+Enqueue.swift.

Decisions and trade-offs

  • The rule is "no entry file", not "only v9 files". It also removes a body a failed enqueue staged and left behind, which nothing else would delete.
  • A failed delete is not reported, and cancel() still resolves. Release is best effort, like the rest of the v9 cleanup.
  • cancel("") does nothing, as before.

Test plan

  • yarn lint:ci, yarn typecheck, yarn test (189 tests): pass.
  • Android unit tests (:react-native-background-upload:testDebugUnitTest, 313 tests): pass. New cases cover cancel of a row-less v9 folder, of an id with no folder, and a replace over a legacy row with a corrupt manifest.
  • swift test in ios/ (210 tests): pass. New cases cover the iOS cancel and the unreadable-manifest replace. Each new case fails with its fix removed.
  • Not run on a device.

🤖 Generated with Claude Code

cancel(id) on an id with no row resolved and did nothing, so a v9 chunked
upload that was still running at the upgrade, which gets no legacy row,
kept its manifest and blob on disk for good. cancel(id) now deletes the
id's directory when it has no entry file. A live entry and another id's
directory are never touched.

A same-id mutate() over a legacy row whose v9 manifest could not be read
ignored the v9 blob, so it failed E_FILE_MISSING when the caller's source
was already gone. It now runs over that blob on both platforms. A caller
file that exists still wins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dmurphy5
dmurphy5 marked this pull request as ready for review October 1, 2026 18:11
@dmurphy5
dmurphy5 requested a review from elliottkember October 1, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants