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 a flag to force Bazel to download certain artifacts when using --remote_download_minimal #15638

Closed
wants to merge 11 commits into from

Conversation

lfpino
Copy link
Contributor

@lfpino lfpino commented Jun 8, 2022

When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded.

Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases.

Signed-off-by: Luis Fernando Pino Duque luis@engflow.com

When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_force_downloads_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded.

Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_force_downloads_regex=".*jar$", also included an integration test with several cases.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
@lfpino lfpino requested a review from a team as a code owner June 8, 2022 07:45
@sgowroji sgowroji added team-Remote-Exec Issues and PRs for the Execution (Remote) team awaiting-review PR is awaiting review from an assigned reviewer labels Jun 8, 2022
@meisterT meisterT requested a review from coeuvre June 8, 2022 11:14
Copy link
Member

@coeuvre coeuvre left a comment

Choose a reason for hiding this comment

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

Thanks for your PR!

I think this is working towards the point 3 I mentioned in #12665.

The new flag works on output-wise, i.e. filter each output of a spawn. I didn't look into IDE usages yet, but since we are on the topic, I want to learn more about the requirements. Have you consider other options, like, filter at spawn level (that's how --remote_download_toplevel works) or use an aspect with output group?

String regex = remoteOptions.experimentalForceDownloadsRegex;
// TODO(bazel-team): Consider adding a warning or more validation if the experimentalForceDownloadsRegex is used
// without RemoteOutputsMode.MINIMAL
this.shouldForceDownloads = !regex.isEmpty() && remoteOptions.remoteOutputsMode == RemoteOutputsMode.MINIMAL;
Copy link
Member

Choose a reason for hiding this comment

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

I think we can also use this flag for --remote_download_toplevel.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -1021,24 +1036,9 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
/* exitCode = */ result.getExitCode(),
hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload));

ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder();
Copy link
Member

Choose a reason for hiding this comment

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

why not reuse downloadsBuilder?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying to steer away from the current downloads codepath since I'm not an expert in this part of the code. Wanted to make sure this change is isolated to avoid any potential problems but if you want I can try to unify them using downloadsBuilder.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, please unify them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to unify them in a few ways but I always ended up finding issues and making the code more unreadable. Do you have any suggestions? Since this is experimental I'm inclined to leave it as it is right now and if we can confirm this is a good direction then we can refactor the code to make it more readable (I still find it very confusing the code path that depends on the downloadOutputs boolean)

Copy link
Member

Choose a reason for hiding this comment

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

downloadOutputs basically means whether we are using BwoB. The two mods were merged into one function because eventually we want to only have BwoB (but the behaviour is still the same by default that Bazel download ALL outputs but in the background, so that the boolean is removed and only one code path left).

As you said this is an experimental feature, I am fine to move forward without unifying them at this PR if that introduce other issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I understood that, but some tests are failing when I'm unifying them and it's not entirely clear to me why that's the case. Seems like a bug somewhere where downloadOutputs is not entirely consistent with using BwoB. I'll go ahead as is.

@@ -574,6 +574,16 @@ public RemoteOutputsStrategyConverter() {
help = "Maximum number of open files allowed during BEP artifact upload.")
public int maximumOpenFiles;

@Option(
name = "experimental_force_downloads_regex",
Copy link
Member

Choose a reason for hiding this comment

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

How about name this flag --experimental_remote_download_regex to match other flags?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor Author

@lfpino lfpino left a comment

Choose a reason for hiding this comment

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

Thanks for your PR!

I think this is working towards the point 3 I mentioned in #12665.

The new flag works on output-wise, i.e. filter each output of a spawn. I didn't look into IDE usages yet, but since we are on the topic, I want to learn more about the requirements. Have you consider other options, like, filter at spawn level (that's how --remote_download_toplevel works) or use an aspect with output group?

You're welcome! :-) and thanks for the prompt reply!

Yeah, I hadn't seen #12665 but this does contribute towards that goal.

The requirement is quite simple: Being able to use build without the bytes without breaking IDE integration. By using this flag, one can use IntelliJ with --remote_download_minimal and ask Bazel to also download the jar files.

I haven't explored any other options since, as usual, there's too many ways of doing this and I tried something that made sense when I looked at the code. Of course if you think that this is not ok architecturally I'm happy to look at other options but I'll probably need a couple of code pointers. If you think this approach is ok, I think we should merge and improve this with some follow-up PRs. WDYT?

@@ -574,6 +574,16 @@ public RemoteOutputsStrategyConverter() {
help = "Maximum number of open files allowed during BEP artifact upload.")
public int maximumOpenFiles;

@Option(
name = "experimental_force_downloads_regex",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -1021,24 +1036,9 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
/* exitCode = */ result.getExitCode(),
hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload));

ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying to steer away from the current downloads codepath since I'm not an expert in this part of the code. Wanted to make sure this change is isolated to avoid any potential problems but if you want I can try to unify them using downloadsBuilder.

String regex = remoteOptions.experimentalForceDownloadsRegex;
// TODO(bazel-team): Consider adding a warning or more validation if the experimentalForceDownloadsRegex is used
// without RemoteOutputsMode.MINIMAL
this.shouldForceDownloads = !regex.isEmpty() && remoteOptions.remoteOutputsMode == RemoteOutputsMode.MINIMAL;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@lfpino lfpino requested a review from coeuvre June 9, 2022 21:14
Copy link
Member

@coeuvre coeuvre left a comment

Choose a reason for hiding this comment

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

It seems that the new changes haven't been pushed.

@@ -1021,24 +1036,9 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
/* exitCode = */ result.getExitCode(),
hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload));

ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder();
Copy link
Member

Choose a reason for hiding this comment

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

Yes, please unify them.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Copy link
Contributor Author

@lfpino lfpino left a comment

Choose a reason for hiding this comment

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

Addressed comments PTAL

@@ -1021,24 +1036,9 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
/* exitCode = */ result.getExitCode(),
hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload));

ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to unify them in a few ways but I always ended up finding issues and making the code more unreadable. Do you have any suggestions? Since this is experimental I'm inclined to leave it as it is right now and if we can confirm this is a good direction then we can refactor the code to make it more readable (I still find it very confusing the code path that depends on the downloadOutputs boolean)

Copy link
Member

@coeuvre coeuvre left a comment

Choose a reason for hiding this comment

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

Sorry for the delay. I think this PR is good now. Just address remaining comments and we are ready to merge.

@@ -1021,24 +1036,9 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
/* exitCode = */ result.getExitCode(),
hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload));

ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder();
Copy link
Member

Choose a reason for hiding this comment

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

downloadOutputs basically means whether we are using BwoB. The two mods were merged into one function because eventually we want to only have BwoB (but the behaviour is still the same by default that Bazel download ALL outputs but in the background, so that the boolean is removed and only one code path left).

As you said this is an experimental feature, I am fine to move forward without unifying them at this PR if that introduce other issues.

@@ -1068,6 +1075,15 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
throw e;
}

ImmutableList<ListenableFuture<FileMetadata>> forcedDownloads = forcedDownloadsBuilder.build();
try (SilentCloseable c = Profiler.instance().profile("Remote.forcedDownload")) {
Copy link
Member

Choose a reason for hiding this comment

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

Consider extracting this into a function to share the code above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@coeuvre unfortunately the generic Exception catch here is making this code very brittle. Exception handling needs to be improved before we can move this to a generic function, I've added a TODO to avoid mixing things up. That was causing the test failures from my previous attempts.

@@ -1079,6 +1095,10 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
tmpOutErr.clearOut();
tmpOutErr.clearErr();

if (!forcedDownloads.isEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

Consider moving this into else block below to make it clear that this is only available in BwoB.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -215,6 +220,19 @@ public RemoteExecutionService(
this.captureCorruptedOutputsDir = captureCorruptedOutputsDir;

this.scheduler = Schedulers.from(executor, /*interruptibleWorker=*/ true);

String regex = remoteOptions.remoteDownloadRegex;
// TODO(bazel-team): Consider adding a warning or more validation if the experimentalForceDownloadsRegex is used
Copy link
Member

Choose a reason for hiding this comment

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

Comment needs update.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

…wnloads

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
@lfpino
Copy link
Contributor Author

lfpino commented Jul 5, 2022

@coeuvre this PR should be ready now, PTAL!

@lfpino
Copy link
Contributor Author

lfpino commented Jul 6, 2022

There are some failures, let me check that first.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
@lfpino lfpino requested a review from coeuvre July 8, 2022 22:53
@lfpino
Copy link
Contributor Author

lfpino commented Jul 8, 2022

@coeuvre you should be able to take a look now

Copy link
Member

@coeuvre coeuvre left a comment

Choose a reason for hiding this comment

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

LGTM! I will import after following comment is addressed.

@@ -1133,6 +1159,47 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
return null;
}

// private void waitForDownloads(ImmutableList<ListenableFuture<FileMetadata>> downloads,
Copy link
Member

Choose a reason for hiding this comment

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

Please remove commented code.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
@lfpino lfpino requested a review from coeuvre July 12, 2022 15:07
@lfpino
Copy link
Contributor Author

lfpino commented Jul 12, 2022

Done. Feel free to merge @coeuvre

Thanks a lot!

@brentleyjones
Copy link
Contributor

@bazel-io flag

@bazel-io bazel-io added the potential release blocker Flagged by community members using "@bazel-io flag". Should be added to a release blocker milestone label Jul 13, 2022
@sgowroji
Copy link
Member

@bazel-io fork 5.3.0

@bazel-io bazel-io removed the potential release blocker Flagged by community members using "@bazel-io flag". Should be added to a release blocker milestone label Jul 13, 2022
sgowroji pushed a commit to sgowroji/bazel that referenced this pull request Jul 13, 2022
…remote_download_minimal

When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded.

Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>

Closes bazelbuild#15638.

PiperOrigin-RevId: 460672954
Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd
sgowroji added a commit that referenced this pull request Jul 14, 2022
…remote_download_minimal (#15870)

When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded.

Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>

Closes #15638.

PiperOrigin-RevId: 460672954
Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd

Co-authored-by: Luis Fernando Pino Duque <luis@engflow.com>
aranguyen pushed a commit to aranguyen/bazel that referenced this pull request Jul 20, 2022
…remote_download_minimal

When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded.

Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>

Closes bazelbuild#15638.

PiperOrigin-RevId: 460672954
Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd
aranguyen pushed a commit to aranguyen/bazel that referenced this pull request Jul 20, 2022
…remote_download_minimal

When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded.

Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases.

Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>

Closes bazelbuild#15638.

PiperOrigin-RevId: 460672954
Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd
@ShreeM01 ShreeM01 removed the awaiting-review PR is awaiting review from an assigned reviewer label Sep 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team-Remote-Exec Issues and PRs for the Execution (Remote) team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants