From 83b95dd41b7bbdf1750f60d7424e6bfd1a578c1a Mon Sep 17 00:00:00 2001 From: Julien Greffe Date: Mon, 30 Jun 2025 18:12:53 +0200 Subject: [PATCH 1/2] Add `SynchronousNonBlockingStepExecutorServiceAugmentor` --- .../SynchronousNonBlockingStepExecution.java | 23 +++++++++- ...ckingStepExecutorServiceAugmentorTest.java | 42 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java diff --git a/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java b/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java index acfc0d3..bd4e05f 100644 --- a/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java +++ b/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java @@ -1,5 +1,7 @@ package org.jenkinsci.plugins.workflow.steps; +import hudson.ExtensionList; +import hudson.ExtensionPoint; import hudson.security.ACL; import hudson.security.ACLContext; import hudson.util.ClassLoaderSanityThreadFactory; @@ -12,6 +14,8 @@ import java.util.concurrent.Future; import edu.umd.cs.findbugs.annotations.NonNull; import jenkins.model.Jenkins; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.Beta; import org.springframework.security.core.Authentication; /** @@ -92,9 +96,26 @@ public void onResume() { static synchronized ExecutorService getExecutorService() { if (executorService == null) { - executorService = Executors.newCachedThreadPool(new NamingThreadFactory(new ClassLoaderSanityThreadFactory(new DaemonThreadFactory()), "org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution")); + ExecutorService result = Executors.newCachedThreadPool(new NamingThreadFactory(new ClassLoaderSanityThreadFactory(new DaemonThreadFactory()), "org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution")); + + for (SynchronousNonBlockingStepExecutorServiceAugmentor augmentor : ExtensionList.lookup(SynchronousNonBlockingStepExecutorServiceAugmentor.class)) { + result = augmentor.augment(result); + } + executorService = result; } return executorService; } + /** + * Extension point for augmenting the executorService of {@link SynchronousNonBlockingStepExecution}. + */ + @Restricted(Beta.class) + public interface SynchronousNonBlockingStepExecutorServiceAugmentor extends ExtensionPoint { + /** + * Augment the executor service used by {@link SynchronousNonBlockingStepExecution}. + * @param executorService the executor service to augment + */ + ExecutorService augment(ExecutorService executorService); + } + } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java new file mode 100644 index 0000000..affc648 --- /dev/null +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java @@ -0,0 +1,42 @@ +package org.jenkinsci.plugins.workflow.steps; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; + +import java.util.concurrent.ExecutorService; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.LoggerRule; +import org.jvnet.hudson.test.TestExtension; + +public class SynchronousNonBlockingStepExecutorServiceAugmentorTest { + + @Rule + public JenkinsRule r = new JenkinsRule(); + + @Rule + public LoggerRule loggerRule = + new LoggerRule().record(AugmentorTestExtension.class, Level.FINE).capture(10); + + @Test + public void smokes() throws Exception { + SynchronousNonBlockingStepExecution.getExecutorService(); + assertThat(loggerRule.getMessages(), hasItem("Augmenting")); + } + + @TestExtension + public static class AugmentorTestExtension + implements SynchronousNonBlockingStepExecution.SynchronousNonBlockingStepExecutorServiceAugmentor { + + private static final Logger LOGGER = Logger.getLogger(AugmentorTestExtension.class.getName()); + + @Override + public ExecutorService augment(ExecutorService executorService) { + LOGGER.fine(() -> "Augmenting"); + return executorService; + } + } +} From d44f505b0c5bc4c6e9ca5087bfc265b09cb8da3f Mon Sep 17 00:00:00 2001 From: Julien Greffe Date: Wed, 2 Jul 2025 04:14:59 +0200 Subject: [PATCH 2/2] Rename inner interface --- .../steps/SynchronousNonBlockingStepExecution.java | 7 +++---- ...hronousNonBlockingStepExecutorServiceAugmentorTest.java | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java b/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java index bd4e05f..b5cfc85 100644 --- a/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java +++ b/src/main/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecution.java @@ -8,7 +8,6 @@ import hudson.util.DaemonThreadFactory; import hudson.util.NamingThreadFactory; -import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -98,7 +97,7 @@ static synchronized ExecutorService getExecutorService() { if (executorService == null) { ExecutorService result = Executors.newCachedThreadPool(new NamingThreadFactory(new ClassLoaderSanityThreadFactory(new DaemonThreadFactory()), "org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution")); - for (SynchronousNonBlockingStepExecutorServiceAugmentor augmentor : ExtensionList.lookup(SynchronousNonBlockingStepExecutorServiceAugmentor.class)) { + for (ExecutorServiceAugmentor augmentor : ExtensionList.lookup(ExecutorServiceAugmentor.class)) { result = augmentor.augment(result); } executorService = result; @@ -110,9 +109,9 @@ static synchronized ExecutorService getExecutorService() { * Extension point for augmenting the executorService of {@link SynchronousNonBlockingStepExecution}. */ @Restricted(Beta.class) - public interface SynchronousNonBlockingStepExecutorServiceAugmentor extends ExtensionPoint { + public interface ExecutorServiceAugmentor extends ExtensionPoint { /** - * Augment the executor service used by {@link SynchronousNonBlockingStepExecution}. + * Augment the executor service used by {@link SynchronousNonBlockingStepExecution} and {@link GeneralNonBlockingStepExecution}. * @param executorService the executor service to augment */ ExecutorService augment(ExecutorService executorService); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java index affc648..442dc81 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutorServiceAugmentorTest.java @@ -29,7 +29,7 @@ public void smokes() throws Exception { @TestExtension public static class AugmentorTestExtension - implements SynchronousNonBlockingStepExecution.SynchronousNonBlockingStepExecutorServiceAugmentor { + implements SynchronousNonBlockingStepExecution.ExecutorServiceAugmentor { private static final Logger LOGGER = Logger.getLogger(AugmentorTestExtension.class.getName());