While far from perfect, one thing that I do is strictly following the convention that the only objects a specific actor will process are defined within that actor's companion object.
I also refrain from directly importing those objects/classes anywhere so I always have to write out actor.message when sending it. I find that actually helps a lot.
--
>>>>>>>>>> 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.
Hi Derek.Yes, I'm aware of the tradeoffs and the reasons for them. It just seems to me there ought to be a middle road.Here's an idea off the top of my head. If remoting is going to be transparent, there won't be compile time type assurance. So let's give up on local type assurance too, and just use types for documentation and refactoring; that still seems a lot better than nothing.Suppose for each actor I wanted to implement, I declare a trait with a method for each message it might receive. Each method must receive exactly one parameter, which is the message, and return Unit:trait Printer {def print(msg: String): Unit}The method name 'print' is just for documentation; only the parameter is sent as the message. This preserves transparency with the actor model; you don't rely on the trait implementation to build the actual message.The user of an ActorRef would use a wrapper (value type around the ActorRef) generated by a macro to implement this trait. The macro would also validate the trait: each method has one argument, returns Unit, and all argument types are distinct. Each method call would be implemented as a send().val actor : ActorRef = ???val typedActor: Printer = mymacro.wrap[Printer](actor) // Or is there a way to declare types with macros? I forget.typedActor.print("my message")The macro would add an (implicit sender: ActorRef) argument to each method.The actor itself would extend the Printer trait and implement its methods. Another macro would concatenate them to implement receive:class PrinterActor extends Actor with Printer with TypedActorMacro[Printer] {def print(msg: String):}To use become/unbecome, we could introduce something more complicated. Or, even, use the Printer trait only on the sender side - it would still be useful. This is just a rough outline. Do you think it might be useful, or do you think I shouldn't go down this road and trying to marry akka actors and (actor) types is a futile endeavour?
You received this message because you are subscribed to a topic in the Google Groups "Akka User List" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/akka-user/rLKk7-D_jHQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to akka-user+...@googlegroups.com.
Endre, i don't think this is related to distributed computations at all.
Any method call can fail even locally.
The way to represent that is with sum types e.g. Either.
Hi Aleh,On Sun, Mar 9, 2014 at 6:56 PM, OlegYch <oleg...@gmail.com> wrote:
Endre, i don't think this is related to distributed computations at all.
Any method call can fail even locally.This is true of course, but way more relevant in distributed cases where failures are orders of magnitudes more common.
The way to represent that is with sum types e.g. Either.Won't work. Either supposes that you received a reply (even if it is a failure notification). No replies are guaranteed in general (distributed) settings.
BTW: almost all Future combinators are not concurrent (as in nondeterministic), Futures are therefore very useful for modeling parallelism without the concurrency pain. I invite you to scrutinize the scala.concurrent.Future API for non-determinism and then see for yourself how that is reflected in the types.
--
receive is a method that returns a PartialFunction. PartialFunctions don't take 2 params and you don't want to allocate/box a Tuple2 for each receive.
Yes, allocating millions of PFs per second is expensive.
On Mon, Mar 10, 2014 at 9:11 AM, Roland Kuhn <goo...@rkuhn.info> wrote:
BTW: almost all Future combinators are not concurrent (as in nondeterministic), Futures are therefore very useful for modeling parallelism without the concurrency pain. I invite you to scrutinize the scala.concurrent.Future API for non-determinism and then see for yourself how that is reflected in the types.
Stating the obvious for Dr. Roland Kuhn :-), but in my opinion the difference between a Future[T] and an ActorRef is that actors are too low-level and general, whereas Future[T] is very specialized - the Future combinators simply assume that Future is a container for a Try[T] result that will be available either now or in the future, the actual moment being of no consequence for the combinators that simply guide you through the happy path.
The problem with Future[T] is that it can't be applied for example on problems where streams and/or bi-directional communications are involved. An ActorRef can provide an awesome implementation for Future[T] instances. However, between an ActorRef and a Future[T], there is a need for abstractions in-between.
I know there are already patterns and best practices for designing stuff with actors, but whenever I work with actors, somehow I always end up with fragile and tightly-coupled designs, precisely because I had to deal with low-level stuff. E.g. actor A sends a message to actor B, but actor B could crash, so now you're thinking of using an external queue
that persists messages for actor B's return. But once that external queue is operational, now you're thinking of redundancy for actor B, so you actually want actors B1 and B2, but because you designed actor B as statefull, now you're thinking in terms of primary / backup nodes
and maybe you want those messages to not be pulled out of that queue unless they were processed in a reasonable amount of time by the primary actor, or otherwise have a backup that takes over that responsibility. Or maybe you have stateless B actors, so round-robin dispatching is not a problem, yet the message processing itself is long and could crash, so maybe you want to try again later with another actor in case it didn't finish in a reasonable amount of time.
Then you realize that actor A should maybe send the same or different messages to different actors, but then you realize that this is actually tight coupling
and you actually want a channel on which actors could subscribe for the messages they are interested in. Or maybe you want your cluster to scale depending on the load, so you want to create actors dynamically depending on runtime stats, yet this is a far cry from bringing up HTTP servers dynamically in an AWS ELB environment, because it's more generic and those docs give me the creeps.
Somewhere in that process, my head explodes, especially given that I haven't solved the first problem I always have, which is good future-proof design, because actors don't guide your implementation at all and many times it's totally non-obvious of what to do.
Kudos on debating the deprecation of "sender". That's a step in making that interface more solid. I also await eagerly on your Reactive Streams - I do feel the need for an Rx streams implementation that also does back-pressure.
--
>>>>>>>>>> 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.
Futures very cleanly model local dataflow. Actors very cleanly model distribution and concurrency. My guess is that if you try to create an abstraction in-between then it will have the disadvantages of both and the advantages of neither.
On Thu, Mar 13, 2014 at 11:27 PM, Roland Kuhn <goo...@rkuhn.info> wrote:
Futures very cleanly model local dataflow. Actors very cleanly model distribution and concurrency. My guess is that if you try to create an abstraction in-between then it will have the disadvantages of both and the advantages of neither.
I think that's right, and I'm starting to think it might help to have a cleaner way of combining futures with actors. (At least it would help me, if not others.)
In one direction, I sometimes want an actor not to process any further messages until a Future completes. This is because a message caused the actor to do something implemented in a Future-based library and I want to serialize operations against that library, as if it were an internal implementation detail of the actor.I could become an actor that stashes all messages until a continuation of the future sends me another message. But that requires a special mailbox and the actor actually reacts to each message. I don't know if there are any performance concerns here, but it would look cleaner if the actor could logically return a Future from receive and the dispatcher would understand that.
In the other direction, we have the ask pattern with its known shortcomings (can't receive more than one message, creating an actor per message can be expensive). It would be nice to send the actor a message + a promise it can complete, but with support for transparent remoting, perhaps falling back to the ask pattern's implementation in the remote case. (I'm assuming here that, for local message sends, creating a Promise is significantly cheaper than creating an Actor that will only ever receive one message. I may be wrong.)
Maybe the correct answer is it really isn't important enough to optimize and I should just use stash and pattern.ask everywhere. What do you think?
--
>>>>>>>>>> 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.
The idea with actors is that they shall remain responsive whenever possible. Another way to look at it is that the internal queue (or stash) should be limited, and when it overflows you might want to send a negative reply right away. For that the actor needs to be runnable while the Future executes.