Visitar URL original
fix(file-provider): Properly handle cancellations by claucambra · Pull Request #11001 · nextcloud/desktop · GitHub
Skip to content

fix(file-provider): Properly handle cancellations - #11001

Open
claucambra wants to merge 49 commits into
masterfrom
work/fp-cancellations
Open

claucambra wants to merge 49 commits into
masterfrom
work/fp-cancellations

Conversation

@claucambra

@claucambra claucambra commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Resolves

Second fix for #10579

Summary

Ensures cancellation propagates through File Provider uploads, downloads, and thumbnail fetches. Previously, cancellation did not consistently reach the surrounding operation or its supporting network requests, allowing cancelled operations to continue, update database state, and potentially report success

Checklist

AI (if applicable)

@claucambra claucambra added this to the 35.0.0 milestone Oct 5, 2026
@claucambra claucambra self-assigned this Oct 5, 2026
@claucambra claucambra added os: 🍎 macOS Apple macOS, formerly also known as OS X feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. labels Oct 5, 2026
@claucambra claucambra changed the title fix(file-provider): Properly handle fix(file-provider): Properly handle cancellations Oct 5, 2026
@i2h3

i2h3 commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

@claucambra Please rebase onto master and resolve the conflicts.

@claucambra
claucambra force-pushed the work/fp-cancellations branch from 67f30c7 to a27c618 Compare October 6, 2026 09:11
@claucambra

Copy link
Copy Markdown
Collaborator Author

@claucambra Please rebase onto master and resolve the conflicts.

Rebased and resolved now

@claucambra
claucambra force-pushed the work/fp-cancellations branch from a27c618 to 8336b0f Compare October 6, 2026 09:12

@i2h3 i2h3 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 8336b0f. Main points:

  1. A cancelled fetch is persisted as .downloadError, which blocks later depth-1 metadata updates for that item (Item+Fetch.swift).
  2. A chunked upload cancelled during assembly reports cancellation although the server committed the file (Upload.swift).
  3. Upload cancellation has no tests; the new upload mock hooks are unused.

The rest are edge cases and test-robustness notes. The NetworkOperationCancellation helper and the thumbnail batching look correct to me (Darwin invokes cancellationHandler asynchronously, so no lock re-entrancy; registrations are sequential).

Hygiene: only 2 of 22 commits carry an Assisted-by: trailer while the PR declares AI assistance; please add it where it applies. At ~2.4k changed lines across uploads, downloads, thumbnails, capabilities and account waits, splitting the helper + uploads from the download changes would ease review. The failing classic-client PermissionsTest is unrelated.

Review prepared with AI assistance (Claude Code) and checked against the head commit.

@claucambra claucambra modified the milestones: 35.0.0, 35.0.1 Oct 12, 2026
@claucambra
claucambra requested a review from i2h3 October 13, 2026 14:17
@claucambra
claucambra force-pushed the work/fp-cancellations branch 2 times, most recently from adce455 to 5890733 Compare October 15, 2026 06:10

@i2h3 i2h3 left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. b4361ca clears deleted on unchanged rows in every non-paginated depth-1 read, which brings back local-only deletions (inline).
  2. cancelledWaiterDoesNotWaitForAccountTimeout still hangs instead of failing if cancellation regresses (inline).
  3. 4 of 40 commits mention Assisted-by: Codex:GPT-6, and in each a blank line separates it from Signed-off-by, so git parses only one of the two as a trailer. Please add the trailer to every commit with AI-assisted content, in the same block as Signed-off-by.

Review prepared with AI assistance (Claude Code) and checked against the head commit.

@claucambra claucambra modified the milestones: 35.0.1, 35.0.2 Oct 27, 2026
@claucambra
claucambra force-pushed the work/fp-cancellations branch 2 times, most recently from 500fce4 to 00e796f Compare October 28, 2026 17:48
@claucambra
claucambra requested a review from i2h3 October 28, 2026 17:49

@i2h3 i2h3 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 40d5802. The three points from the last round are resolved: the depth-1 un-tombstoning is gone, cancelledWaiterDoesNotWaitForAccountTimeout is bounded, and every commit now carries Assisted-by and Signed-off-by as trailers. swift test passes locally (XCTest: 460 tests, 1 skipped; Swift Testing: 129 tests).

One blocker remains (inline): a package fetch now returns success without the members whose rows are tombstoned.

Notes, not blocking:

  • directoryDownloadMetadatas also takes the remote fields (serverUrl, fileName, etag, size) from the database row. Depth-1 reads never refresh a member row in .downloadError or .downloading, so if such a member is renamed on the server, every retry requests the old path, gets a 404 and fails the package with noSuchItem. Master used the listing and recovered on the next attempt. Taking the remote fields from the listing fixes this together with the blocker.
  • A member moved between subfolders during a fetch is listed twice, and the second beginDownload supersedes the fetch's own earlier child operation, so the fetch fails with cannotSynchronize. A retry recovers.
  • The Lint job fails on new SwiftFormat rules (nestedIf, repeatedGuard, noForceUnwrapInTests). Master fails the same job, but Item+Fetch.swift, FilesDatabaseManager+Downloads.swift, MockRemoteInterface.swift and ItemModifyTests.swift are among the flagged files.

Review prepared with AI assistance (Claude Code) and checked against the head commit.

@nilsding nilsding modified the milestones: 35.0.2, 35.0.3 Oct 30, 2026
@claucambra
claucambra requested a review from i2h3 October 30, 2026 08:49
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…ail instead of hanging

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…d overlapping names

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…imeout, waiting for actual registration

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…ack to normal, downloaded set to false, no session error

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
… for later changes

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…m NextcloudKit

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…chunked uploads through upload, create and modify

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…en more than one task depends on it

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…erly waiting for account setup

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
…ownload

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Require the release that preserves committed chunk-upload results when
cancellation arrives during assembly.


Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Verify create and modify persist completed chunked uploads despite
cancellation, including the server identity, ETag and chunk cleanup.

Reopen Realm after the async modify before checking chunk rows so the
existing exclusion test does not access a Realm from another thread.

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Keep unchanged local tombstones during ordinary depth-1 reads. Restore
listed file rows only for an explicit folder download, before transfers
start, without rewriting live or in-flight metadata.

Cover ignored files, excluded bundles, missing rows, local state and
deletions made after the directory listing.

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Bound both waiter registration and task completion with the existing
async test helpers. Release any stranded account waiter during cleanup
so a cancellation regression fails instead of hanging the test run.

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Assisted-by: Codex:GPT-6
Select children from persisted metadata without undeleting or recreating
records. Skip deleted subtrees and retain nested directory ownership
through traversal so late deletions cannot be overwritten.

Cover deleted children, missing records, late deletions, and nested
folder success, failure and cancellation.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Use a unique temporary destination for each folder fetch and remove
unreturned contents after failure or cancellation. Retries cannot reuse
partial contents or overwrite a previously returned folder.

Cover retries after partial failure and cancellation, successive fetches,
and cleanup of unreturned directories.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Map missing child metadata at download completion to cannotSynchronize
instead of reporting the requested parent folder as missing. Keep direct
file completion and missing requested-folder errors unchanged.

Reproduce a parent enumeration marking an active child deleted after its
contents arrive, covering files and nested folders.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Keep child download ownership until the folder is ready to return, then
publish the folder and all children in one Realm transaction. Discarded
fetches clear only the state they still own, preserving newer results
and recorded transfer errors.

Cover partial failure, cancellation during final lookups, supersession
and atomic publication failure.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Treat NextcloudKit's overloaded -5 code as cancellation only when the
upload operation was cancelled. Preserve other preparation failures,
including empty chunks, instead of reporting userCancelled.

Cover both File Provider error mappers and the upload workflow while
retaining actual cancellation and committed assembly result coverage.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Restore missing or inactive deleted member rows through a dedicated
helper for package downloads. Preserve local metadata, cancellation and
ownership checks. Keep ordinary directory downloads' tombstone
selection unchanged.

Use current server listings for package transfer paths, including
renamed members on retry and nested folders within packages.

Cover package exclusion and reappearance, package and ordinary
directory boundaries, cancellation, ownership and atomic restoration.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Use the database to filter deleted children, then transfer live children
using the current server listing. Preserve stored local metadata and
missing-row checks instead of replacing fresh paths with stale fields.

Cover renamed-member retries for ordinary folders and packages, and
selection across transfer states without changing database rows.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Use persisted store identity to share download ownership across reopened
managers. Restore package members and publish completed folder downloads
in GRDB transactions while retaining local metadata and ownership checks.

Port database regressions and chunk assertions to the current test APIs.
Preserve store identity during fixture resets and recover test schemas
without relying on cached table-existence information.

Assisted-by: Codex:GPT-6
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
@claucambra
claucambra force-pushed the work/fp-cancellations branch from 3e3c0ce to 4b8c083 Compare October 30, 2026 11:09
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. os: 🍎 macOS Apple macOS, formerly also known as OS X

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants