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

Add custom fingerprinting and build cache #589

Merged
merged 5 commits into from
Oct 4, 2024

Conversation

jakub-gonet
Copy link
Member

  • Extracts logic responsible to writing build info from build manager so we always use correct fingerprints
  • Replaces buildScript in configuration with customBuild object that allows using custom build and fingerprinting scripts

Testing

Checked force rebuilds, closing IDE while building, and detecting changed fingerprints when file change for regressions.
Checked custom fingerprints when closing and opening IDE and when project files change (installing new native dependency, changing fingerprint and saving file).

Copy link

vercel bot commented Oct 3, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
radon-ide ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 4, 2024 10:38am

Comment on lines 588 to 600
private checkIfNativeChanged = throttle(async (cancelToken: CancelToken) => {
if (!this.buildCacheInvalidated && this.projectState.selectedDevice) {
// TODO: should be refactored to not create a new PlatformBuildCache
// instance every time
const platform = this.projectState.selectedDevice.platform;
const buildCache = new PlatformBuildCache(platform, cancelToken);

if (await buildCache.isCacheInvalidated()) {
this.buildCacheInvalidated = true;
this.eventEmitter.emit("needsNativeRebuild");
}
}
}, 300);
Copy link
Member Author

Choose a reason for hiding this comment

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

Build cache shouldn't live here but I considered few options and all of them made structure more complex.

packages/docs/docs/launch-configuration.md Outdated Show resolved Hide resolved
packages/vscode-extension/src/builders/BuildManager.ts Outdated Show resolved Hide resolved
buildResult,
});

await buildCache.storeBuild(buildResult);
Copy link
Member

Choose a reason for hiding this comment

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

The issue here is that we actually want to use the fingerprint from before the build. Since builds take quite some time, there's a chance that someone will update some files that'd impact the fingerprint, in which case it'd be better to run another build afterwards than think that the build reflects all the changes done in the meantime.

}
}

public async isCacheInvalidated() {
Copy link
Member

Choose a reason for hiding this comment

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

"invalidating" here is not the right term. It refers to the fact of cleaning the cached data. In this case, it'd be checking if the stored cache key still exists. This method however, checks whether the stored cache is up to date. I'd rename to hasUpToDateBuild or something along these lines

Copy link
Member Author

Choose a reason for hiding this comment

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

This inverts logic – this was originally named detectedFingerprintChange. I renamed the method to isCacheStale, keeping the original boolean direction.


constructor(
private readonly platform: DevicePlatform,
private readonly cancelToken: CancelToken
Copy link
Member

Choose a reason for hiding this comment

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

cancel tokens are transient and shouldn't be kept like that. Their purpose is to be able to pass them to async methods, such that they can be intercepted. Storing cancelToken like that defeats this purpose, because who is now in the control of cancelling it?

We should likely pass cancelTokens to methods that needs them directly, such that the caller is responsible for cancelling.
Alternatively we can create new cancel tokens for the calls that require them and expose some cancel method from this class which may be called by the caller.

// TODO: should be refactored to not create a new PlatformBuildCache
// instance every time
const platform = this.projectState.selectedDevice.platform;
const buildCache = new PlatformBuildCache(platform, cancelToken);
Copy link
Member

Choose a reason for hiding this comment

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

responding to your comment here: maybe we could have a static method in PlatformBuildCache.get(platform) that returns an instance. This way we can hide the fact it is a stateless object and avoid constructing it in multiple places

Copy link
Member Author

Choose a reason for hiding this comment

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

This works quite nicely but we now split getting fingerprint and storing the build (which is correct) so the value of the class is reduced. I think it's still marginally better than standalone functions but not by much.

…of cache

We need to store fingerprint that was calculated at the start of the build process
instead of calculating it after it finishes, as user can modify workspace while build is happening.

Cancel token was removed because we expect fingerprints to be calculated much quicker than it takes to build the app.
Copy link
Member

@kmagiera kmagiera left a comment

Choose a reason for hiding this comment

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

Accepting but added some comments re. the naming. You may want to address those prior to merging.

Comment on lines 133 to 137
the last line of the standard output. If custom fingerprint script is used, it
should output fingerprint as the last line of the standard output. When
fingerprint changes between invocations, RN IDE will rebuild the project. The
IDE runs fingerprint quite frequently (i.e., on every file save), so this
process should be fast and avoid over the network communication.
Copy link
Member

Choose a reason for hiding this comment

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

We should explain the concept of fingerprint here. Specifically that it is a string that allows us to tell whether new native build needs to be run

"buildScript": {
"android": "npm run build:ftp-fetch-android"
"customBuild": {
"android": { "buildScript": "npm run build:ftp-fetch-android" }
Copy link
Member

Choose a reason for hiding this comment

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

This isn't a script, so maybe we should rename to buildCommand? On the other hand in package.json you also have scripts sections where you can put commands and not just scripts.

Comment on lines 590 to 591
// TODO: should be refactored to not create a new PlatformBuildCache
// instance every time
Copy link
Member

Choose a reason for hiding this comment

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

Is this still relevant? We're not creating it here directly now

@jakub-gonet jakub-gonet merged commit c7ef126 into main Oct 4, 2024
3 checks passed
@jakub-gonet jakub-gonet deleted the jgonet/custom-fingerprints branch October 4, 2024 10:39
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