I am trying to write to multiple files concurrently using the Akka framework, First I created a class called MyWriter that writes to a file, then using futures I call the object twice hopping that 2 files will be created for me, but when I monitor the execusion of the program, it first populates the first file and then the second one (blocking /synchronously).
Q: how can I make the code bellow run (none-blocking /asynchronously)
import akka.actor._
import akka.dispatch._
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.Future
import scala.concurrent.{ ExecutionContext, Promise }
import ExecutionContext.Implicits.global
class my_controler {
}
object Main extends App {
val system = ActorSystem("HelloSystem")
val myobj = system.actorOf(Props(new MyWriter), name = "myobj")
implicit val timeout = Timeout(50 seconds)
val future2 = Future { myobj ! save("lots of conentet") }
val future1 = Future { myobj ! save("event more lots of conentet") }
}
the MyWriter code:
case class save(startval: String)
class MyWriter extends Actor {
def receive = {
case save(startval) => save_to_file(startval)
}
any ideas why the code does not execute concurrently?
Why are you wrapping the call to ? with an additional Future? Ask (?) returns a Future anyway, so what you are doing here is wrapping a Future around another Future and I'm not surte that's what you wanted to do.
The second issue I see is that you are sending two messages to the same actor instance and you are expecting them to be running in parallel. An actor instance processes its mailbox serially. If you wanted to process concurrently, then you will need two instances of your FileWriter actor to accomplish that. If that's all you want to do then just start up another instance of FileWriter and send it the second message.
Related
I am building an API with Kotlin and Ktor that should be able to receive a normal POST request.
Upon receiving it, he should keep it alive and establish a series of asynchronous communications with other systems using websocket.
Only at the end of these communications and receiving certain information will it be able to respond to the POST request.
Needless to say, the request must be kept alive.
I'm not sure how to make this possible.
I have investigated using coroutines and threads but my inexperience prevents me from understanding what would be the best solution.
By default sequential code inside a coroutine is executed synchronously so you can just put your code for communication via Websockets inside a route's handler and in the end send a response. Here is an example:
import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.plugins.websocket.*
import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import io.ktor.websocket.*
fun main() {
val client = HttpClient(OkHttp) {
install(WebSockets)
}
embeddedServer(Netty, port = 12345) {
routing {
get("/") {
client.webSocket("ws://127.0.0.1:5050/ws") {
outgoing.send(Frame.Text("Hello"))
val frame = incoming.receive()
println((frame as Frame.Text).readText())
println("Websockets is done")
}
call.respondText { "Done" }
}
}
}.start(wait = false)
embeddedServer(Netty, port = 5050) {
install(io.ktor.server.websocket.WebSockets)
routing {
webSocket("/ws") {
outgoing.send(Frame.Text("Hello from server"))
}
}
}.start()
}
I'm new to Groovy and am a bit lost on how to batch up requests so they can be submitted to a server as a batch, instead of individually, as I currently have:
class Handler {
private String jobId
// [...]
void submit() {
// [...]
// client is a single instance of Client used by all Handlers
jobId = client.add(args)
}
}
class Client {
//...
String add(String args) {
response = postJson(args)
return parseIdFromJson(response)
}
}
As it is now, something calls Client.add(), which POSTs to a REST API and returns a parsed result.
The issue I have is that the add() method is called maybe thousands of times in quick succession, and it would be much more efficient to collect all the args passed in to add(), wait until there's a moment when the add() calls stop coming in, and then POST to the REST API a single time for that batch, sending all the args in one go.
Is this possible? Potentially, add() can return a fake id immediately, as long as the batching occurs, the submit happens, and Client can later know the lookup between fake id and the ID coming from the REST API (which will return IDs in the order corresponding to the args sent to it).
As mentioned in the comments, this might be a good case for gpars which is excellent at these kinds of scenarios.
This really is less about groovy and more about asynchronous programming in java and on the jvm in general.
If you want to stick with the java concurrent idioms I threw together a code snippet you could use as a potential starting point. This has not been tested and edge cases have not been considered. I wrote this up for fun and since this is asynchronous programming and I haven't spent the appropriate time thinking about it, I suspect there are holes in there big enough to drive a tank through.
That being said, here is some code which makes an attempt at batching up the requests:
import java.util.concurrent.*
import java.util.concurrent.locks.*
// test code
def client = new Client()
client.start()
def futureResponses = []
1000.times {
futureResponses << client.add(it as String)
}
client.stop()
futureResponses.each { futureResponse ->
// resolve future...will wait if the batch has not completed yet
def response = futureResponse.get()
println "received response with index ${response.responseIndex}"
}
// end of test code
class FutureResponse extends CompletableFuture<String> {
String args
}
class Client {
int minMillisLullToSubmitBatch = 100
int maxBatchSizeBeforeSubmit = 100
int millisBetweenChecks = 10
long lastAddTime = Long.MAX_VALUE
def batch = []
def lock = new ReentrantLock()
boolean running = true
def start() {
running = true
Thread.start {
while (running) {
checkForSubmission()
sleep millisBetweenChecks
}
}
}
def stop() {
running = false
checkForSubmission()
}
def withLock(Closure c) {
try {
lock.lock()
c.call()
} finally {
lock.unlock()
}
}
FutureResponse add(String args) {
def future = new FutureResponse(args: args)
withLock {
batch << future
lastAddTime = System.currentTimeMillis()
}
future
}
def checkForSubmission() {
withLock {
if (System.currentTimeMillis() - lastAddTime > minMillisLullToSubmitBatch ||
batch.size() > maxBatchSizeBeforeSubmit) {
submitBatch()
}
}
}
def submitBatch() {
// here you would need to put the combined args on a format
// suitable for the endpoint you are calling. In this
// example we are just creating a list containing the args
def combinedArgs = batch.collect { it.args }
// further there needs to be a way to map one specific set of
// args in the combined args to a specific response. If the
// endpoint responds with the same order as the args we submitted
// were in, then that can be used otherwise something else like
// an id in the response etc would need to be figured out. Here
// we just assume responses are returned in the order args were submitted
List<String> combinedResponses = postJson(combinedArgs)
combinedResponses.indexed().each { index, response ->
// here the FutureResponse gets a value, can be retrieved with
// futureResponse.get()
batch[index].complete(response)
}
// clear the batch
batch = []
}
// bogus method to fake post
def postJson(combinedArgs) {
println "posting json with batch size: ${combinedArgs.size()}"
combinedArgs.collect { [responseIndex: it] }
}
}
A few notes:
something needs to be able to react to the fact that there were no calls to add for a while. This implies a separate monitoring thread and is what the start and stop methods manage.
if we have an infinite sequence of adds without pauses, you might run out of resources. Therefore the code has a max batch size where it will submit the batch even if there is no lull in the calls to add.
the code uses a lock to make sure (or try to, as mentioned above, I have not considered all potential issues here) we stay thread safe during batch submissions etc
assuming the general idea here is sound, you are left with implementing the logic in submitBatch where the main problem is dealing with mapping specific args to specific responses
CompletableFuture is a java 8 class. This can be solved using other constructs in earlier releases, but I happened to be on java 8.
I more or less wrote this without executing or testing, I'm sure there are some mistakes in there.
as can be seen in the printout below, the "maxBatchSizeBeforeSubmit" setting is more a recommendation that an actual max. Since the monitoring thread sleeps for some time and then wakes up to check how we are doing, the threads calling the add method might have accumulated any number of requests in the batch. All we are guaranteed is that every millisBetweenChecks we will wake up and check how we are doing and if the criteria for submitting a batch has been reached, then the batch will be submitted.
If you are unfamiliar with java Futures and locks, I would recommend you read up on them.
If you save the above code in a groovy script code.groovy and run it:
~> groovy code.groovy
posting json with batch size: 153
posting json with batch size: 234
posting json with batch size: 243
posting json with batch size: 370
received response with index 0
received response with index 1
received response with index 2
...
received response with index 998
received response with index 999
~>
it should work and print out the "responses" received from our fake json submissions.
I'm setting up a kotlin coroutine based networking framework for the jvm. The Client and Server classes implement CoroutineScope, and the override for coroutinecontext is Dispatchers.IO, as I am pretty sure that's the correct Dispatcher to use for such a case. However, I wish to handle read packets on the main thread, or at least provide that option. Without reading the documentation, I used Dispatchers.Main, which I now realize is for the android UI thread. Is there a dispatcher I can use to get a coroutine running on the main thread? If not, how would I go about making one?
I have looked around the kotlin documentation on how to create a dispatcher based around a single thread, but I couldn't find anything besides newSingleThreadContext which creates a new thread. I also figured out that it is possible to create a dispatcher from a java Executor, but I'm still not sure how to limit this to a already existing thread.
class AbstractNetworkComponent : CoroutineScope {
private val packetProcessor = PacketProcessor()
private val job = Job()
override val coroutineContext = job + Dispatchers.IO
}
class PacketProcessor : CoroutineScope {
private val job = Job()
override val coroutineContext = job + Dispatchers.Main //Android only!
private val packetHandlers = mutableMapOf<Opcode, PacketHandlerFunc>()
fun handlePacket(opcode: Opcode, packet: ReceivablePacket, networker: Writable) {
launch(coroutineContext) {
packetHandlers[opcode]?.invoke(packet, networker)
}
}
}
So with the Dispatchers.Main I get an IllegalStateException due to the android component missing. Is there a way to create a dispatcher that blocks the main thread until its completion (like runBlocking does?) Thanks!
runBlocking is exactly what you need. It creates a dispatcher and sets it in the coroutine context. You can access the dispatcher with
coroutineContext[ContinuationInterceptor] as CoroutineDispatcher
and then you can pass it to an object that implements CoroutineScope or whatever else you want to do with it. Here's some sample code:
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
import kotlin.coroutines.ContinuationInterceptor
fun main() {
println("Top-level: current thread is ${Thread.currentThread().name}")
runBlocking {
val dispatcher = coroutineContext[ContinuationInterceptor]
as CoroutineDispatcher
ScopedObject(dispatcher).launchMe().join()
}
}
class ScopedObject(dispatcher: CoroutineDispatcher) : CoroutineScope {
override val coroutineContext = Job() + dispatcher
fun launchMe() = launch {
val result = withContext(IO) {
"amazing"
}
println("Launched coroutine: " +
"current thread is ${Thread.currentThread().name}, " +
"result is $result")
}
}
This will print
Top-level: current thread is main
Launched coroutine: current thread is main, result is amazing
As per Guide to UI programming with coroutines kotlinx.coroutines has three modules that provide coroutine context for different UI application libraries:
kotlinx-coroutines-android -- Dispatchers.Main context for Android
applications.
kotlinx-coroutines-javafx -- Dispatchers.JavaFx context for JavaFX UI
applications.
kotlinx-coroutines-swing -- Dispatchers.Swing context for Swing UI
applications.
Also, UI dispatcher is available via Dispatchers.Main from kotlinx-coroutines-core and corresponding implementation (Android, JavaFx or Swing) is discovered by ServiceLoader API. For example, if you are writing JavaFx application, you can use either Dispatchers.Main or Dispachers.JavaFx extension, it will be the same object.
I have a following code:
import scala.concurrent.ExecutionContext.Implicits.global
def index = Action {
Ok(Await.result(callSync, 10.seconds).body)
}
def callSync = {
WS.url("http://yahoo.jp").get
}
Basically WS.url will return Future[ws.Response] so in the code above I wanted to monitor the behaviour of this service when invoked in blocking manner. In my action, I am waiting for the result then displaying the response body back. I am attempting this with 2000 concurrent users with 20sec ramp. Problem is that above code creates new threads in massive amount that play instance shuts down the the error "java.lang.OutOfMemoryError : unable to create new native Thread". This is totally not expected behaviour. I am using the default execution context, so this pool will only have core + 1 threads. Why is above creating massive amount of threads?
Await.result wraps the blocking wait for a result with scala.concurrent.blocking which informs the ExecutionContext that it is blocking. The default ExecutionContext is backed by a fork-join pool which would then starve quickly since it only has got as many threads as there is cores and instead it will spawn a new thread to keep the number of available threads for non-blocking operations the same.
Do this instead:
import play.api.libs.concurrent.Promise
def index = Action.async {
Future.firstCompletedOf(List(
callsync.map(x => Ok(x.body)),
Promise.timeout(Ok("an error occurred"), 10.seconds)
))
}
I cant get my head around this one here
I am a beginner to Scala just few weeks old and have tried but failed
I have read and tried about Actors, Futures,...etc didnt work for me
Could you supply a code of a server client example (or at least the server side)
Suppose to open connection using a socket that receives a string (i.e. file path) from several clients and process each one in a thread
import java.net.{Socket, ServerSocket}
import java.util.concurrent.{Executors, ExecutorService}
import java.util.Date
import java.io._
import scala.io._
import java.nio._
import java.util._
import scala.util.control.Breaks
import java.security.MessageDigest
import java.security.DigestInputStream
import scala.util.Sorting
class NetworkService(port: Int, poolSize: Int) extends Runnable {
val serverSocket = new ServerSocket(port)
val pool: ExecutorService = Executors.newFixedThreadPool(poolSize)
def run() {
try {
var i = 0
while (true) {
// This will block until a connection comes in.
val socket = serverSocket.accept()
val in = new BufferedReader(new InputStreamReader(socket.getInputStream)).readLine
/*var f = new FileSplit(in) //FileSplit is another class that i would like each
// client's sent string to be passed as an instance of
f.move*/
pool.execute(new Handler(socket))
}
} finally {
pool.shutdown()
}
}
}
class Handler(socket: Socket) extends Runnable {
def message = (Thread.currentThread.getName() + "\n").getBytes
def run() {
socket.getOutputStream.write(message)
socket.getOutputStream.close()
}
}
object MyServer {
def main(args: Array[String]) {
(new NetworkService(2030, 2)).run
}
}
You have several options available. You could do same old java style app, basically just using java standard libraries and scala syntax.
Maybe this helps: Scala equivalent of python echo server/client example?
You would just need to write logic that handles each socket (the one you get from accept()) in a new thread.
However I would not recommend using plain old java approach directly. There are great libraries out there that can handle that for you. For example Akka:
http://doc.akka.io/docs/akka/2.3.3/scala/io-tcp.html
I would also urge you to read about futures as they are super useful to do stuff async.