Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: hmr with fsCache after concurrent file changes #16222

Closed

Conversation

patak-dev
Copy link
Member

Description

It seems we have a race condition for the fs cached checks when automated refactoring tools are used, or the user changes branches with the dev server open. Issue first reported by @cpojer here

Scenario (with the dev server open):

  • A user renames a file (add, unlink events).
  • It then modifies the import (change event).
  • HMR works properly, the change is processed after add, unlink so the fs cache is already updated.
  • git commit
  • git checkout previous commit (change, add, unlink events triggered concurrently)
  • HMR could break if we process the change event before the rename (add, unlink)

The same could happen with an automated refactoring, depending on the order they do changes.

I don't know how we can support this except by adding debouncing the processing of watch events so we can ensure that the fs cache has time to be updated before we start the HMR processing. This PR adds a 50ms debounce if the fs cache is active.

If this is the only solution to this problem, the tradeoffs of having the fs cache by default changes a bit. We are now trading faster startup and processing for slower HMR. If the needed debounce delay is ~25ms maybe it is acceptable? If we need 50-100ms, then I think we may need to get back to the fs cache being opt-in.

@patak-dev patak-dev added feat: hmr p3-minor-bug An edge case that only affects very specific usage (priority) regression The issue only appears after a new release performance Performance related enhancement labels Mar 21, 2024
Copy link

stackblitz bot commented Mar 21, 2024

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@sapphi-red
Copy link
Member

I don't know how we can support this except by...

I guess the ideal fix would be fixing #10663.

@patak-dev
Copy link
Member Author

Oh, that's a great reference @sapphi-red. Thanks for connecting the dots here. I agree. The fs cache is just making this issue more prominent. So even in the worse case of having to temporarily make it opt-in again, we could have opportunities to bring it back in the future.

@sapphi-red
Copy link
Member

@patak-dev Do you prefer merging this one as a workaround until #10663 is fixed? If so, I'll review this PR.

@patak-dev
Copy link
Member Author

@sapphi-red I was waiting for feedback from @cpojer regarding the minimum value for the delay. If we need to add a 50ms delay, maybe we should disable the cache by default. We could try merging with a 10ms for now to see if that is enough maybe 🤔

@sapphi-red
Copy link
Member

I see. Let's wait for now then 👍

@cpojer
Copy link
Contributor

cpojer commented Mar 25, 2024

Ah, apologies, I didn't realize you were waiting for my input on this issue. Any delay that you are choosing here will inevitably lead to race conditions that only some users will run into some of the time. Why can HMR not wait for the filesystem changes directly?

@patak-dev
Copy link
Member Author

Any delay that you are choosing here will inevitably lead to race conditions that only some users will run into some of the time. Why can HMR not wait for the filesystem changes directly?

The issue is that when you run git switch -, there may be N different files change almost at the same time. Each of these files will trigger a change, add, or unlink event. In the scenario in the description, depending what file git writes first, the events order could trigger reprocessing of a file for HMR (because of a change that modifies an import path that was renamed) before the add/unlink event triggers the invalidation of the fs cache. If we wait for something, we should somehow detect that a git command was executed and wait until the command is done. I don't know if we can do that from Vite.

But about the race condition, given that git should write the branch changes quickly, the delay is just serving as a way to order very close events. So if you try this PR and it works well for a 5-10ms delay, then maybe we can move forward with it. If you need to set it to 50ms (like it is now), then I think we will need to make the fs cache opt-in.

@cpojer
Copy link
Contributor

cpojer commented Mar 27, 2024

I see what you mean. Let's start with a 15ms delay and see how it goes for everyone?

@patak-dev
Copy link
Member Author

I see what you mean. Let's start with a 15ms delay and see how it goes for everyone?

Any chance you could get this branch locally and try it out with 5ms and 10ms? If we go with 15ms, that extra overhead may be there for a long time.

@cpojer
Copy link
Contributor

cpojer commented Mar 28, 2024

I see. Unfortunately I'm traveling for the next two weeks. You could start with 5ms and I can report back after my travels if I'm still running into the same issue.

@patak-dev
Copy link
Member Author

@sapphi-red I'm good merging this with a 5ms delay, let me know what you think

@patak-dev
Copy link
Member Author

/ecosystem-ci run

@patak-dev
Copy link
Member Author

/ecosystem-ci run astro

@vite-ecosystem-ci
Copy link

📝 Ran ecosystem CI on 23d1867: Open

suite result latest scheduled
astro failure success

@patak-dev
Copy link
Member Author

It seems Astro CI in their main is pretty unstable right now: https://github.com/withastro/astro/commits/main/

@patak-dev
Copy link
Member Author

/ecosystem-ci run

@vite-ecosystem-ci
Copy link

📝 Ran ecosystem CI on 23d1867: Open

suite result latest scheduled
astro failure success
sveltekit failure success

analogjs, histoire, ladle, laravel, marko, nuxt, previewjs, quasar, qwik, rakkas, remix, unocss, vike, vite-plugin-pwa, vite-plugin-react, vite-plugin-react-pages, vite-plugin-react-swc, vite-plugin-svelte, vite-plugin-vue, vite-setup-catalogue, vitepress, vitest

@sapphi-red
Copy link
Member

It seems to be because astro expects the event to happen sync when server.watcher.emit is called.
https://github.com/withastro/astro/blob/0ff5d72c7841e10065d37b43322358f4a48b7e95/packages/astro/test/units/dev/dev.test.js#L101
https://github.com/withastro/astro/blob/0ff5d72c7841e10065d37b43322358f4a48b7e95/packages/astro/test/units/test-utils.js#L118-L125

I'll take a look if I can fix #10663 easily as I checked the related code quite recently by coincidence.

@sapphi-red sapphi-red deleted the fix/fs-checks-with-concurrent-file-structure-changes branch March 29, 2024 06:24
@patak-dev
Copy link
Member Author

@cpojer, #16303 has been released in vite@5.2.7. Let us know if you experience further issues with HMR after changing git branches. Shoutout again to @sapphi-red for implementing and pushing for the right fix here 💚

@cpojer
Copy link
Contributor

cpojer commented Mar 29, 2024

Thanks so much. I will report back in case there are issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: hmr p3-minor-bug An edge case that only affects very specific usage (priority) performance Performance related enhancement regression The issue only appears after a new release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants