What does it mean that Vert.x is "based on callbacks" (instead of futures)? - callback

When talking about futures and callbacks, the documentation says that
The Vert.x core APIs are based on callbacks to notify of asynchronous
events. The seasoned developer will naturally think that this opens
the door to the so-called "callback hell" where multiple levels of
nested callbacks render the code difficult to comprehend as
illustrated by this fictional code:
foo.a(1, res1 -> {
if (res1.succeeded()) {
bar.b("abc", 1, res2 -> {
if (res.succeeded()) {
baz.c(res3 -> {
dosomething(res1, res2, res3, res4 -> {
// (...)
});
});
}
});
}
});
While the core APIs could have been designed to favor promises and futures, the choice of callbacks as the cardinal model is
actually interesting since it allows different programming
abstractions to be used.
What does it mean that "The Vert.x core APIs are based on callbacks"? What would be different if it was based on futures?
What does "callbacks as the cardinal model" mean?

It means that the Vert.x core asynchronous APIs all take callbacks as input, and use that callback to handle reacting to the asynchronous result of the API call. If it was based on Futures, instead of an API like this:
void deployVerticle(Verticle verticle, Handler<AsyncResult<String>>
completionHandler);
It would look like this:
Future<String> deployVerticle(Verticle verticle);
So instead of taking a callback that gets an AsyncResult<String> as input, it returns a Future<String>. However, the Vert.x team is moving to a hybrid Callback/Future-based model in Vert.x 4.0, so both of these kinds of APIs will be part of the core Vert.x API in the near-future.
I believe cardinal is used here to mean "fundamental". So it just means that Vert.x itself uses callbacks in its own implementation. It then uses code generation and/or other techniques to derive other kinds of API abstractions. Like APIs that return Futures, or return RxJava types, or can be used as Kotlin coroutines, etc.
In general, Futures are easier to work with than callbacks, especially when you have to compose several asynchronous operations together. For example, the code you included in your original question could probably be written like this, using Futures:
CompositeFuture.all(foo.a(1), bar.b("abc", 1), baz.c())
.compose(fut -> doSomething(fut.resultAt(0), fut.resultAt(1),
fut.resultAt(2)))
.compose(res4 -> ...)

Related

What are algebraic effects, exactly? [duplicate]

Ref:
http://www.eff-lang.org/handlers-tutorial.pdf
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/08/algeff-tr-2016-v2.pdf
https://github.com/matijapretnar/eff
I have searched a lot of links, but it seems that no one could explain it specifically. Could anyone give some code(use javaScript) to explain it?
What is an Algebraic Effect?
TL;DR: In short, Algebraic Effects are an exception mechanism which lets the throwing function continue its operation.
Try to think of Algebraic Effects as some sort of try / catch mechanism, where the catch handler does not just "handle the exception", but is able to provide some input to the function which threw the exception. The input from the catch handler is then used in the throwing function, which continues as if there was no exception.
Some sample pseudo code:
Let's consider a function which needs some data to perform its logic:
function throwingFunction() {
// we need some data, let's check if the data is here
if (data == null) {
data = throw "we need the data"
}
// do something with the data
}
Then we have the code that invokes this function:
function handlingFunction() {
try {
throwingFunction();
} catch ("we need the data") {
provide getData();
}
}
As you see, the throw statement is an expression evaluating to the data provided by the catch handler (I used the keyword provide here, which afaik does not exist in any programming language of today).
Why is this important?
Algebraic Effects are a very general and basic concept. This can be seen by the fact that many existing concepts can be expressed in Algebraic Effects.
try/catch
If we had Algebraic Effects but no Exceptions in our favorite programming language, we could just omit the provide keyword in the catch handler, and voilĂ , we would have an exception mechanism.
In other words, we would not need any Exceptions if we had Algebraic Effects.
async/await
Look again at the pseudo code above. Let's assume the data which we need has to be loaded over the network. If the data is not yet there, we would normally return a Promise and use async/await to handle it. This means that our function becomes an asynchronous function, which can only be called from asynchronous functions. However, Algebraic Effects are capable of that behavior too:
function handlingFunction() {
try {
throwingFunction();
} catch ("we need the data") {
fetch('data.source')
.then(data => provide data);
}
}
Who said that the provide keyword has to be used immediately?
In other words, had we had Algebraic Effects before async/await, there would be no need to clutter up the languages with them. Furthermore, Algebraic Effects would not render our functions colorful - our function does not become aynchronous from the language viewpoint.
Aspect-Oriented Programming
Let's say we want to have some log statements in our code, but we don't yet know which logging library it will be. We just want some general log statements (I replaced the keyword throw with the keyword effect here, to make it a bit more readable - note that effect is not a keyword in any language I know):
function myFunctionDeepDownTheCallstack() {
effect "info" "myFunctionDeepDownTheCallstack begins"
// do some stuff
if (warningCondition) {
effect "warn" "myFunctionDeepDownTheCallstack has a warningCondition"
}
// do some more stuff
effect "info" "myFunctionDeepDownTheCallstack exits"
}
And then we can connect whichever log framework in a few lines:
try {
doAllTheStuff();
}
catch ("info" with message) {
log.Info(message);
}
catch ("warn" with message) {
log.Warn(message);
}
This way, the log statement and the code that actually does the logging are separated.
As you can see, the throw keyword is not really suited in the context of the very general Algebraic Effects. More suitable keywords would be effect (as used here) or perform.
More examples
There are other existing language or library constructs that could be easily realized using Algebraic Effects:
Iterators with yield. A language with Algebraic Effects does not need the yield statement.
React Hooks (this is an example of a construct at the library level - the other examples here are language constructs).
Today's support
AFAIK there are not many languages with support for Algebraic Effects out of the box (please comment if you know examples that do). However, there are languages which allow the creation of algebraic effects libraries, one example being Javascript with its function* and yield keywords (i.e. generators). The library redux-saga uses Javascript generators to create some Algebraic Effects:
function* myRoutineWithEffects() {
// prepare data load
let data = yield put({ /* ... description of data to load */ });
// use the data
}
The put is an instruction that tells the calling function to execute the data load call described in the argument. put itself does not load anything, it just creates a description of what data to load. This description is passed by the yield keyword to the calling function, which initiates the data load.
While waiting for the results, the generator routine is paused. Then, the results are passed back to the routine and can then be used there after being assigned to the data variable. The routine then continues with the local stack plus the loaded data.
Note that in this scenario, only the calling function (or the code that has a reference to the generator) can "serve" the algebraic effect, e.g. do data loads and other things. So it is not an algebraic effect as described above, because it is not an exception mechanism that can jump up and down the call stack.
Its hard to gain a solid theoretical understanding of algebraic effects without a basis in category theory, so I'll try to explain its usage in layman terms, possibly sacrificing some accuracy.
An computational effect is any computation that includes an alteration of its environment. For example, things like total disk capacity, network connectivity are external effects, that play a role in operations like reading/writing files or accessing a database. Anything that a function produces, besides the value it computes, is a computational effect. From the perspective of that function, even another function that accesses the same memory as that function does, can be considered an effect.
That's the theoretical definition. Practically, its useful to think of an effect as any interaction between a sub expression and a central control which handles global resources in a program. Sometimes, a local expression may need to send messages to the central control while execution, along with enough information so that once the central control is done, it can resume the suspended execution.
Why do we do this? Because sometimes large libraries have very long chains of abstractions, which can get messy. Using "algebraic effects", gives us a sort of short cut to pass things between abstractions, without going through the whole chain.
As a practical JavaScript example, let's take a UI library like ReactJS. The idea is that UI can be written as a simple projection of data.
This for instance, would be the representation of a button.
function Button(name) {
return { buttonLabel: name, textColor: 'black' };
}
'John Smith' -> { buttonLabel: 'John Smith', textColor: 'black' }
Using this format, we can create a long chain of composable abstractions. Like so
function Button(name) {
return { buttonLabel: name, textColor: 'black' };
}
function UsernameButton(user) {
return {
backgroundColor: 'blue',
childContent: [
Button(user.name)
]
}
}
function UserList(users){
return users.map(eachUser => {
button: UsernameButton(eachUser.name),
listStyle: 'ordered'
})
}
function App(appUsers) {
return {
pageTheme: redTheme,
userList: UserList(appUsers)
}
}
This example has four layers of abstraction composed together.
App -> UserList -> UsernameButton -> Button
Now, let's assume that for any of these buttons, I need to inherit the color theme of whatever machine it runs on. Say, mobile phones have red text, while laptops have blue text.
The theme data is in the first abstraction (App). It needs to be implemented in the last abstraction (Button).
The annoying way, would be to pass on the theme data, from App to Button, modifying each and every abstraction along the way.
App passes theme data to UserList
UserList passes it to UserButton
UserButton passes it to Button
It becomes obvious that in large libraries with hundreds of layers of abstraction, this is a huge pain.
A possible solution is to pass on the effect, through a specific effect handler and let it continue when it needs to.
function PageThemeRequest() {
return THEME_EFFECT;
}
function App(appUsers) {
const themeHandler = raise new PageThemeRequest(continuation);
return {
pageTheme: themeHandler,
userList: UserList(appUsers)
}
}
// ...Abstractions in between...
function Button(name) {
try {
return { buttonLabel: name, textColor: 'black' };
} catch PageThemeRequest -> [, continuation] {
continuation();
}
}
This type of effect handling, where one abstraction in a chain can suspend what its doing (theme implementation), send the necessary data to the central control (App, which has access to external theming), and passes along the data needed for continuation, is an extremely simplistic example of handling effects algebraically.
Well as far as I understand the topic, algebraic effects are currently an academic/experimental concept that lets you alter certain computational elements (like function calls, print statements etc.) called "effects" by using a mechanism that resembles throw catch
The simplest example I can think of in a language like JavaScript is modifying the output message in lets say console.log. Supposed you want to add "Debug Message: " in front of all your console.log statements for whatever reason. This would be trouble in JavaScript. Basically you would need to call a function on every console.log like so:
function logTransform(msg) { return "Debug Message: " + msg; }
console.log(logTransform("Hello world"));
Now if you have many console.log statements every single one of them needs to be changed if you want to introduce the change in logging. Now the concept of algebraic effects would allow you to handle the "effect" of console.log on the system. Think of it like console.log throwing an exception before invocation and this exception (the effect) bubbles up and can be handled. The only difference is: If unhandled the execution will just continue like nothing happened. No what this lets you do is manipulate the behaviour of console.log in an arbitrary scope (global or just local) without manipulating the actual call to console.log. Could look something like this:
try
{
console.log("Hello world");
}
catch effect console.log(continuation, msg)
{
msg = "Debug message: " + msg;
continuation();
}
Note that this is not JavaScript, I'm just making the syntax up. As algebraic effects are an experimental construct they are not natively supported in any major programming language I know (there are however several experimental languages like eff https://www.eff-lang.org/learn/). I hope you get a rough understanding how my made-up code is intended to work. In the try catch block the effect that might be thrown by console.log can be handled. Continuation is a token-like construct that is needed to control when the normal workflow should continue. It's not necessary to have such a thing but it would allow you to make manipulations before and after console.log (for example you could add an extra log message after each console.log)
All in all algebraic effects are an interesting concept that helps with many real-world problems in coding but it can also introduce certain pitfalls if methods suddenly behave differently than expected. If you want to use algebraic effects right now in JavaScript you would have to write a framework for it yourself and you probably won't be able to apply algebraic effects to core functions such as console.log anyway. Basically all you can do right now is explore the concept on an abstract scale and think about it or learn one of the experimental languages. I think that's also the reason why many of the introductory papers are so abstract.
You can check out algebraic-effects. It is a library that implements a lot of the concepts of algebraic effects in javascript using generator functions, including multiple continuations. It's a lot easier to understand algebraic-effects in terms of try-catch (Exception effect) and generator functions.

How to achieve composing of Vert.x AsyncResult<T>?

While performing a operation which might fail or succeed I have been using the Handler<AsyncResult<T>> so that result can be asynchronously passed when ready.
For example operation may be something like adding an entry into cache, like below
public void putEnvironmentVariable(String variableName, EnvVariable variable, Handler<AsyncResult<Long>> rsHandler) {
redisClient.hset(ENV_CACHE, variableName, Json.encode(variable), rsHandler);
}
In the above example I'm making use of Vert.x-redis add entry into a set.
Now if the same has to be done to add multiple entries into cache, I'm doing it like mentioned below
list.forEach(envVariable -> {
redisUtils.putEnvironmentVariable(envVariable.getName(), envVariable, result -> {
});
});
Questions:
1) Is this approach right ? or can it be done in a simpler/better way?
2) Here I've taken an example, but in general if there is a need to perform some operation like mentioned above and result of all operations combined to be passed on to the calling method how can that be achieved in vert.x?
I'm using
Vert.x 3.6.3
When you have to perform several async operations and combine the result of them into one result, you have two choices:
Using Vert.x Future
You wrap the redisClient.hset() async result in a Vert.x Future and then join all that async operations using Vert.x CompositeFuture:
Future<Long> fut = Future.future();
redisClient.hset(ENV_CACHE, variableName, Json.encode(variable), fut);
Then when you have a list of all futures you can use CompositeFuture:
CompositeFuture
.all(futuresList)
.map(cf -> /*aggregate all results in one single result*/)
Using Vert.x with RxJava 2
If you are using Vert.x with RxJava 2, you can merge all Single using combinators and then compose the final result with aggregators
The choice depends on you, anyway I suggest you give a look at Vert.x with RxJava 2. The RxJava 2 operators play well with Vert.x async operations and allow you to easily solve problems like these

What are advantages of a Twitter Future over a Scala Future?

I know a lot of reasons for Scala Future to be better. Are there any reasons to use Twitter Future instead? Except the fact Finagle uses it.
Disclaimer: I worked at Twitter on the Future implementation. A little bit of context, we started our own implementation before Scala had a "good" implementation of Future.
Here're the features of Twitter's Future:
Some method names are different and Twitter's Future has some new helper methods in the companion.
e.g. Just one example: Future.join(f1, f2) can work on heterogeneous Future types.
Future.join(
Future.value(new Object), Future.value(1)
).map {
case (o: Object, i: Int) => println(o, i)
}
o and i keep their types, they're not casted into the least common supertype Any.
A chain of onSuccess is guaranteed to be executed in order:
e.g.:
f.onSuccess {
println(1) // #1
} onSuccess {
println(2) // #2
}
#1 is guaranteed to be executed before #2
The Threading model is a little bit different. There's no notion of ExecutionContext, the Thread that set the value in a Promise (Mutable implementation of a Future) is the one executing all the computations in the future graph.
e.g.:
val f1 = new Promise[Int]
f1.map(_ * 2).map(_ + 1)
f1.setValue(2) // <- this thread also executes *2 and +1
There's a notion of interruption/cancellation. With Scala's Futures, the information only flows in one direction, with Twitter's Future, you can notify a producer of some information (not necessarily a cancellation). In practice, it's used in Finagle to propagate the cancellation of a RPC. Because Finagle also propagates the cancellation across the network and because Twitter has a huge fan out of requests, this actually saves lots of work.
class MyMessage extends Exception
val p = new Promise[Int]
p.setInterruptHandler {
case ex: MyMessage => println("Receive MyMessage")
}
val f = p.map(_ + 1).map(_ * 2)
f.raise(new MyMessage) // print "Receive MyMessage"
Until recently, Twitter's Future were the only one to implement efficient tail recursion (i.e. you can have a recursive function that call itself without blowing up you call stack). It has been implemented in Scala 2.11+ (I believe).
As far as I can tell the main difference that could go in favor of using Twitter's Future is that it can be cancelled, unlike scala's Future.
Also, there used to be some support for tracing the call chains (as you probably know plain stack traces are close to being useless when using Futures). In other words, you could take a Future and tell what chain of map/flatMap produced it. But the idea has been abandoned if I understand correctly.

Playframework non-blocking Action

Came across a problem I did not find an answer yet.
Running on playframework 2 with Scala.
Was required to write an Action method that performs multiple Future calls.
My question:
1) Is the attached code non-blocking and hence looking the way it should be ?
2) Is there a guarantee that both DAO results are caught at any given time ?
def index = Action.async {
val t2:Future[Tuple2[List[PlayerCol],List[CreatureCol]]] = for {
p <- PlayerDAO.findAll()
c <- CreatureDAO.findAlive()
}yield(p,c)
t2.map(t => Ok(views.html.index(t._1, t._2)))
}
Thanks for your feedback.
Is the attached code non-blocking and hence looking the way it should be ?
That depends on a few things. First, I'm going to assume that PlayerDAO.findAll() and CreatureDAO.findAlive() return Future[List[PlayerCol]] and Future[List[CreatureCol]] respectively. What matters most is what these functions are actually calling themselves. Are they making JDBC calls, or using an asynchronous DB driver?
If the answer is JDBC (or some other synchronous db driver), then you're still blocking, and there's no way to make it fully "non-blocking". Why? Because JDBC calls block their current thread, and wrapping them in a Future won't fix that. In this situation, the most you can do is have them block a different ExecutionContext than the one Play is using to handle requests. This is generally a good idea, because if you have several db requests running concurrently, they can block Play's internal thread pool used for handling HTTP requests, and suddenly your server will have to wait to handle other requests (even if they don't require database calls).
For more on different ExecutionContexts see the thread pools documentation and this answer.
If you're answer is an asynchronous database driver like reactive mongo (there's also scalike-jdbc, and maybe some others), then you're in good shape, and I probably made you read a little more than you had to. In that scenario your index controller function would be fully non-blocking.
Is there a guarantee that both DAO results are caught at any given time ?
I'm not quite sure what you mean by this. In your current code, you're actually making these calls in sequence. CreatureDAO.findAlive() isn't executed until PlayerDAO.findAll() has returned. Since they are not dependent on each other, it seems like this isn't intentional. To make them run in parallel, you should instantiate the Futures before mapping them in a for-comprehension:
def index = Action.async {
val players: Future[List[PlayerCol]] = PlayerDAO.findAll()
val creatures: Future[List[CreatureCol]] = CreatureDAO.findAlive()
val t2: Future[(List[PlayerCol], List[CreatureCol])] = for {
p <- players
c <- creatures
} yield (p, c)
t2.map(t => Ok(views.html.index(t._1, t._2)))
}
The only thing you can guarantee about having both results being completed is that yield isn't executed until the Futures have completed (or never, if they failed), and likewise the body of t2.map(...) isn't executed until t2 has been completed.
Further reading:
Are there any benefits in using non-async actions in Play Framework 2.2?
Understanding the Difference Between Non-Blocking Web Service Calls vs Non-Blocking JDBC

A little help on understanding Scalaz Future and Task

I'm trying to understand the idea and purpose behind scalaz concurrent package, primarily Future and Task classes, but when using them in some application, it's now far from simple sequential analog, whereas scala.concurrent.Future, works more then better. Can any one share with his experience on writing concurrent/asynchronous application with scalaz, basically how to use it's async method correctly? As i understand from the sources async doesn't use a separate thread like the call to standard future, or fork/apply methods from scalaz works, so why it is called async then? Does it mean that in order to get real concurrency with scalaz i always have to call fork(now(...)) or apply?
I'm not a scalaz expert, but I'll try to help you a little bit. Let me try answer your questions one by one:
1) Can any one share with his experience on writing concurrent/asynchronous application with scalaz, basically how to use it's async method correctly?
Let's first take a look at async signature:
def async[A](listen: (A => Unit) => Unit): Future[A]
This could be a bit cryptic at first, so as always it's good idea to look at tests to understands possible use cases. In https://github.com/scalaz/scalaz/blob/scalaz-seven/tests/src/test/scala/scalaz/concurrent/FutureTest.scala
you can find the following code:
"when constructed from Future.async" ! prop{(n: Int) =>
def callback(call: Int => Unit): Unit = call(n)
Future.async(callback).run must_==
}
As we know from signature Future.async just construct new Future using function of signature (A => Unit) => Unit. What this really means is that Future.async takes as parameter function which for given callback makes all required computations and pass the result to that callback.
What is important to note it that Future.async does not run any computations on itself, it only prepare structure to run them later.
2) As i understand from the sources async doesn't use a separate thread like the call to standard future, or fork/apply methods from scalaz works, so why it is called async then?
You are correct. Only fork and apply seems to be running anything using threads, which is easy to notice looking at the signatures which contains implicit pool: ExecutorService. I cannot speak for the authors here, but I guess async is related to the callback. It means that rather than blocking on Future to get it result at the end you will use asynchronous callback.
3) Does it mean that in order to get real concurrency with scalaz i always have to call fork(now(...)) or apply?
From what I can say, yes. Just notice that when you are creating Future using syntax Future(x) you are using apply method here, so this is kind of default behavior (which is fine).
If you want to better understand design of Scalaz Futures I can recommend you reading "Functional Programming in Scala". I believe this book is written by main Scalaz contributors and chapter 7 discusses designing API for purely functional parallelism library. It's not exactly the same as Scalaz Future, but you can see many similarities.
You can also read wonderful Timothy Perrett blog post about Scalaz Task and Future which covers many not so obvious details.
async is used to adapt an async, callback-based API as a Future. It's called async because it's expected that it will be used with something that runs asynchronously, perhaps calling the callback from another thread somewhere further down the line. This is "real" concurrency, provided the API you're calling really uses it asynchronously (e.g. I use Future.async with the async parts of the AWS SDK like AmazonSimpleDBAsyncClient).
If you want "real" concurrency from the scalaz Task API directly you need to use things like fork or gatherUnordered, as many of the APIs default towards being safe/deterministic and restartable, with concurrency only when explicitly requested.
When composing Tasks with map and flatMap you can get a performance win by not using fork, see:
http://blog.higher-order.com/blog/2015/06/18/easy-performance-wins-with-scalaz/