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

Remove existing mirrored cells before generating new #5820

Closed
wants to merge 1 commit into from

Conversation

Tobbe
Copy link
Member

@Tobbe Tobbe commented Jun 24, 2022

Fixes #5775

Splits the generator file watching into two. One for the API side and one for the Web side.
The Web side watcher now also watches for directory changes. It was the only way to catch directories that were being renamed. When a Cell directory is unlinked we now also remove the corresponding mirror directory.

@netlify
Copy link

netlify bot commented Jun 24, 2022

Deploy Preview for redwoodjs-docs canceled.

Name Link
🔨 Latest commit 5fec6ff
🔍 Latest deploy log https://app.netlify.com/sites/redwoodjs-docs/deploys/62c053007832140007046671

@Tobbe Tobbe added the release:fix This PR is a fix label Jun 24, 2022
@dac09
Copy link
Collaborator

dac09 commented Jun 24, 2022

My only issue with this stuff is that we're increasing file system operations on every change. This really does add up over time. Can we not remove the files specifically when its renamed/removed?

@Tobbe
Copy link
Member Author

Tobbe commented Jun 24, 2022

@dac09 I don't think it's too bad, because this code is only run when you manually run yarn rw g types or when you run some other command that in turns run the type generator.

To specifically remove the affected files when something is renamed/removed we'd need to run a watcher to detect the renaming/removal, right? Or do we already have a watcher on the cells I can leverage?

Copy link
Collaborator

dac09 commented Jun 24, 2022

We already have watchers for each type - that’s how we know to generate mirror cells I think!

Won’t it run when running the generate subprocess in rw dev?

@Tobbe
Copy link
Member Author

Tobbe commented Jun 24, 2022

No, we explicitly run generateTypes or whatever it's called as a separate step in the cell generator. No watchers for that stuff

Copy link
Collaborator

dac09 commented Jun 24, 2022

I believe its the same function as we use in the watcher. If you check packages/internal/package.json - the rw-gen and rw-gen-watch commands reference the same generate function - so it will be triggered on any file changes

See packages/internal/src/generate/watch.ts for where we filter Cell files, and we use the “all” event, but we could be smarter about this.

Copy link
Member Author

Tobbe commented Jun 24, 2022

Ohh, so we do both! TMYK. Thanks Danny. I'll see what I can do then.

Copy link
Collaborator

dac09 commented Jun 24, 2022

✌️

@Tobbe Tobbe marked this pull request as ready for review July 2, 2022 20:31
@Tobbe
Copy link
Member Author

Tobbe commented Jul 3, 2022

@dac09 This is ready for a new review. Thanks :)

// A Cell must be a directory named module.
if (!dir.endsWith(name)) {
// A cell must end with "Cell.{jsx,js,tsx}".
if (!name.endsWith('Cell')) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this change?

I'm wondering if this has a downstream impact elsewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

We used to have the name check out in the watcher function, but I thought it was such a fundamental check that I wanted it to be part of the isCellFile check itself. So that we always check this when checking if a file is a Cell.

The reason I removed the "directory named module"-check is because I think it's wrong. In one of my projects I have a "child cell" (for a waterfall kind of setup), and I chose to put that Cell in the same directory as the parent Cell. Works great.

This also aligns with the comment in RWCell.ts in the structure package:

  /**
   * A "Cell" is a component that ends in `Cell.{js, jsx, tsx}`, has no
   * default export AND exports `QUERY`
   **/

And it aligns with our public facing docs

Redwood looks for all files ending in "Cell" (so if you want your component to be a Cell, its filename does have to end in "Cell"), but if the file 1) doesn't export a const named QUERY and 2) has a default export, then it'll be skipped.
https://redwoodjs.com/docs/cells#how-does-redwood-know-a-cell-is-a-cell

As far as downstream impact goes the isCellFile function is used (by extension) in our type generator and directly in the watcher. So I think we're good on that front.

Looking at all this again I think maybe we should also remove the check for a Success export below to further align this implementation with the other code and docs

Copy link
Collaborator

@dac09 dac09 Jul 4, 2022

Choose a reason for hiding this comment

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

Would the generated mirror types be correct for a non-directory-import Cell? If so, happy with it and makes sense.

Also agreed about the fact that a cell shouldn't need to be in a directory named module.

Copy link
Member Author

Choose a reason for hiding this comment

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

The project I'm referring to is actually a JS project. So I only know that the basic Cell functionality works. Don't know about the types. I'll make sure to test it manually.

@dac09
Copy link
Collaborator

dac09 commented Jul 4, 2022

Bit of feedback here as well @Tobbe - https://s.tape.sh/LiBfply6

Not working as expected on Gitpod/linux

dac09
dac09 previously requested changes Jul 4, 2022
Copy link
Collaborator

@dac09 dac09 left a comment

Choose a reason for hiding this comment

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

Left a few comments, and test on gitpod didn't quite work!

Copy link
Member Author

@Tobbe Tobbe left a comment

Choose a reason for hiding this comment

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

@dac09 replied to your code comments. Thanks for your review as always. Will watch your tape next.

// A Cell must be a directory named module.
if (!dir.endsWith(name)) {
// A cell must end with "Cell.{jsx,js,tsx}".
if (!name.endsWith('Cell')) {
Copy link
Member Author

Choose a reason for hiding this comment

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

We used to have the name check out in the watcher function, but I thought it was such a fundamental check that I wanted it to be part of the isCellFile check itself. So that we always check this when checking if a file is a Cell.

The reason I removed the "directory named module"-check is because I think it's wrong. In one of my projects I have a "child cell" (for a waterfall kind of setup), and I chose to put that Cell in the same directory as the parent Cell. Works great.

This also aligns with the comment in RWCell.ts in the structure package:

  /**
   * A "Cell" is a component that ends in `Cell.{js, jsx, tsx}`, has no
   * default export AND exports `QUERY`
   **/

And it aligns with our public facing docs

Redwood looks for all files ending in "Cell" (so if you want your component to be a Cell, its filename does have to end in "Cell"), but if the file 1) doesn't export a const named QUERY and 2) has a default export, then it'll be skipped.
https://redwoodjs.com/docs/cells#how-does-redwood-know-a-cell-is-a-cell

As far as downstream impact goes the isCellFile function is used (by extension) in our type generator and directly in the watcher. So I think we're good on that front.

Looking at all this again I think maybe we should also remove the check for a Success export below to further align this implementation with the other code and docs

packages/internal/src/generate/watch.ts Show resolved Hide resolved
packages/internal/src/generate/watch.ts Show resolved Hide resolved
@Tobbe
Copy link
Member Author

Tobbe commented Jul 4, 2022

Thanks for the tape @dac09

I've noticed that it's a bit flaky on my Mac as well unfortunately, especially with detecting deleted folders as you noticed. I will play around with it a bit in GitPod and see if the event names etc are the same as on Mac.

Not sure here, but for deleted folders, if we don't detect that, potentially we'll have "orphaned" mirror files in .redwood/, right? But as long as those don't have a an actual Cell in /web/src/... to merge with they won't actually do anything, will they?

I was thinking of adding a "garbage collection" step in watcher.on('ready'), so on startup it will first always delete all mirror files, and then generate new ones. What do you think about that?

Also, how do you feel about setting the bar at "better than it was before" instead of "perfect"? I'd really like to aim for "perfect" but I just don't know how feasible that is.


EDIT: Just realized another thing. If the user does some changes, like renaming or deleting a folder, while the dev server isn't running we need the GC step to get .redwood/ back in a good state when the user eventually does start the dev server back up. Also need to make sure manually running yarn rw g types does the GC

unlink: 'Deleted',
change: 'Modified',
}
const dirWatcher = chokidar.watch('src', {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Was there a reason to separate these watchers? I'm not 100% sure, but I think spinning up more watchers is discouraged, especially on systems with a big FS penalty e.g. Windows, and certain scenarios with docker.

Copy link
Member Author

@Tobbe Tobbe Jul 4, 2022

Choose a reason for hiding this comment

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

Yes. It's a trade-off I guess. This dirWatcher is going to be watching a lot more files because of the less restrictive pattern. To limit that, I split it up so that I could keep the more restrictive pattern for the API side. Because on that side we don't have to watch for folder deletions.

But if you think it's still better to just watch everything across both the api side and the web side with a single watcher I can easily switch to that instead

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can't speak with full confidence which is better really! Let's leave it as is, but worth doing a check on Windows maybe, but its also super hard to quantify the impact of something like this.

@dac09
Copy link
Collaborator

dac09 commented Jul 4, 2022

I was thinking of adding a "garbage collection" step in watcher.on('ready'), so on startup it will first always delete all mirror files, and then generate new ones. What do you think about that?

Yeah that will likely solve a bunch of cases, especially if we do a fresh generate right after.

Also, how do you feel about setting the bar at "better than it was before" instead of "perfect"? I'd really like to aim for "perfect" but I just don't know how feasible that is.

Yeah totally ok 👌, was pointing out incase you hadn't noticed, we don't need to solve all the edge cases now.

@dac09
Copy link
Collaborator

dac09 commented Dec 13, 2022

Found this again @Tobbe - lets pick this up again?

Copy link
Member Author

Tobbe commented Dec 13, 2022

Would be really great to get a solution in place for this for sure. But for now I want to focus on auth 🙂

@Tobbe
Copy link
Member Author

Tobbe commented Dec 17, 2023

I'm not going to have time to prioritize this anytime soon. If anyone else wants to pick this one back up, please feel free to do so 🙂

@Tobbe Tobbe closed this Dec 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Typescript is Broken when Renaming Cells
2 participants