Requester 2.0 library released

101 views
Skip to first unread message

Justin du coeur

unread,
Jul 29, 2015, 10:49:22 AM7/29/15
to akka...@googlegroups.com
For those who are interested, I have just cut the second major release of the Requester library, with many improvements over 1.1.


What it is: Requester introduces request(), which can be thought of as the better-behaved big brother to ask().  ask() returns a Future, and is therefore quite dangerous to use inside of an Actor, because the Future violates the single-threadedness of the Actor, and doesn't preserve sender.  request(), by contrast, loops the result of its request back into the Actor's mailbox and preserves sender across the whole thing.  Basically, request() works the way you intuitively *expect* ask() to work.

As a result, Requester allows you to safely write completely natural, composed, multi-Actor code inside of an Actor, like this:

case GetSpacesStatus(requester) => {
  for {
    ActiveThings(nConvs) <- conversations ? GetActiveThings
    ActiveSessions(nSessions) <- sessions ? GetActiveSessions
  }
    sender ! SpaceStatus(spaceId, state.displayName, nConvs, nSessions)
}
There is a lot more -- Requester is heavily used by Querki, and I've been evolving it steadily.  At this point, I think it's in good shape for other folks to make serious use of it.  I invite y'all to play with it; comments and PRs are warmly welcomed.

(And yes, I still need to write up a PR for the Akka documentation, for the external contributions section. I hadn't done so before because I wasn't happy enough about the state of things, but it seems to be getting solid enough now.)


Changes in 2.0

The most important change is that RequestM (the equivalent of Future -- a block of work that will be executed in the Actor's receive loop) is now much better-behaved, monadically. By and large, you can treat a RequestM like a Future, and it will typically do what you expect.  In particular, RequestMs now generally compose correctly, where they previously only composed in certain ways.

There is now an implicit conversion from RequestM[T] to Future[T].  This makes it easier to use when your Actor is implementing Future-oriented functions.  (Which I find comes up in client-server RPC programming.)

The loopback is now caught in unhandled(), so you can usually just mix in Requester and start using it.  You only need to explicitly call handleRequestResponse under certain special circumstances.

? is now an alias for request(), intentionally mimicking ask().

Heiko Seeberger

unread,
Jul 29, 2015, 11:14:37 AM7/29/15
to akka...@googlegroups.com
Is Requester offering any benefits over ask in combination with pipeTo?

Thanks
Heiko

--

Heiko Seeberger
Twitter: @hseeberger

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Justin du coeur

unread,
Jul 30, 2015, 12:25:02 PM7/30/15
to akka...@googlegroups.com
Compositional construction of your functions, mainly.  pipeTo gets the data to where it needs to be in order to work safely, but you wind up writing a separate clause in your receive to handle that response, at which point ask() isn't gaining all that much over simply doing tells back and forth.  Your logic winds up getting sliced-and-diced over a bunch of receive case clauses.

request(), OTOH, allows you to build more natural code, that *looks* like programming with Futures, where the response processing can be right there with the request.  I've found that this approach produces much more readable code, especially when you get into complex situations.  For example, you can compose recursive structures, like this example from the unit tests:

class Exponent extends QTestActor {
def doReceive = {
case Terms(seed, exp) => askDoubler(seed, exp) foreach { result => sender ! result }
}
def askDoubler(seed:Int, exp:Int):RequestM[Int] = {
if (exp == 1) {
RequestM.successful(seed)
} else {
doubler.requestFor[Int](seed) flatMap { doubled =>
askDoubler(doubled, exp - 1)
}
}
}
}

In this example, askDoubler is essentially folding over a series of doubling operations, pretty much exactly the way you would do with Futures.  (Granted, this example is pure-functional, so you could potentially just ignore the dangers of using ask and Future, but as soon as you interact with the Actor's state Requester becomes crucial.)  Moreover, it gives you a nice composable handle, so doReceive() can simply say what to do with the results of the whole chain of askDoubler operations.  (I wanted a more complex, impure version of this example in my real code a few days ago, which is what led to this second release of Requester.)

And of course, since RequestM is strongly typed (like Future), it makes it much easier to compose complex processes in a strongly-typed way.  I've caught more than one bug in the IDE simply through that type checking, because the IDE pointed out that my RequestMs didn't line up properly.

So that's the real advantage, and really what I've been trying to accomplish: doing Future-style programming while not breaking the Actor invariants.  I find it much more natural, especially for my higher-level Actors that are doing lots of interaction with other Actors.  Indeed, it basically is nothing more than a shell *around* ask + forward, providing a higher-level abstraction...

Patrik Nordwall

unread,
Aug 5, 2015, 5:15:19 PM8/5/15
to akka...@googlegroups.com
Thanks for sharing, Justin! I have not tried it but what you describe here looks great to me. Looking forward to adding this to http://akka.io/community/

Cheers,
Patrik

Patrik Nordwall
Typesafe Reactive apps on the JVM
Twitter: @patriknw

Reply all
Reply to author
Forward
0 new messages