I am current writing a WebSocket client. There are a few functions that I need to happen sequentially.
currently I do it in this way
Connect to server
Then set up a listener.
Add Conditional statement to listener.(To check if response id's match request ids)
send request One with id
if response id matches request One Id then process request
send request Two
repeat
This makes sequential actions look something like this
_channel.stream.listen((response) {
if(response.id == requestOne.id) {
handleRequestOneResponse(response);
}
if (response.id == requestTwo.id){
handleRequestTwoResponse(response);
}
...
});
sendActionOneRequest();
handleRequestOneResponse() {
// Some processing
sendActionTwoRequest();
}
handleRequestTwoResponse() {
// some processing
sendActionThreeRequest();
}
What I want to do is
Set up an async function
Send the request to the WebSocket server.
Pause the execution of the async function.
wait until a matching response comes from the server
complete the async function.
This would allow me to write a series of actions like
await actionOne();
await actionTwo();
await actionThree();
I'm thinking I can set up and destroy a stream listener in each action function but I don't know how to wait for a specific response before exiting.
On the other hand I think I can even use the existing listener on the outside, but I still can't figure out to wait till a specific response comes in before moving forward.
As it is I have to jump through every function to find out what comes after the other and there are more than 5 requests that have to be sent sequentially.
I am making a web service request that produces a Future. Like so (a simplified reproduction):
import play.api.libs.ws.WSClient
import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.duration._
class Service(wsClient: WSClient)(implicit ec: ExecutionContext) {
def callWebService() = {
val req: WSRequest = wsClient.url(...).withRequestTimeout(180 seconds)...
val respFuture:Future[Response] = req.execute()
}
}
The web service being invoked gets 180 seconds to respond before WSClient gives up.
This Service class' client now calls it as service.callWebService(). When the third party web service takes > 120 seconds, instead of waiting for 180 seconds, the future timesout at 120 seconds (java.util.concurrent.TimeoutException: Read timeout to localhost/127.0.0.1:8081 after 120000 ms thrown in application-akka.actor.default-dispatcher-3 thread).
Appreciate any pointers on how to increase the 120 seconds used by the default dispatcher to 180 seconds.
Note:
The app uses Akka actors elsewhere. But there are no actors involved in this control flow.
This post comes close but doesn't help.
Play WS includes a global request timeout, which defaults to 2 minutes.
Putting the following in your application's config (by default application.conf) should rectify things.
play.ws.timeout.request = 3 minutes
play.ws.timeout.idle = 3 minutes
I'm new to Play and Scala. I'm trying to build an Application using Play and Scala. I need to make post call internally to get data from my server. But this should be synchronous. After getting the data from this post request, I need to send that data to front end. I've seen many resources but all are asynchronous. Please help me.
I'm fetching data from DB and then should return the data as response.
DB is at remote server not in the hosted server.
I think you should not block anyway.
def action = Action.async {
WS.url("some url")
.post(Json.toJson(Map("query"->query)))
.map { response =>
val jsonResponse = response.json
// in this place you have your response from your call
// now just do whatever you need to do with it,
// in this example I will return it as `Ok` result
Ok(jsonResponse)
}
}
Just map the result of your call and modify it staying in context of Future and use Action.async that takes a Future.
If you really want to block use Await.result(future, 5 seconds), importing
import scala.concurrent.duration._
import scala.concurrent.Await
See docs for Await here
All requests are asynchronous but nothing prevents you from waiting the response with await in your code.
val response = await(yourFutureRequest).body
The line written above will block until the future has finished.
I am new in Akka actors and I am doing some tests. Suppose I have actors performing long running tasks like following:
override def receive = {
case email: Email => /*Future*/ {
Thread sleep 3000
}
}
I ran a stress test (remote actos on another machine in network) and I receive the following error:
akka.remote.EndpointAssociationException: Association failed with [akka.tcp://EmailSystem#192.168.1.6:5000]
Caused by: akka.remote.transport.AkkaProtocolException: No response from remote. Handshake timed out
How can I configure this to don't get this error again? Should I use a future in the receive method instead of normal code (as on comment above)? What is the impact of doing that?
It's a really bad idea to have an actor that blocks for a long time like that, since it cannot respond to messages and additionally the akka default threadpool is one thread per core of your computer so you might also be stopping other actors from processing any messages.
Fork that blocking job on a separate execution context/thread pool instead (and make sure to limit how many threads there is in that threadpool). You can then notify the actor using pipeTo:
import akka.pattern.pipe
case email: Email =>
val futureEmail = Future {
... send email and then ...
EmailSent()
}
futureEmail pipeTo sender
I need to write a client that continuously polls a web server for commands. A response from the server indicates that a command is available (in which case the response contains the command) or an instruction that no command is available, and you should fire off a new request for incoming commands.
I'm trying to figure out how to do it using spray-client and Akka, and I can think of ways to do it, but none of them look like they're the idiomatic way to get it done. So the question is:
what's the most sensible way to have a couple of threads poll the same web server for incoming commands and hand the commands off to an actor?
This example uses spray-client, scala futures, and Akka scheduler.
Implementation varies depending on desired behavior (execute many requests in parallel at the same time, execute in different intervals, send responses to one actor to process one response at a time, send responses to many actors to process in parallel... etc).
This particular example shows how execute many requests in parallel at the same time, and then do something with each result as it completes, without waiting for any other requests that were fired off at the same time to complete.
The code below will execute two HTTP requests every 5 seconds to 0.0.0.0:9000/helloWorld and 0.0.0.0:9000/goodbyeWorld in parallel.
Tested in Scala 2.10, Spray 1.1-M7, and Akka 2.1.2:
Actual scheduling code that handles periodic job execution:
// Schedule a periodic task to occur every 5 seconds, starting as soon
// as this schedule is registered
system.scheduler.schedule(initialDelay = 0 seconds, interval = 5 seconds) {
val paths = Seq("helloWorld", "goodbyeWorld")
// perform an HTTP request to 0.0.0.0:9000/helloWorld and
// 0.0.0.0:9000/goodbyeWorld
// in parallel (possibly, depending on available cpu and cores)
val retrievedData = Future.traverse(paths) { path =>
val response = fetch(path)
printResponse(response)
response
}
}
Helper methods / boilerplate setup:
// Helper method to fetch the body of an HTTP endpoint as a string
def fetch(path: String): Future[String] = {
pipeline(HttpRequest(method = GET, uri = s"/$path"))
}
// Helper method for printing a future'd string asynchronously
def printResponse(response: Future[String]) {
// Alternatively, do response.onComplete {...}
for (res <- response) {
println(res)
}
}
// Spray client boilerplate
val ioBridge = IOExtension(system).ioBridge()
val httpClient = system.actorOf(Props(new HttpClient(ioBridge)))
// Register a "gateway" to a particular host for HTTP requests
// (0.0.0.0:9000 in this case)
val conduit = system.actorOf(
props = Props(new HttpConduit(httpClient, "0.0.0.0", 9000)),
name = "http-conduit"
)
// Create a simple pipeline to deserialize the request body into a string
val pipeline: HttpRequest => Future[String] = {
sendReceive(conduit) ~> unmarshal[String]
}
Some notes:
Future.traverse is used for running futures in parallel (ignores order). Using a for comprehension on a list of futures will execute one future at a time, waiting for each to complete.
// Executes `oneThing`, executes `andThenAnother` when `oneThing` is complete,
// then executes `finally` when `andThenAnother` completes.
for {
oneThing <- future1
andThenAnother <- future2
finally <- future3
} yield (...)
system will need to be replaced with your actual Akka actor system.
system.scheduler.schedule in this case is executing an arbitrary block of code every 5 seconds -- there is also an overloaded version for scheduling messages to be sent to an actorRef.
system.scheduler.schedule(
initialDelay = 0 seconds,
frequency = 30 minutes,
receiver = rssPoller, // an actorRef
message = "doit" // the message to send to the actorRef
)
For your particular case, printResponse can be replaced with an actor send instead: anActorRef ! response.
The code sample doesn't take into account failures -- a good place to handle failures would be in the printResponse (or equivalent) method, by using a Future onComplete callback: response.onComplete {...}
Perhaps obvious, but spray-client can be replaced with another http client, just replace the fetch method and accompanying spray code.
Update: Full running code example is here:
git clone the repo, checkout the specified commit sha, $ sbt run, navigate to 0.0.0.0:9000, and watch the code in the console where sbt run was executed -- it should print Hello World!\n'Goodbye World! OR Goodbye World!\nHelloWorld! (order is potentially random because of parallel Future.traverse execution).
You can use HTML5 Server-Sent Events. It is implemented in many Scala frameworks. For example in xitrum code looks like:
class SSE extends Controller {
def sse = GET("/sse") {
addConnectionClosedListener {
// The connection has been closed
// Unsubscribe from events, release resources etc.
}
future {
respondEventSource("command1")
//...
respondEventSource("command2")
//...
}
}
SSE is pretty simple and can be used in any software not only in browser.
Akka integrated in xitrum and we use it in similar system. But it uses netty for async server it is also good for processing thousands of request in 10-15 threads.
So in this way your client will keep connection with server and reconnect when connection will be broken.