I installed the grails executor plugin so I can run some background task that takes a while to execute. The task requires that I call LinkedIn APIs using OauthService. The problem is that I can't seem to be able to call OauthService.accessResource in the asynchronous block, while the exact same code executes fine otherwise. Here's the code, simplified to illustrate the problem :
import org.grails.plugins.oauth.OauthService
class DemoController {
OauthService oauthService
def demo() {
runAsync {
println "ASYNC BEGIN"
def baseURL = "http://api.linkedin.com/v1/people-search?keywords=blah"
def async_response = oauthService.accessResource( baseURL, 'linkedin', [key:session.oauthToken.key, secret:session.oauthToken.secret], 'GET')
println "ASYNC END"
}
println "SYNC BEGIN"
def baseURL = "http://api.linkedin.com/v1/people-search?keywords=blah"
def sync_response = oauthService.accessResource( baseURL, 'linkedin', [key:session.oauthToken.key, secret:session.oauthToken.secret], 'GET')
println "SYNC END"
}
}
Here's the output :
SYNC BEGIN
2012-01-12 14:55:07,163 ["http-bio-8080"-exec-10] DEBUG oauth.OauthService - Attempting to access protected resource
2012-01-12 14:55:07,163 ["http-bio-8080"-exec-10] DEBUG oauth.OauthService - Executing GET to http://api.linkedin.com/v1/people-search?keywords=blah
ASYNC BEGIN
2012-01-12 14:55:07,780 ["http-bio-8080"-exec-10] DEBUG oauth.OauthService - Reading response body
2012-01-12 14:55:07,781 ["http-bio-8080"-exec-10] DEBUG oauth.OauthService - Response body read successfully
SYNC END
The asynchronous process just seems to stall on oauthService.accessResource and nothing gets executed after that. I get no other output ...
Any ideas ?
Thanks for your help.
(BTW I'm using grails 2.0, groovy 1.8.5)
Related
I have Java/Groovy/Spock tests and Allure 2 report. I use allure.Step() annotation to describe all steps that I want to see in Allure report. For example:
def "some test"() {
when: "do some request"
Request.getRequest()
}
class Request {
#Step("GET https://some.request")
static Response getRequest() {
return given().log().all()
.filter(new AllureRestAssured())
.when()
.get(conf.url())
}
}
In that case I see two basically same blocks in report:
one beautiful block step with finely formatted request and response due to AllureRestAssured()
one ugly block with the same unformatted request and response info due to .log().all() console output.
Is there a way to remove all console output from Allure report and leave only methods that have #Step annotation?
I have a page that needs parameters received by a request from a third-party service. Unfortunately, the request takes a long time and the server crashes with a 504 error.
def show
start_time = Time.now
#project = Project.find(params[:id])
file = File.new(project.rvt_schema, 'rb')
rvt_params = ForgeHandler.instance.get_urn_token_params(file, "#{#project.id.to_s}.rvt")
#urn = rvt_params[:urn]
#token = rvt_params[:token]
end_time = Time.now
end
The most time inside the method is taken by request:
# Translate previously uploaded file to SVF format
def translate_to_svf(object_id,access_token)
base_64_urn = Base64.strict_encode64(object_id)
response = RestClient.post("#{API_URL}/modelderivative/v2/designdata/job",
{
input: {
urn: base_64_urn
},
output: {
formats: [
{
type: "svf",
views: [
"3d"
]
}
]
}
}.to_json,
{ Authorization: "Bearer #{access_token}", content_type:'application/json' })
return response
end
Which status is checked in cycle by another method:
def verify_job_complete(base_64_urn,access_token)
is_complete = false
while(!is_complete)
response = RestClient.get("#{API_URL}/modelderivative/v2/designdata/#{base_64_urn}/manifest",
{ Authorization: "Bearer #{access_token}"} )
json = JSON.parse(response.body)
if(json["progress"]=="complete")
is_complete = true
puts("***** Finished translating your file to SVF - status: #{json['status']}, progress: #{json['progress']} ")
else
puts("***** Haven't finished translating your file to SVF - status: #{json['status']}, progress: #{json['progress']} ")
sleep 5
end
end
I would like to implement asynchronous parameter loading. So I want to load data after losing control of the controller but but initializing the beginning of data loading from remote request in it. Tell me how best to implement this.
Or another way that would remove the error "Gateway timeout".
While this might be more of a question for the ruby-on-rails community, let me answer from the Autodesk Forge standpoint:
First of all, you should never wait for the Model Derivative job to complete when handling a request to your server. If the design file is complex enough, the translation could take up to hours, so this should definitely be handled asynchronously.
One option is to poll the status of the translation by requesting "derivative manifest" using the GET :urn/manifest endpoint.
Another option is to setup a Forge Webhook to get notified when the extraction.finished event is triggered.
It's probably easier to offload asynchronous stuff to a worker and save a reference to the user that needs to know about it. If you couple it with something like StimulusReflex you can render the result once it's finished. Another option might be the Render Async gem.
I'm using shared library to build CI/CD pipelines in Jenkins. And in my case, some of the stages need to send the execute info through web apis. In this case, we need to add stage id for current stage to api calls.
How can I access the stage id similar with ${STAGE_NAME}?
I use Pipeline REST API Plugin as well as HTTP Request Plugin
Your methods in Jenkinsfile can look like:
#NonCPS
def getJsonObjects(String data){
return new groovy.json.JsonSlurperClassic().parseText(data)
}
def getStageFlowLogUrl(){
def buildDescriptionResponse = httpRequest httpMode: 'GET', url: "${env.BUILD_URL}wfapi/describe", authentication: 'mtuktarov-creds'
def buildDescriptionJson = getJsonObjects(buildDescriptionResponse.content)
def stageDescriptionId = false
buildDescriptionJson.stages.each{ it ->
if (it.name == env.STAGE_NAME){
stageDescriptionId = stageDescription.id
}
}
return stageDescriptionId
}
Questiion is old but i found the solution: use some code from pipeline-stage-view-plugin( looks like it is already installed in jenkins by default)
we can take current job ( workflowrun ) and pass it as an argument to
com.cloudbees.workflow.rest.external.RunExt.create , and whoala: we have object that contains info about steps and time spent on it's execution.
Full code will looks like this:
import com.cloudbees.workflow.rest.external.RunExt
import com.cloudbees.workflow.rest.external.StageNodeExt
def getCurrentBuildStagesDuration(){
LinkedHashMap stagesInfo = [:]
def buildObject = com.cloudbees.workflow.rest.external.RunExt.create(currentBuild.getRawBuild())
for (StageNodeExt stage : buildObject.getStages()) {
stagesInfo.put(stage.getName(), stage.getDurationMillis())
}
return stagesInfo
}
Function will return
{SomeStage1=7, SomeStage2=1243, SomeStage3=5}
Tested with jenkins shared library and Jenkins 2.303.1
Hope it helps someone )
I am trying to upgrade my application from grails 2 to grails 3. However, the functional test which is working in grails 2 fails to run now. In grails 2, I use RestBuilder to send request and get response. In grails 3, there is no corresponding RestBuilder release. How can I send my post and get request in grails 3 functional test?
Thanks very much.
My test code in grails 2:
void testRequestNewEnvironment() {
setup:
def rest = new RestBuilder(connectTimeout:1000, readTimeout:20000)
int timeout = 10
String environmentId = 0
String environmentStatus = "Not Ready"
when:
/**
* PostMethod. Send out a post and response status should be 200 and the body of response include env_id
*/
def resp = rest.post('http://localhost:8080/test-environment-manager/environment') {
contentType "multipart/form-data"
buildfile= new File('script.sh')
username = "apps"
keepEnvflag = "false"
env_flavor = "default"
}
then:
resp.getStatus() == 200
environmentId = resp.json.env_id
println "Environment ID: $environmentId"
println ("Environment Status"+resp.json.Status)
I use RESTClient for executing HTTP requests in Grails functional tests. It's a class from the HTTPBuilder library, so it should work in every Grails version (because it has dependency on Grails).
Some example usages are shown here. Before you can use it, you'll need to add a dependency on this library by adding the following to build.gradle
compile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
I added :
compile ":rest-client-builder:2.1.1"
and it works fine.
I'm getting messages of a RabbitMQ queue and each message is a URL that I want to make a request to. Now I'm using the AMQP gem to subscribe to the queue and that uses EventMachine, so I'm using the the em-http-request library to make the http requests. According to the documentation here: https://github.com/igrigorik/em-http-request/wiki/Parallel-Requests
The following will issue asynchronous http-requests:
EventMachine.run {
http1 = EventMachine::HttpRequest.new('http://google.com/').get
http2 = EventMachine::HttpRequest.new('http://yahoo.com/').get
http1.callback { }
http2.callback { }
end
So when I subscribe to the RabbitMQ queue I have the following code:
x = 0
EventMachine.run do
connection = AMQP.connect(:host => '127.0.0.1')
channel = AMQP::Channel.new(connection)
channel.prefetch(50)
queue = channel.queue("http.requests")
exchange = channel.direct("")
queue.subscribe do |metadata, payload|
url = payload.inspect
eval "
#http#{x} = EventMachine::HttpRequest.new(url).get
#http#{x}.callback do
puts \"got a response\"
puts #http#{x}.response
end
x = x+1
"
end
end
This dynamically creates new variables and creates new http requests, similar to the way described in the em-http-request documentation. But is there a way to test whether the requests are actually being made asynchronously? Is it possible to write to the console every time a get request is fired off so I can see they are fired off one after the other without waiting for a response?
You can try running tcpdump and analysing the output. If you see the TCP three-way handshakes for the two connections being interleaved then the connections are happening in parallel.
This can't really be part of an automated test though, if that's what you're trying to aim for. I would be happy just to verify that the library does what it says it does once and not make it part of a test suite.
A very simple example, demonstrating exactly what you want:
require 'em-http-request'
EM.run do
# http://catnap.herokuapp.com/3 delays the HTTP response by 3 seconds.
http1 = EventMachine::HttpRequest.new('http://catnap.herokuapp.com/3').get
http1.callback { puts 'callback 1' }
http1
puts 'fired 1'
http2 = EventMachine::HttpRequest.new('https://www.google.com/').get
http2.callback { puts 'callback 2' }
puts 'fired 2'
end
Output (for me):
fired 1
fired 2
callback 2
callback 1
Depending on your internet connection, Heroku and Google, the response to the second HTTP request will likely come in first and you can be sure, the requests are indeed done in parallel.