Skip to content

refactor: resource fetcher#1023

Open
chmjkb wants to merge 9 commits intomainfrom
@chmjkb/resource-fetcher-refactor
Open

refactor: resource fetcher#1023
chmjkb wants to merge 9 commits intomainfrom
@chmjkb/resource-fetcher-refactor

Conversation

@chmjkb
Copy link
Copy Markdown
Collaborator

@chmjkb chmjkb commented Mar 27, 2026

Description

  • Extracted shared base class (BaseResourceFetcherClass) into the core package containing the fetch loop, source dispatching, and pause/resume/cancel plumbing — eliminating duplication between expo and bare
    implementations
  • Extracted platform-specific handlers (handlers.ts) for both packages, separating download mechanics from the class structure
  • Rewrote both fetchers as classes extending the base, implementing only platform-specific file system and download operations
  • Replaced the linked-list download pattern with a simple sequential for loop
  • Cancel now throws DownloadInterrupted instead of returning null, giving callers a consistent error-based API

Note: this PR still uses the legacy FS as the support for background / resumable downloads is WIP.

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)
  • New feature (change which adds functionality)
  • Documentation update (improves or adds clarity to existing documentation)
  • Other (chores, tests, code style improvements etc.)

Tested on

  • iOS
  • Android

Testing instructions

  1. Create a demo app trying to run all the functionalities exposed in Resource Fetchers
  2. Fetch function with single and/or multiple resources
  3. Cancel long fetching file, also verify fetch throws an error when its canceled
  4. Check if a model with downloaded file works
  5. Make sure deleting resources work
  6. Try running a background download

Screenshots

Related issues

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

Additional notes

@chmjkb chmjkb marked this pull request as ready for review March 31, 2026 10:07
@chmjkb chmjkb force-pushed the @chmjkb/resource-fetcher-refactor branch from e6a0fc4 to 32a80a2 Compare March 31, 2026 10:36
@msluszniak
Copy link
Copy Markdown
Member

Please run yarn lint --fix in the root of the package and push changes

}

downloads.delete(source);
ResourceFetcherUtils.triggerHuggingFaceDownloadCounter(uri);
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.

remove from here, i want those calls to be strictly inside core package so that they are mandatory.
Also there is a bug when we fire those calls even when file is already downloaded (see packages/react-native-executorch/src/utils/ResourceFetcher.ts:128

Comment on lines +114 to +117
if (dl.task) {
// iOS: background downloader cancel
dl.task.stop();
} else if (dl.jobId !== undefined) {
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.

Two things here

  1. why are we checking with (dl.task) and the other time with (dl.jobId !==...) instead of (!dl.jobId)
  2. why are we using those fields (task/jobId) as a proxy for checking what platform we are using, especially since you are then writing comments explaining the platforms

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

regarding the first point, jobId can be 0 which is falsy, so it would incorrectly tread a valid job with id 0 as missing. Task is an object ref, so !downloadHandle.task is safe.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

and regarding the second point, I could do something like this instead, but I'm not sure if its much cleaner though:

    if (Platform.OS === 'ios') {
      if (!downloadHandle.task) {
        throw new RnExecutorchError(
          RnExecutorchErrorCode.ResourceFetcherDownloadFailed,
          'Download task is missing. This should not happen on iOS.'
        );
      }
      downloadHandle.task.stop();
    } else if (Platform.OS === 'android') {
      if (downloadHandle.jobId === undefined) {
        throw new RnExecutorchError(
          RnExecutorchErrorCode.ResourceFetcherDownloadFailed,
          'Download job ID is missing. This should not happen on Android.'
        );
      }
      RNFS.stopDownload(downloadHandle.jobId);
      if (await ResourceFetcherUtils.checkFileExists(downloadHandle.cacheFileUri)) {
        await RNFS.unlink(downloadHandle.cacheFileUri);
      }
    }

@chmjkb chmjkb requested a review from mkopcins April 7, 2026 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resource fetcher should throw on error instead of returning empty array Remove linked list from resourcefetcher implementation

3 participants