Please change the title to the original, "Actors: A Model Of Concurrent Computation In Distributed Systems".
I'm not normally a stickler for HN's rule about title preservation, but in this case the "in distributed systems" part is crucial, because IMO the urge to use both the actor model (and its relative, CSP) in non-distributed systems solely in order to achieve concurrency has been a massive boondoggle and a huge dead end. Which is to say, if you're within a single process, what you want is structured concurrency ( https://vorpus.org/blog/notes-on-structured-concurrency-or-g... ), not the unstructured concurrency that is inherent to a distributed system.
I'm working on an rest API server backed by a git repo. Having an actor responsible for all git operations saved me from a lot of trouble as having all git operations serialised freed me from having to prevent concurrent git operations.
Using actors also simplified greatly other parts of the app.
So you're just using actors to limit concurrency? Why not use a mutex?
This might be a question of personal preference.
At the design stage I already find it more approachable to think in separated responsibilities, and it naturally translates to actors.
Thinking about the app, it's much reasier for me to thin "send the message to the actor" than call that function that uses the necessary mutex. With mutexes, I think the separation of concerns is not as strong, and you might end up with a function taking multiples mutexes that might interfere. With the actor model, I feel there is less risk (though I'm sure this would be questioned by seasoned mutex users).
Hmm, you think?
I’m currently engineering a system that uses an actor framework to describe graphs of concurrent processing. We’re going to a lot of trouble to set up a system that can inflate a description into a running pipeline, along with nesting subgraphs inside a given node.
It’s all in-process though, so my ears are perking up at your comment. Would you relax your statement for cases where flexibility is important? E.g. we don’t want to write one particular arrangement of concurrent operations, but rather want to create a meta system that lets us string together arbitrary ones. Would you agree that the actor abstraction becomes useful again for such cases?
> we don’t want to write one particular arrangement of concurrent operations, but rather want to create a meta system that lets us string together arbitrary ones. Would you agree that the actor abstraction becomes useful again for such cases?
Actors are still just too general and uncontrolled, unless you absolutely can't express the thing you want to any other way. Based on your description, have you looked at iterate-style abstractions and/or something like Haskell's Conduit? In my experience those are powerful enough to express anything you want to (including, critically, being able to write a "middle piece of a pipeline" as a reusable value), but still controlled and safe in a way that actor-based systems aren't.
> both the actor model (and its relative, CSP) in non-distributed systems solely in order to achieve concurrency has been a massive boondoggle and a huge dead end.
Why is that so?
Well, lots of people have tried it and spent a lot of money on it and don't seem to have derived any benefit from doing so.
Except Akka in Java and for the entirety of Erlang and its children Elixir and Gleam. You obviously can scale those to multiple systems, but they provide a lot of benefit in local single process scenarios too imo.
Things like data pipelines, and games etc etc.
I've worked on a number of systems that used Akka in a non-distributed way and it was always an overengineered approach that made the system more complex for no benefit.
Fair, I worked a lot on data pipelines and found the actor model worked well in that context. I particularly enjoyed it in the Elixir ecosystem where I was building on top of Broadway[0]
Probably has to do with not fighting the semantics of the language.
Actor model is one of these things that really seduces me on paper, but my only exposure to it was in my consulting career, and that was to help migrate away from it. The use case seemed particularly adapted (integration of a bunch of remote devices with spotty connection), but it was practically a nightmare to debug... which was a problem since it was buggy.
To be fair, the problem was probably that particular implementation, but I'm wondering if there's any successful rollout of that model at any significant scale out there.
I was in a team that built a bigger telco project for machine to machine communication, using akka actors. It was okayish, the only thing that I hated was how the whole pattern spread through the whole code base
I think Microsoft Orleans, Erlang OTP and Scala Play are probably most famous examples in use today.
Orleans is pretty cool! The project has matured nicely over the years (been something like 10 years?) and they have some research papers attached to it if you like reading up on the details. The nuget stats indicate a healthy amount of downloads too, more than one might expect.
One of the single most important things I've done in my career was going down the Actor Model -framework rabbit hole about 8 or 9 years ago, read a bunch of books on the topic, that contained a ton of hidden philosophy, amazing reasoning, conversations about real-time vs eventual consistency, Two-Generals-Problem - just a ton of enriching stuff, ways to think about data flows, the direction of the flow, immutability, event-logged systems and on and on. At the time CQS/CQRS was making heavy waves and everyone tried to implement DDD & Event-based (and/or service busses - tons of nasty queues...) and Actor Model (and F# for that matter) was such clean fresh breath of air from all the Enterprise complexity.
Would highly recommend going this path for anyone with time on their hands, its time well spent. I still call on that knowledge frequently even when doing OOP.
Do any of the books you read on the topic stand out as something you'd recommend?
I was disappointed when MS discontinued Axum, which I found pleasant to use and thought the language based approach was nicer than a library based solution like Orleans.
The Axum language had `domain` types, which could contain one or more `agent` and some state. Agents could have multiple functions and could share domain state, but not access state in other domains directly. The programming model was passing messages between agents over a typed `channel` using directional infix operators, which could also be used to build process pipelines. The channels could contain `schema` types and a state-machine like protocol spec for message ordering.
It didn't have "classes", but Axum files could live in the same projects as regular C# files and call into them. The C# compiler that came with it was modified to introduce an `isolated` keyword for classes, which prevented them from accessing `static` fields, which was key to ensuring state didn't escape the domain.
The software and most of the information was scrubbed from MS own website, but you can find an archived copy of the manual[1]. I still have a copy of the software installer somewhere but I doubt it would work on any recent Windows.
Sadly this project was axed before MS had embraced open source. It would've been nice if they had released the source when the decided to discontinue working on it.
Please change the title to the original, "Actors: A Model Of Concurrent Computation In Distributed Systems".
I'm not normally a stickler for HN's rule about title preservation, but in this case the "in distributed systems" part is crucial, because IMO the urge to use both the actor model (and its relative, CSP) in non-distributed systems solely in order to achieve concurrency has been a massive boondoggle and a huge dead end. Which is to say, if you're within a single process, what you want is structured concurrency ( https://vorpus.org/blog/notes-on-structured-concurrency-or-g... ), not the unstructured concurrency that is inherent to a distributed system.
I'm working on an rest API server backed by a git repo. Having an actor responsible for all git operations saved me from a lot of trouble as having all git operations serialised freed me from having to prevent concurrent git operations.
Using actors also simplified greatly other parts of the app.
So you're just using actors to limit concurrency? Why not use a mutex?
This might be a question of personal preference. At the design stage I already find it more approachable to think in separated responsibilities, and it naturally translates to actors. Thinking about the app, it's much reasier for me to thin "send the message to the actor" than call that function that uses the necessary mutex. With mutexes, I think the separation of concerns is not as strong, and you might end up with a function taking multiples mutexes that might interfere. With the actor model, I feel there is less risk (though I'm sure this would be questioned by seasoned mutex users).
Hmm, you think?
I’m currently engineering a system that uses an actor framework to describe graphs of concurrent processing. We’re going to a lot of trouble to set up a system that can inflate a description into a running pipeline, along with nesting subgraphs inside a given node.
It’s all in-process though, so my ears are perking up at your comment. Would you relax your statement for cases where flexibility is important? E.g. we don’t want to write one particular arrangement of concurrent operations, but rather want to create a meta system that lets us string together arbitrary ones. Would you agree that the actor abstraction becomes useful again for such cases?
> we don’t want to write one particular arrangement of concurrent operations, but rather want to create a meta system that lets us string together arbitrary ones. Would you agree that the actor abstraction becomes useful again for such cases?
Actors are still just too general and uncontrolled, unless you absolutely can't express the thing you want to any other way. Based on your description, have you looked at iterate-style abstractions and/or something like Haskell's Conduit? In my experience those are powerful enough to express anything you want to (including, critically, being able to write a "middle piece of a pipeline" as a reusable value), but still controlled and safe in a way that actor-based systems aren't.
> both the actor model (and its relative, CSP) in non-distributed systems solely in order to achieve concurrency has been a massive boondoggle and a huge dead end.
Why is that so?
Well, lots of people have tried it and spent a lot of money on it and don't seem to have derived any benefit from doing so.
Except Akka in Java and for the entirety of Erlang and its children Elixir and Gleam. You obviously can scale those to multiple systems, but they provide a lot of benefit in local single process scenarios too imo.
Things like data pipelines, and games etc etc.
I've worked on a number of systems that used Akka in a non-distributed way and it was always an overengineered approach that made the system more complex for no benefit.
Fair, I worked a lot on data pipelines and found the actor model worked well in that context. I particularly enjoyed it in the Elixir ecosystem where I was building on top of Broadway[0]
Probably has to do with not fighting the semantics of the language.
[0] https://elixir-broadway.org/
Actor model is one of these things that really seduces me on paper, but my only exposure to it was in my consulting career, and that was to help migrate away from it. The use case seemed particularly adapted (integration of a bunch of remote devices with spotty connection), but it was practically a nightmare to debug... which was a problem since it was buggy.
To be fair, the problem was probably that particular implementation, but I'm wondering if there's any successful rollout of that model at any significant scale out there.
I was in a team that built a bigger telco project for machine to machine communication, using akka actors. It was okayish, the only thing that I hated was how the whole pattern spread through the whole code base
A more legible version: https://dspace.mit.edu/handle/1721.1/6952
https://en.wikipedia.org/wiki/Gul_Agha_(computer_scientist)
The first link returns a 403.
I think Microsoft Orleans, Erlang OTP and Scala Play are probably most famous examples in use today.
Orleans is pretty cool! The project has matured nicely over the years (been something like 10 years?) and they have some research papers attached to it if you like reading up on the details. The nuget stats indicate a healthy amount of downloads too, more than one might expect.
One of the single most important things I've done in my career was going down the Actor Model -framework rabbit hole about 8 or 9 years ago, read a bunch of books on the topic, that contained a ton of hidden philosophy, amazing reasoning, conversations about real-time vs eventual consistency, Two-Generals-Problem - just a ton of enriching stuff, ways to think about data flows, the direction of the flow, immutability, event-logged systems and on and on. At the time CQS/CQRS was making heavy waves and everyone tried to implement DDD & Event-based (and/or service busses - tons of nasty queues...) and Actor Model (and F# for that matter) was such clean fresh breath of air from all the Enterprise complexity.
Would highly recommend going this path for anyone with time on their hands, its time well spent. I still call on that knowledge frequently even when doing OOP.
Do any of the books you read on the topic stand out as something you'd recommend?
I was disappointed when MS discontinued Axum, which I found pleasant to use and thought the language based approach was nicer than a library based solution like Orleans.
The Axum language had `domain` types, which could contain one or more `agent` and some state. Agents could have multiple functions and could share domain state, but not access state in other domains directly. The programming model was passing messages between agents over a typed `channel` using directional infix operators, which could also be used to build process pipelines. The channels could contain `schema` types and a state-machine like protocol spec for message ordering.
It didn't have "classes", but Axum files could live in the same projects as regular C# files and call into them. The C# compiler that came with it was modified to introduce an `isolated` keyword for classes, which prevented them from accessing `static` fields, which was key to ensuring state didn't escape the domain.
The software and most of the information was scrubbed from MS own website, but you can find an archived copy of the manual[1]. I still have a copy of the software installer somewhere but I doubt it would work on any recent Windows.
Sadly this project was axed before MS had embraced open source. It would've been nice if they had released the source when the decided to discontinue working on it.
[1]:https://web.archive.org/web/20110629202213/http://download.m...
I would think Akka in Java world is more famous than orleans
Akka's not open source anymore so people tend to look at similar or competing systems like Scala Play.
Apache Pekko is an open-source fork of Akka from before their licensing changes.
That's probably what they meant by "Scala Play".
May be of interest: Pony Language is designed from the ground up to support the Actor model.
https://www.ponylang.io/
Missing: (1985)