9 ms·
An Akka actor simply must not issue a DB call That's untrue. With Akka's pipe pattern, you can take the results of any future and pipe it back to the sender, i
by mark242 13y ago
An Akka actor simply must not issue a DB call
That's untrue. With Akka's pipe pattern, you can take the results of any future and pipe it back to the sender, including using a map on the future if you like. This is how we do reactive database calls in Akka. For example:
def receive = {
case msg => {
val f = future { myDatabaseResult(msg) }
f map { result => myTransformResult(result) } pipeTo sender
}
}
At no point does this actor block. Assuming you even have something like Play calling this actor, you wouldn't be blocking there, either, you'd take the result from the actor, likely map it to a result, and Play would asynchronously return that. My basic rule is that if you're typing Await.result anywhere in your Play/Akka code, you're doing it wrong.
- pron 13y agoThere are many ways to do asynchronous programming employing functional approaches. The difference is that with Quasar you can use them if you like but you don't have to. You can issue a plain-old JDBC call, and at no point will the thread block, either, but the actor will: because it's simple, familiar and intuitive. You don't need to learn so many unfamiliar patterns. You program as you normally would a single thread.
- dxbydt 13y agoOk, so issuing a blocking call is "simple, familiar and intuitive". Invoking a Future or a Promise is "so many unfamiliar patterns". Yes Sir, with this attitude I hope to make a remarkable progress in my tech career :) Seriously, there is nothing mysterious or magical about shoving a "plain-old JDBC call" into a Future. http://en.wikipedia.org/wiki/Future_(programming) http://en.wikipedia.org/wiki/Future_(programming) Remarkable demo, btw. But lets not run down other approaches simply because one might, god forbid, have to "learn so many unfamiliar patterns".
- andrewvc 13y agoI think you're pretending that removing the ceremony of the Future isn't a significant difference. Your point is correct, but you're missing the forrest for the trees
- MrBuddyCasino 13y agoWell he is kind of right. I'm familiar with enterprise IT, and there are very mediocre programmers at work. I'll bet you most of them have never heard of "futures". Sad, but thats how I experienced it.
- lotsofcows 13y agoPeople who don't follow your favourite programming paradigm are mediocre? Did you mean that or is it just a poorly constructed paragraph?
- MrBuddyCasino 13y agoCertainly not. I was just responding to dxbydt , who was questioning the statement that futures and promises are unfamiliar to many programmers, and I think they are, because I've seen some corporate IT departments from the inside, and its just a different environment. In no way do I endorse the use of futures or whatnot, nor are they my "favourite programming paradigm". I am simply advocating the simplest solution that works, and avoiding constructs like promises/futures seems like a good idea in that regard.
- rdtsc 13y ago> I'm familiar with enterprise IT I am also familiar with snobby wannabees functional programmers who instead of opening the goddam file and reading it are creating homomorphic endofunctors wrapped in futures with double memoization and distributed locks, so that nobody on the fucking team knows what's going on. These people are 10x more dangerous than mediocre programmers who just find the simplest way to get the work done and ship the product. Eventually 1% of the wannabes might get enlightened and realize that simple basic code is usually better than using every single programming concept wrapped in 100 lines of code that nobody (including themselves 2 weeks later) can understand.
- MrBuddyCasino 13y agoI fully agree, thats why I don't like Scala. Readability and simplicity above everything. That doesn't mean that you shouldn't be familiar with the basic concepts of the programming language that you use, and I feel the silicon valley bubble is sometimes unaware that not all programmers are startup hot shots. You actually support my argument, introducing the concept of futures is just an added layer of unnecessary "cleverness" that could be avoided with quasar/pulsar.
- deleted 13y ago[deleted]
- pron 13y agoA future is a simple blocking mechanism. The Scala example above uses something called a future, but isn't. It's an "Rx" functional future – cool and often useful, but it's yet another construct that isn't part of the actor model. I'm happy to use Rx, but I wouldn't use it in an actor. There are many ways to tackle concurrency, but IMO it's best to keep them separate as much as possible, or you quickly lose track of what's happening when.
- rdtsc 13y ago> Ok, so issuing a blocking call is "simple, familiar and intuitive". Invoking a Future or a Promise is "so many unfamiliar patterns". You got it! Great job! > Yes Sir, with this attitude I hope to make a remarkable progress in my tech career :) Well one way to not make a remarkable progress in your career is use fads, acronyms, and unnecessarily complicated constructs. Why use futures in that example when actors perfectly model the problem domain? Are you showing off that you know about Futures and they are easy?
- eeperson 13y agoWouldn't a thread still have to block somewhere? How would you call the synchronous code without blocking on any threads?
- pron 13y agoYou block the lightweight thread (fiber), rather than the OS thread. Fibers are implemented as continuations scheduled by a very good multi-threaded scheduler (ForkJoinPool).
- tuxychandru 13y agoWhen a query is executed with JDBC, the execute() method does not return until the the DB responds. The method must have been invoked in some OS thread by quasar scheduler. Wouldn't that thread block as long as execute() doesn't complete? To put it differently, can I make 10000 concurrent HTTP requests (to different domains), using a non-NIO HTTP client library, without ending up with one OS thread per request? If I can, how does the scheduler manage it?
- pron 13y ago> can I make 10000 concurrent HTTP requests (to different domains), using a non-NIO HTTP client library, without ending up with one OS thread per request? No. We provide you with a standard HTTP client API (JAX-RS client) that gives you a blocking API. Under the hood it uses asynchronous IO. We then transform callbacks to fiber-blocking operations. So you use a standard blocking API, that is implemented asynchronously. JDBC is a little more complicated as there is no async JDBC standard. What we do, then, is run the thread-blocking call in a separate IO workers pool. Those worker threads will block, but your API call will just block the fiber, letting other fibers use the same OS thread for something else until the JDBC call completes, at which point the IO worker will wake up your fiber.
- tuxychandru 13y agoHow do you determine whether a method call is thread-blocking or not? Should libraries be quasar-aware to not end up in the IO workers pool when invoked?
- hp 13y agoScala has an `async`/`await` feature (like C#) now, which hides the Future ceremony and gives sequential syntax. https://github.com/scala/async https://github.com/scala/async I guess this does still require the `await` word, but I think it's good to have a magic word for "suspend execution now" so you can see where it's happening. An OS thread still has to block on blocking IO calls somewhere, of course. There's no "syntactic" fix for that on the JVM - you have to actually port the blocking IO to nonblocking IO - AFAIK nobody can magically fix JDBC to be nonblocking from outside JDBC.
- pron 13y agoEssentially, Quasar provides async and await for all JVM languages. async is called `Fiber.start()`, and await is called `Fiber.park`. Other than working for all JVM languages, Quasar fibers are more general in that they can spawn many functions (they have a stack), while async is limited to a single expression block. Because of this, we can hide the "await" deep inside the JDBC call stack. Under the hood, they are similar: both instrument your code. Only async does this at the language level (it's a Scala macro), while fibers do it at the bytecode level.