Max Threads in ScriptRunner Cloud

Andrew Lipscomb March 12, 2017

So, as the Adaptavist docos say

REST API calls are made in a blocking style (although async methods are provided too)

Async methods look to be useful when you need to fire a bunch of updates to JIRA and don't care about the results from each. Question is; how many threads does each container get access to and what happens when that count is exceeded. 

As an example; if I try something like

import com.mashape.unirest.http.async.Callback
import com.mashape.unirest.http.exceptions.UnirestException

def issueCount = 100
for (int i=1; i<issueCount; i++) {
	put("/rest/api/2/issue/PROJ-${i}")
		.header('Content-Type', 'application/json')
        .body([
        	fields:[
                summary: "This is issue ${i}"
        	]
		]).asStringAsync(new Callback<String>() {

            public void failed(UnirestException e) {
                logger.info("Exception failure ${e.toString()}")
            }
        
            public void completed(HttpResponse<String> response) {
                 logger.info("Responses are pointless here!")
            }
        
            public void cancelled() {
                logger.info("The request has been cancelled");
            }

    	})
        
}

How will this break? Also I have not tested this code beyond a simple example; no guarantees this will even run. 

Edit: more code typos

1 answer

1 accepted

3 votes
Answer accepted
Jon Mort [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 13, 2017

Hi Andrew,

Your code should work fine, there are a couple of things to be aware of.

  1. There is no thread limit, only execution time limit of 30s
  2. The number of connections to your JIRA instance is limited to 8 (this is not published and may change)
  3. You need to ensure that all the requests finish before the script completes, if you don't in flight requests may not complete, and queued requests will not start.
  4. You have a single core to run on, so don't do CPU intensive work on threads and expect things to be faster

Once you start introducing threads you're into the very advanced area of scripts. We are looking into ways to support returning an object for bulk requests, so you don't have to make them all in your script.

Regards,

Jon

 

Andrew Lipscomb March 13, 2017

Thanks Jon; I ended up with some time to experiment (for science!) yesterday and found that I could get around 50 async requests to fire before timeout using a sleep(XXXX) command to pause the main thread. 

I guess with multi threading with the number of variables in terms of connection speed, dropped server connections and general unreliability you need to scope your solutions right.

For my designs in the 30sec constraint; if sync processing is required, I aim for max 20 API calls. If async is needed, I'd bump to max 50 API calls. If more is needed, use bulk manipulation or custom tools in Jira. 

Jon Mort [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 13, 2017

Rather than use a sleep you could use a CountDownLatch so the script doesn't run for longer than needed. You can also log so you can see if it actually finished.

import java.util.concurrent.CountDownLatch
 
def issueCount = 10
 
CountDownLatch latch = new CountDownLatch(issueCount)
issueCount.times { i ->
    put("/rest/api/2/issue/PROJ-${i}")
        .header('Content-Type', 'application/json')
        .body([
            fields:[
                summary: "This is issue ${i}"
            ]
        ]).asStringAsync(new Callback<String>() {
 
            public void failed(UnirestException e) {
                latch.countDown() // each part of the callback must call countDown()
                logger.info("Exception failure ${e.toString()}")
            }
         
            public void completed(HttpResponse<String> response) {
                 latch.countDown()
                 logger.info("Responses are pointless here!")
            }
         
            public void cancelled() {
                latch.countDown()
                logger.info("The request has been cancelled")
            }
 
        })
}
 
latch.await() // this will block until the latch is empty
logger.info("All requests completed")

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events