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

Generate support bundle Async #617

Merged

Conversation

nevingeorgesunny
Copy link
Contributor

@nevingeorgesunny nevingeorgesunny commented Jan 27, 2025

The problem that I am trying to solve

Currently, when users click on the "Generate Bundle" button on the /jenkins/support/ page, There is no user feedback.In case the generation process takes too long, the request may result in a 503 Timeout

Here is the fix

We will generate support bundle anync in backend which we poll for its status from UI.
The support bundle will be saved in the tmp folder, this will be deleted once the user has downloaded the files

here is a gif for the UX

GIF Recording 2025-02-10 at 10 12 43 AM

@nevingeorgesunny nevingeorgesunny requested a review from a team as a code owner January 27, 2025 09:58
@nevingeorgesunny nevingeorgesunny marked this pull request as draft January 27, 2025 09:59
@nevingeorgesunny nevingeorgesunny changed the title Generate support bundle Async [WIP]Generate support bundle Async Jan 27, 2025
@@ -309,11 +314,17 @@ private WebResponse doBundle(String action, String bundle, String user, String e
}

private ZipFile downloadBundle(String s) throws IOException, SAXException {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

All the test remain the same , as the only thing that changed was how the zip file was obtained, previoulsy it was a sync call , now its async , we just fetch the zip file after the support bundle is created

@nevingeorgesunny nevingeorgesunny changed the title [WIP]Generate support bundle Async Generate support bundle Async Feb 6, 2025
Copy link
Member

@jglick jglick left a comment

Choose a reason for hiding this comment

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

Minor comments, but seems to work as advertised.

if (!outputDir.mkdirs()) {
throw new IOException("Failed to create directory: " + outputDir.getAbsolutePath());
Path outputDir = SUPPORT_BUNDLE_CREATION_FOLDER.resolve(taskId.toString());
if (!Files.exists(outputDir)) {
Copy link
Member

Choose a reason for hiding this comment

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

My point was that you do not need to do this check: createDirectories quietly returns if the directory already exists.

try {
Files.createDirectories(outputDir);
} catch (IOException e) {
throw new IOException("Failed to create directory: " + outputDir.toAbsolutePath(), e);
Copy link
Member

Choose a reason for hiding this comment

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

Probably unnecessary to wrap and rethrow; the original IOException would include sufficient details.

Comment on lines +375 to +376
try (FileOutputStream fileOutputStream =
new FileOutputStream(new File(outputDir.toString(), SYNC_SUPPORT_BUNDLE))) {
Copy link
Member

Choose a reason for hiding this comment

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

Preferable to use Files.newOutputStream.

@@ -517,7 +520,7 @@ public ProgressiveRendering getGeneratorByTaskId(String taskId) throws Exception
}

public static class SupportBundleAsyncGenerator extends ProgressiveRendering {
private final Logger logger = Logger.getLogger(SupportBundleAsyncGenerator.class.getName());
private final Logger logger = Logger.getLogger(SupportAction.class.getName());
Copy link
Member

Choose a reason for hiding this comment

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

No I meant you could just use

private final Logger logger = Logger.getLogger(SupportAction.class.getName());

if (!outputDir.mkdirs()) {
throw new IOException("Failed to create directory: " + outputDir.getAbsolutePath());
Path outputDir = SUPPORT_BUNDLE_CREATION_FOLDER.resolve(taskId.toString());
if (!Files.exists(outputDir)) {
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Comment on lines +550 to +551
} catch (IOException e) {
throw new IOException("Failed to create directory: " + outputDir.toAbsolutePath(), e);
Copy link
Member

Choose a reason for hiding this comment

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

ditto

}
}

try (FileOutputStream fileOutputStream = new FileOutputStream(new File(outputDir, supportBundleName))) {
try (FileOutputStream fileOutputStream =
new FileOutputStream(new File(outputDir.toString(), supportBundleName))) {
Copy link
Member

Choose a reason for hiding this comment

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

ditto

try (ServletOutputStream outputStream = rsp.getOutputStream();
FileInputStream inputStream = new FileInputStream(bundleFile)) {
IOUtils.copy(inputStream, outputStream);
try (ServletOutputStream outputStream = rsp.getOutputStream()) {
Copy link
Member

Choose a reason for hiding this comment

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

stylistically, just

Suggested change
try (ServletOutputStream outputStream = rsp.getOutputStream()) {
try (OutputStream outputStream = rsp.getOutputStream()) {

or

Suggested change
try (ServletOutputStream outputStream = rsp.getOutputStream()) {
try (var outputStream = rsp.getOutputStream()) {

suffices

@@ -347,7 +345,7 @@ private ZipFile downloadSupportBundleByButtonClick() throws IOException, SAXExce
AtomicReference<HtmlPage> pageRef = new AtomicReference<>(page);

HtmlPage finalPage = page;
await().timeout(10, TimeUnit.HOURS).until(() -> {
await().timeout(10, TimeUnit.SECONDS).until(() -> {
Copy link
Member

Choose a reason for hiding this comment

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

or simply

Suggested change
await().timeout(10, TimeUnit.SECONDS).until(() -> {
await().until(() -> {

since this is the default timeout

@jglick jglick added this pull request to the merge queue Feb 20, 2025
Merged via the queue into jenkinsci:master with commit 6a6bf31 Feb 20, 2025
17 checks passed
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.

4 participants