Skip to content

Commit

Permalink
Make workflow-support compatible with Guava 21.0 and newer (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
timja committed Mar 4, 2021
1 parent 408f9c0 commit af9ed05
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .mvn/extensions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<extension>
<groupId>io.jenkins.tools.incrementals</groupId>
<artifactId>git-changelist-maven-extension</artifactId>
<version>1.0-beta-4</version>
<version>1.2</version>
</extension>
</extensions>
7 changes: 4 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
</license>
</licenses>
<scm>
<connection>scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git</connection>
<developerConnection>scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git</developerConnection>
<url>https://github.com/jenkinsci/${project.artifactId}-plugin</url>
<connection>scm:git:git://github.com/${gitHubRepo}.git</connection>
<developerConnection>scm:git:git@github.com:${gitHubRepo}.git</developerConnection>
<url>https://github.com/${gitHubRepo}</url>
<tag>${scmTag}</tag>
</scm>
<repositories>
Expand All @@ -69,6 +69,7 @@
<no-test-jar>false</no-test-jar>
<useBeta>true</useBeta>
<hpi.compatibleSinceVersion>3.0</hpi.compatibleSinceVersion>
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
</properties>
<dependencyManagement>
<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public void run() {
ChainingListenableFuture.this.outputFuture = null;
}
}
}, MoreExecutors.sameThreadExecutor());
}, Futures.newExecutorService());
} catch (UndeclaredThrowableException e) {
// Set the cause of the exception as this future's exception
setException(e.getCause());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
import com.google.common.util.concurrent.SettableFuture;

import javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
Expand Down Expand Up @@ -65,7 +68,7 @@ public abstract class Futures {
* });}</pre>
*
* <p>Note: This overload of {@code addCallback} is designed for cases in
* which the callack is fast and lightweight, as the method does not accept
* which the callback is fast and lightweight, as the method does not accept
* an {@code Executor} in which to perform the the work. For heavier
* callbacks, this overload carries some caveats: First, the thread that the
* callback runs in depends on whether the input {@code Future} is done at the
Expand All @@ -74,7 +77,7 @@ public abstract class Futures {
* callback in the thread that calls {@code addCallback} or {@code
* Future.cancel}. Second, callbacks may run in an internal thread of the
* system responsible for the input {@code Future}, such as an RPC network
* thread. Finally, during the execution of a {@code sameThreadExecutor}
* thread. Finally, during the execution of a {@code newExecutorService}
* callback, all other registered but unexecuted listeners are prevented from
* running, even if those listeners are to run in other executors.
*
Expand All @@ -87,7 +90,7 @@ public abstract class Futures {
*/
public static <V> void addCallback(ListenableFuture<V> future,
FutureCallback<? super V> callback) {
addCallback(future, callback, MoreExecutors.sameThreadExecutor());
addCallback(future, callback, newExecutorService());
}

/**
Expand Down Expand Up @@ -115,16 +118,16 @@ public static <V> void addCallback(ListenableFuture<V> future,
*
* When the callback is fast and lightweight consider {@linkplain
* Futures#addCallback(ListenableFuture, FutureCallback) the other overload}
* or explicit use of {@link MoreExecutors#sameThreadExecutor
* sameThreadExecutor}. For heavier callbacks, this choice carries some
* or explicit use of {@link #newExecutorService()}.
* For heavier callbacks, this choice carries some
* caveats: First, the thread that the callback runs in depends on whether
* the input {@code Future} is done at the time {@code addCallback} is called
* and on whether the input {@code Future} is ever cancelled. In particular,
* {@code addCallback} may execute the callback in the thread that calls
* {@code addCallback} or {@code Future.cancel}. Second, callbacks may run in
* an internal thread of the system responsible for the input {@code Future},
* such as an RPC network thread. Finally, during the execution of a {@code
* sameThreadExecutor} callback, all other registered but unexecuted
* newExecutorService} callback, all other registered but unexecuted
* listeners are prevented from running, even if those listeners are to run
* in other executors.
*
Expand Down Expand Up @@ -218,7 +221,7 @@ public static <V> ListenableFuture<V> immediateFailedFuture(
* thread that called {@code transform}. Second, transformations may run in
* an internal thread of the system responsible for the input {@code Future},
* such as an RPC network thread. Finally, during the execution of a {@code
* sameThreadExecutor} transformation, all other registered but unexecuted
* newExecutorService} transformation, all other registered but unexecuted
* listeners are prevented from running, even if those listeners are to run
* in other executors.
*
Expand All @@ -240,7 +243,7 @@ public static <V> ListenableFuture<V> immediateFailedFuture(
*/
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> future,
final Function<? super I, ? extends O> function) {
return Futures.<I, O>transform(future, function, MoreExecutors.sameThreadExecutor());
return Futures.<I, O>transform(future, function, newExecutorService());
}

/**
Expand Down Expand Up @@ -272,15 +275,15 @@ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> future,
* <p>Note: For cases in which the transformation is fast and lightweight,
* consider {@linkplain Futures#transform(ListenableFuture, Function) the
* other overload} or explicit use of {@link
* MoreExecutors#sameThreadExecutor}. For heavier transformations, this
* #newExecutorService}. For heavier transformations, this
* choice carries some caveats: First, the thread that the transformation
* runs in depends on whether the input {@code Future} is done at the time
* {@code transform} is called. In particular, if called late, {@code
* transform} will perform the transformation in the thread that called
* {@code transform}. Second, transformations may run in an internal thread
* of the system responsible for the input {@code Future}, such as an RPC
* network thread. Finally, during the execution of a {@code
* sameThreadExecutor} transformation, all other registered but unexecuted
* newExecutorService} transformation, all other registered but unexecuted
* listeners are prevented from running, even if those listeners are to run
* in other executors.
*
Expand All @@ -304,6 +307,29 @@ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> future,
return chain(future, wrapperFunction, executor);
}

/**
* Returns an {@link ExecutorService} to be used as a parameter in other methods.
* It calls {@code MoreExecutors#newDirectExecutorService} or falls back to {@code MoreExecutors#sameThreadExecutor}
* for compatibility with older (&lt; 18.0) versions of guava.
*
* @since TODO
*/
public static ExecutorService newExecutorService() {
try {
try {
// Guava older than 18
Method method = MoreExecutors.class.getMethod("sameThreadExecutor");
return (ExecutorService) method.invoke(null);
} catch (NoSuchMethodException e) {
// TODO invert this to prefer the newer guava method once guava is upgrade in Jenkins core
Method method = MoreExecutors.class.getMethod("newDirectExecutorService");
return (ExecutorService) method.invoke(null);
}
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e ) {
throw new RuntimeException(e);
}
}

/**
* Creates a new {@code ListenableFuture} whose value is a list containing the
* values of all its input futures, if all succeed. If any input fails, the
Expand All @@ -324,7 +350,7 @@ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> future,
public static <V> ListenableFuture<List<V>> allAsList(
ListenableFuture<? extends V>... futures) {
return new ListFuture<V>(ImmutableList.copyOf(futures), true,
MoreExecutors.sameThreadExecutor());
newExecutorService());
}

/**
Expand All @@ -347,7 +373,7 @@ public static <V> ListenableFuture<List<V>> allAsList(
public static <V> ListenableFuture<List<V>> allAsList(
Iterable<? extends ListenableFuture<? extends V>> futures) {
return new ListFuture<V>(ImmutableList.copyOf(futures), true,
MoreExecutors.sameThreadExecutor());
newExecutorService());
}

/**
Expand Down Expand Up @@ -379,14 +405,14 @@ public static <V> ListenableFuture<List<V>> allAsList(
* <p>Note: For cases in which the work of creating the derived future is
* fast and lightweight, consider {@linkplain Futures#chain(ListenableFuture,
* Function) the other overload} or explicit use of {@code
* sameThreadExecutor}. For heavier derivations, this choice carries some
* newExecutorService}. For heavier derivations, this choice carries some
* caveats: First, the thread that the derivation runs in depends on whether
* the input {@code Future} is done at the time {@code chain} is called. In
* particular, if called late, {@code chain} will run the derivation in the
* thread that called {@code chain}. Second, derivations may run in an
* internal thread of the system responsible for the input {@code Future},
* such as an RPC network thread. Finally, during the execution of a {@code
* sameThreadExecutor} {@code chain} function, all other registered but
* newExecutorService} {@code chain} function, all other registered but
* unexecuted listeners are prevented from running, even if those listeners
* are to run in other executors.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void run() {
// Let go of the memory held by other futures
ListFuture.this.futures = null;
}
}, MoreExecutors.sameThreadExecutor());
}, Futures.newExecutorService());

// Now begin the "real" initialization.

Expand Down

0 comments on commit af9ed05

Please sign in to comment.