Schedule a build in parallel from code (Jenkins API)

574 views
Skip to first unread message

dev123

unread,
Mar 9, 2014, 5:27:11 PM3/9/14
to jenkins...@googlegroups.com
In a jenkins plugin I am writing I need to run 5 jobs in parallel. Currently I do (sequentially):

    for (int i = 0; i < 4; i++) {
      try {
        build = project.scheduleBuild2(0, new Cause.UserCause(), myActions[i]).get();
      } catch (Exception e) {
        throw new AbortException(e.getMessage());
      }      
    }

How do I trigger these jobs to run in parallel - each one on a separate executor?

Daniel Beck

unread,
Mar 9, 2014, 5:32:31 PM3/9/14
to jenkins...@googlegroups.com
Don't immediately call .get(), instead assign the Future returned from scheduleBuild2 to a variable. Only .get() once you're willing to wait for the build to complete.
> --
> You received this message because you are subscribed to the Google Groups "Jenkins Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jenkinsci-use...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

dev123

unread,
Mar 9, 2014, 5:52:52 PM3/9/14
to jenkins...@googlegroups.com, m...@beckweb.net
Not sure I understand I now do:


    for (int i = 0; i < 4; i++) {
      try {
        QueueTaskFuture<?> scheduleBuild2 = project.scheduleBuild2(0, new Cause.UserCause(), myActions[i]);
        queue.add(scheduleBuild2);
      } catch (Exception e) {
        throw new AbortException(e.getMessage());
      }
    }

    for (QueueTaskFuture<?> q : queue) {
      q.get();
    }


I need to get the results from each job and print some info but it still does not execute in parallel. 

I also found this:

Queue$Item item = Jenkins.getInstance().getQueue().schedule2(null, 0,  myActions[i])

But I still does not give me what I want.

Daniel Beck

unread,
Mar 9, 2014, 6:21:56 PM3/9/14
to jenkins...@googlegroups.com, dev123
If you have the executors, the builds should run in parallel. Given the following script in the Script Console (and jobs named wait1..wait4 with different durations):
---
def futures = []
[1, 2, 3, 4].each {
futures.add Jenkins.instance.getItemByFullName("wait${it}").scheduleBuild2(0)
}
futures.each {
println it.get().time
println it.get().duration // millis
}
---
The following output is printed:
---
Sun Mar 09 23:18:12 CET 2014
20025
Sun Mar 09 23:18:12 CET 2014
10031
Sun Mar 09 23:18:22 CET 2014
25027
Sun Mar 09 23:18:32 CET 2014
15026
---
I have two executors, and you can see the first two started at the same time, the third when the second was finished, the fourth when the first was finished.

Note that get() is a blocking call, and it waits for the related build to complete. That build isn't necessarily the one finishing first -- there's a chance you'll wait for the longest-running build first in the second loop, only to then get the subsequent results immediately, because they've finished long ago. Perhaps you can use Future.get(long,TimeUnit) instead if you want to present the results in the order they are available.

Another possible issue: Did you make sure that your queue does not simply collapse multiple executions of the same job into one, because they're considered equal?

Daniel Beck

unread,
Mar 9, 2014, 6:23:37 PM3/9/14
to jenkins...@googlegroups.com, dev123
Since you seem to be triggering multiple builds of the same project, did you enable the project for parallel execution of multiple builds?

dev123

unread,
Mar 9, 2014, 6:47:20 PM3/9/14
to jenkins...@googlegroups.com, dev123, m...@beckweb.net
Yes I did a check in allow concurrent execution.

Now when I run mvn clean hpi:run it starts the jobs in parallel on the available executors, but its spawns jobs infinitely and the text: XXXX Done in: " + object.getTime() is never printed. And I have not even pressed the build button.

Why do I get something that seems like an infinite loop?

Here is my code based on your script:

    List<Future<?>> futures = new ArrayList<Future<?>>();
    for (int i = 0; i < 5; i++) {
      System.out.println("Running: " + i + " out off: " + executors);
      try {
        QueueTaskFuture<?> scheduleBuild2 = build.getProject().scheduleBuild2(0, new Cause.UserCause(), parametersAction);
        futures.add((Future) scheduleBuild2);
      } catch (Exception e) {
        throw new AbortException(e.getMessage());
      }
    }
    for (Future<?> future : futures) {
      AbstractBuild<?, ?> object = (AbstractBuild<?, ?>) future.get();
      System.out.println("XXXX Done in: " + object.getTime());

dev123

unread,
Mar 9, 2014, 6:56:28 PM3/9/14
to jenkins...@googlegroups.com, dev123, m...@beckweb.net
A my bad I of course had to call the correct job, it now works thanks :-)

Thandesha VK

unread,
Jul 15, 2015, 3:25:01 AM7/15/15
to jenkins...@googlegroups.com, delb...@gmail.com
It can't find the class Future. Could you please help

unable to resolve class Future

Thandesha VK

unread,
Jul 15, 2015, 4:00:26 AM7/15/15
to jenkins...@googlegroups.com
Never mind. Got it in 
import java.lang.Object

Now I am stuck with

unable to resolve class QueueTaskFuture 

unable to resolve class QueueTaskFuture 


--
You received this message because you are subscribed to a topic in the Google Groups "Jenkins Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jenkinsci-users/emSwxk2F6Oo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jenkinsci-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-users/53d688f9-1070-4f57-b07a-e47011315489%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
- T
Reply all
Reply to author
Forward
0 new messages