I have a snippet from angular UI that will call myService.getNames() when user types in a letter in the field. The switchMap will cancel the previous request whenever the user types in another letter in the field.
.pipe(
debounceTime(500),
switchMap(value => this.myService.getNames(value))
)
This service will call the REST endpoint http://localhost:8080/listing?value=<value_sent_from_client>. The query for retrieving the list of names takes some time to complete. If the user edited the field 3 times, there will be 2 cancelled requests and 1 on-going request.
On the server side, how do you cancel the 2 previously running queries? Or will they get cancelled automatically?
You cannot cancel request on server side. The solution might be in more sophisticated algorithm, like:
each request are putting into queue and return immediately not waiting for processing to be finished (storing in DB, etc.)
queue replace previous items if new items are present from same user
client subscribes to updates from server via web-sockets
Or any other approach.
Related
I have a service where a couple requests can be long running actions. Occasionally we have timeouts for these requests, and that causes bad state because steps of the flux stop executing after the cancel is called when the client disconnects. Ideally we want this action to continue processing to completion.
I've seen WebFlux - ignore 'cancel' signal recommend using the cache method... Are there any better solutions and/or drawbacks to using cache to achieve this?
there are some solutions for that.
One could be to make it asyncron. when you get the request from the customer you can put it in a processor
Sinks.Many<QueueTask<T>> queue = Sinks.many().multicast().onBackpressureBuffer()
and when the client comes from the customer you just push it to the queue and the queue will be in background processing the items.
But in this case customer will not get any response with the progress of item. only if you send it by socket or he do another request after some times.
Another one is to use Chunked http request.
#GetMapping(value = "/sms-stream/{s}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
Flux<String> streamResponse(#PathVariable("s") String s) {
return service.streamResponse(s);
}
In this case the connection will be open and you can close it automatically in server when processing is done
I am consuming a REST web service from Java code using Apache commons HTTP client API. If no response returns within the socket timeout value configured in the connection manager parameters, socket time out exception occurs. In such cases as the thread returns the exception to the caller class, even if the REST service returns response few secs later, will be lost.
Is it possible to create a new thread which will still listen to the service even after the timeout and just logs the response, while the main thread returns the exception to the caller class?
Is there any better way to achieve this?
Thanks.
The pattern you are most likely looking for involves asynchronous requests. For every action you post you create a unique "job" id and with that a specific URL for the job status. After starting the job, you can then query on that specific job instance's status. For example:
POST to /actions
Returns 202 Accepted & include a Location header to /actions/results/1234
Immediately GET /actions/results/1234 to ascertain it's status.
If it returns a 2xx your job is done.
If it returns 404, wait 10 seconds (or whatever) and try again.
Once you are happy with the result, issue a DELETE to /actions/results/1234 to clean up after yourself.
Of course you don't have to return 404 if the job is not done, there are other strategies for checking on the status - the key thing is that it's a subsequent call.
My operation takes 30 mins to process which is invoked by a rest call request. i want to give the client an immediate response telling operation in progress,and processing should happen in another thread, what is the best way to crack this out,Is deferred result the only way.
30 minutes is a long time. I'd suggest you using websockets to push progress updates and operation status.
Since you are providing rest services, another approach could be to immediately return 'Accepted' (202) or 'Created' (201) to the client and provide a link to another service that would provide updates about the progress status of the processing. This way the client is free to decide whether to poll the server for updates, or just provide the user an 'update status' button.
Use a message queue (ActiveMQ, Redis).
Send request from client.
Controller gets request, post process/message in message queue.
Send response back to client saying it's processing.
Another thread to look for changes/new process in message queue.
Execute the process - Update the status in message queue each step is completed. - (started/running/completed/failed).
You can show the status of process everytime with the id of process in queue.
I am using the Spring MVC and I have created Controllers and I am accessing them using the JQuery Ajax request, but sometimes it may be possible that the process takes long time, so I want to give the user option to stop the request for that I am using the abort function of JQuery and it stops the Ajax request successfully but it does not stop the process started on the controller. Is there any other way to do that?
If the request has already been sent to the server then the server will process the request even if we abort the request but the client will not wait for/handle the response.
Maybe you'll have to write some custom logic where initiate a thread in controller for each such ajax call and track their thread id. Then on abort request go back in controller and kill that thread.
Just a basic idea, I haven't implemented it myself so not sure about code/logic problems you might face.
Your jQuery's abort() will stop the client to listen for the response but still the server will process.
I can think of something:(I hope the process is long enough for you to stop by the way)
Continuous Polling using a thread. Have a status flag that reads at high frequency so that when you do an abort, you update the status of the request to stop. If continuous polling is enabled, you can check that status is now to abort and the thread is stopped or something like that.
If you don't use any custom logic there is no way to stop an ongoing process at controller level. Because controller process and UI process are two different layers the only connection between them is socket request - response connection.
abort on javascript side could cause big risk for your application, backend will complete process but ui won't be aware of it. You can manage your response time on controller side and return an error and abort your controller process with your own logic. for example if you have some loop on Controller put a timecheck, or you have another socket connection like db configure your connection based on timeout parameter.
What you want to do is directly related to your controller implementation.
Declare a variable to store the ajax request
var req = $.ajax({
type: 'GET',
url: '<*url*>',
......
});
We can use my request .abort()
req.abort();
Check for reference jQuery ajax
My JSF app does the following:
User inputs rows of data into a input ares.
User hit submit, button action is wired up to call remote REST services (1 call per row data)
Result of each REST call persisted into DB.
Problem is this operation is synchronous and the user does not have control of the UI until the calls are finished.