We have an asynchronous application meaning we send a request to an API that accepts the request immediately and returns 200. The server then processes the request and calls back an API with the results of the above processing. Example :
Make a call to Server A on POST /order
Server A calls POST /processor/order on Server B which creates an Order.
Server B processes the Order
Server B calls back URL POST /order/callback/{1} on Server A
Server A processes the response
I tried to write an integration test for this using Spring Boot Tests and WireMock Webhooks which looks something like this :
#Test
void shouldReturnCallbackAndProcessOrder() {
// test setup ...
wm.stubFor(post(urlPathEqualTo("/processor/order"))
.willReturn(ok())
.withPostServeAction("webhook", webhook()
.withMethod(POST)
.withUrl("http://my-target-host/order/callback/1")
.withHeader("Content-Type", "application/json")
.withBody("{ \"result\": \"SUCCESS\" }"))
);
...some assertions here...
Thread.sleep(1000);
}
I need to put this line Thread.sleep(1000); at the end of the test to wait for the webhook to call the Server A. Is there a better way to do this?
I would suggest using Awaitility, which allows you to wrap a checking operation inside a lambda and it will be repeatedly checked until it's passed or a timeout is reached e.g.
await().atMost(5, SECONDS).until(/* fetch some value */, is("expected value"));
WireMock uses this for its own async testing: https://github.com/wiremock/wiremock/blob/25b82f9f97f3cc09136097b249cfd37aef924c36/src/test/java/com/github/tomakehurst/wiremock/PostServeActionExtensionTest.java#L85
Related
I'm new on .NET technology and come into some problem. Currenlty i'm trying to build a REST API that handle long processing before sending the result to client.
What i'm trying to achieve is, i would like to do a background processing after receiving request from client. But, i would also like to send a response to client.
In short, it would be something like this.
Client Request -> Handled by controller ( doing some processing ) -> send response directly, ignoring the background that still running.
On Java, i can do this using Runnable Thread. How can i achieve this on C# Web API ?
Thank you.
In short, don't do this.
The job of an API is not to perform heavy duty, long running tasks.
You could simply let the API receive the request to perform something, then delegate that to another service. The API can then send a 200 response to show it received the request and maybe a URL to another resource which allows a user to track the progress.
The API needs to be available and responsive at all times. It needs to serve a number of users and if a number of them all request something that uses a lot of resources and takes a lot of time, chances are the API will simply go down and not serve anyone.
This is why you do not do such things in an API. Let other services do the heavy lifting.
Your api can call another async method and return 200/OK response without waiting for the request to complete.
You can learn more about async programing in c#.
static async Task Main(string[] args)
{
Console.WriteLine("coffee is ready");
var toastTask = MakeToastWithButterAndJamAsync(2);
async Task<Toast> MakeToastWithButterAndJamAsync(int number)
{
//Do something here.
}
}
This can be achieve this using loosed coupled architecture, by introducing service bus or blob storage, once you receive request in web api you can save it to blob/service bus and return acknowlegement response from web api. From service bus/blob storage use webjob/function/ durable function app to process the message using event.
I have a rest controller which accepts post requests and returns the statuses of whether the operations are successfull or not. It works fine for 100 requests per second as I have multiple operations underlying it which at the end send the response.
There could be hundreds of users trying to send the requests to the controller, thereby its all done using a completable future and http Async invoker. The problem happens when there are a 1000 requests per second and then the controller threads are exhausted as there are already multiple thread processing multiple requests and all are waiting for there future to be complete and then sending the response.
How can I make my rest controller be able to handle 1000 requests per Second without breaking.
there are already multiple thread processing multiple requests and all are waiting for there future to be complete and then sending the response.
You can actually make you controllers asynchronous by making them return a CompletableFuture. Just chain the calls on the CompletableFuture returned by your service to convert them into a an appropriate response instead of using get() or join():
#RequestMapping
public CompletableFuture<ResponseEntity<…>> processRequest() {
return myService.getStatusFuture()
.thenApply(status -> convertToResponseEntity(status));
}
Of course for this to work properly you should have a truly asynchronous service. If you are using #Async or submitting tasks with CompletableFuture.supplyAsync(), this will just move the problem from the HTTP threadpool to another threadpool.
It depends on the servlet server you are using. In the application.properties file, you can use the server.* properties to set the parameters you need.
In this link you can find these properties under the EMBEDDED SERVER CONFIGURATION section. If you are using the default tomcat embedded server, check out the server.tomcat.* properties. Especially the server.tomcat.accept-count, server.tomcat.max-connections and server.tomcat.max-threads properties.
I am upgrading our implementation of AWS to V2. I would like to create an AWS client object in my tests, whose web requests are stubbed. The problem I have is getting this test client to correspond to the real client, such that I can test methods that may be called on the client in the code.
My test suite is RSpec. To give you an illustration of the problem:
aws_client = Aws::DynamoDB::Client.new(stub_responses: true)
is its own object. If created in the test, it won't correspond to the client in the code as an instance_double would:
let(:client) { instance_double(Aws::DynamoDB::Client) }
before do
allow(Aws::DynamoDB::Client).to receive(:new).and_return(client)
allow(client).to receive(<some_method>).with(<some parameters>)...
end
You can see that "client" is being used to test whether the code is communicating with the API in the desired way. The test depends on whether the code uses the correct methods with the correct parameters.
How can I get an object like aws_client (as opposed to an instance double) to correspond to client so there are no unauthorized calls to the API, and so I can test the methods that are called on the client in the code?
When I tried to globally or partially stub the AWS config responses in the spec_helper or the test file (Aws.config[:stub_responses] = true), I still see unauthorized API requests.
You may look at https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/message-chains
(receive_message_chain)
allow(double).to receive_message_chain(:foo, :bar).and_return(:baz)
I have a spring controller and request mapped method.
#RequestMapping(value = { "/doSomething.do" })
public ModelAndView emailToNonBelievers(){
.....
// do something which takes lot of time
// send response..
return modelAndView;
}
This method takes very long time, about an hour.(It is for Admin, not users. And Admin doesn't need to wait an hour. Just fire and forget, that's ok. And this is not a batch job)
But I found that client send requests repeatedly with 3 minutes interval(observed 6 times and I stopeed Spring service).
I guess because client didn't get any response from server.
If my guess is right, server should response sort of "Your request is accepted, just shut up and wait!!" .
But how to send response(200 ok) before jobs finished in Spring?
Or am I missing something?
In this situation it would be recommended to use asynchronous task processing. Spring comes with out-of-box support for it via #Async annotation.Consult my answer for detailed setup for similar query and here for docs.
Hi I am working with Web Api 2, is their any way I can handle request and response before reaching to the API controller.
You may be looking for a DelegatingHandler. These are HTTP Message Handlers that can process the request before it reaches the Controller and can also process the response on the way out of the pipeline. Delegating Handlers can also return the response themselves without calling the rest of the pipeline. You can read about Delegating Handlers here.