@@ -56,6 +56,7 @@ public class RemoteBuildConfiguration extends Builder {
5656
5757 private final boolean shouldNotFailBuild ;
5858 private final int pollInterval ;
59+ private final int connectionRetryLimit = 5 ;
5960 private final boolean preventRemoteBuildQueue ;
6061 private final boolean blockBuildUntilComplete ;
6162
@@ -654,10 +655,38 @@ public String getBuildStatus(String buildUrlString, AbstractBuild build, BuildLi
654655 return buildStatus ;
655656 }
656657
658+ /**
659+ * Orchestrates all calls to the remote server.
660+ * Also takes care of any credentials or failed-connection retries.
661+ *
662+ * @param urlString the URL that needs to be called
663+ * @param requestType the type of request (GET, POST, etc)
664+ * @param build the build that is being triggered
665+ * @param listener build listener
666+ * @return a valid JSON object, or null
667+ * @throws IOException
668+ */
657669 public JSONObject sendHTTPCall (String urlString , String requestType , AbstractBuild build , BuildListener listener )
658670 throws IOException {
659- RemoteJenkinsServer remoteServer = this .findRemoteHost (this .getRemoteJenkinsName ());
671+
672+ return sendHTTPCall ( urlString , requestType , build , listener , 1 );
673+ }
660674
675+ /**
676+ * Same as sendHTTPCall, but keeps track of the number of failed connection attempts (aka: the number of times this
677+ * method has been called).
678+ * In the case of a failed connection, the method calls it self recursively and increments numberOfAttempts
679+ *
680+ * @see sendHTTPCall
681+ * @param numberOfAttempts number of time that the connection has been attempted
682+ * @return
683+ * @throws IOException
684+ */
685+ public JSONObject sendHTTPCall (String urlString , String requestType , AbstractBuild build , BuildListener listener , int numberOfAttempts )
686+ throws IOException {
687+ RemoteJenkinsServer remoteServer = this .findRemoteHost (this .getRemoteJenkinsName ());
688+ int retryLimit = this .getConnectionRetryLimit ();
689+
661690 if (remoteServer == null ) {
662691 this .failBuild (new Exception ("No remote host is defined for this job." ), listener );
663692 return null ;
@@ -693,6 +722,7 @@ public JSONObject sendHTTPCall(String urlString, String requestType, AbstractBui
693722 byte [] encodedAuthKey = Base64 .encodeBase64 (usernameTokenConcat .getBytes ());
694723 connection .setRequestProperty ("Authorization" , "Basic " + new String (encodedAuthKey ));
695724 }
725+
696726 try {
697727 connection .setDoInput (true );
698728 connection .setRequestProperty ("Accept" , "application/json" );
@@ -729,13 +759,29 @@ public JSONObject sendHTTPCall(String urlString, String requestType, AbstractBui
729759 }
730760
731761 } catch (IOException e ) {
732- //If we get a 404 when trying to check a builds status (aka: called from "getBuildStatus") it just means that the build hasn't been queued up because there aren't any more executors available to call the remote server.
733- //So we basically pretend like the error didn't happen.
734- String callingMethod = Thread .currentThread ().getStackTrace ()[2 ].getMethodName ();
735- if (connection .getResponseCode () == 404 && callingMethod == "getBuildStatus" ){
736- return null ;
762+
763+ //If we have connectionRetryLimit set to > 0 then retry that many times.
764+ if ( numberOfAttempts <= retryLimit ) {
765+ listener .getLogger ().println ("Connection to remote server failed, waiting for to retry - " + this .pollInterval + " seconds until next attempt." );
766+
767+ // Sleep for 'pollInterval' seconds.
768+ // Sleep takes miliseconds so need to convert this.pollInterval to milisecopnds (x 1000)
769+ try {
770+ // Could do with a better way of sleeping...
771+ Thread .sleep (this .pollInterval * 1000 );
772+ } catch (InterruptedException ex ) {
773+ this .failBuild (ex , listener );
774+ }
775+
776+
777+ listener .getLogger ().println ("Retry attempt #" + numberOfAttempts + " out of " + retryLimit );
778+ numberOfAttempts ++;
779+ responseObject = sendHTTPCall (urlString , requestType , build , listener , numberOfAttempts );
780+ }else if (numberOfAttempts > retryLimit ){
781+ //reached the maximum number of retries, time to fail
782+ this .failBuild (new Exception ("Max number of connection retries have been exeeded." ), listener );
737783 }else {
738- //something failed with the connection, so throw an exception to mark the build as failed.
784+ //something failed with the connection and we retried the max amount of times... so throw an exception to mark the build as failed.
739785 this .failBuild (e , listener );
740786 }
741787
@@ -797,6 +843,13 @@ public int getPollInterval() {
797843 return this .pollInterval ;
798844 }
799845
846+ /**
847+ * @return the connectionRetryLimit
848+ */
849+ public int getConnectionRetryLimit () {
850+ return connectionRetryLimit ;
851+ }
852+
800853 public String getToken () {
801854 return this .token ;
802855 }
0 commit comments