Readit News logoReadit News
dmm · 6 years ago
The naming is a little confusing here. This is Actix the actor model library, not "Actix web" the web framework that's usually discussed.

Originally "Actix web" depended on Actix the actor library, but no longer. Though they can be used together. And I think websockets still require actors?

I'm using both Actix and Actix web for a personal project. I like it a lot and think the actor model is good fit for applications that don't fit well into a request lifecycle.

My main pain point with it is the use of futures. Right now it's a huge pain to have more than one return value in an Actor Handler, the functions that handle actor messages. Even if you box the returned Future, you end up having to use futures::Either a bunch and when you mess it up you get tons of confusing errors filled with the huge inferred types.

Implementing something like:

  if (condition1) {
    return <future for service call1>;
  } else if (condition2) {
    return <future for service call2>;
  } else {
    return <no-op future>;
  }
Is a big pain requiring two layers of future::Either. Or I just don't know what I'm doing, which is very possible.

async/await would be a huge improvement, but can't be used at the moment, even though the current version of Actix uses std::future's.

aphexairlines · 6 years ago
Can't you use async/await with the compat libraries for futures and for tokio?

https://tokio.rs/blog/2019-12-compat/

kevinmgranger · 6 years ago
> Even if you box the returned Future, you end up having to use futures::Either a bunch

That's really strange. A Boxed future is the end-all-be-all of not caring about the underlying type. Would you mind sharing a snippet of code that shows where you need both a Boxed future and Either?

dmm · 6 years ago
You're probably right, I must be missing something. I'm also still on futures 0.1 because I'm still porting it to std::futures.

Here's an example of what I was discussing:

https://github.com/dmm/exopticon/blob/c40d14c80c150ef6270732...

The idea is that I want to implement a relative ptz move on a camera but some cameras have a broken relative move implementation so in that case we instead use a continuous move + a delay + a continuous stop. The final case is when a camera has no ptz it returns Http::NotFound.

shawnz · 6 years ago
What is the difference between the actor model and object oriented programming? It seems to me like they are basically the same paradigm but with all the names changed, and some additional restrictions like all messages being async and objects only being able to process one message at a time. Why is it necessary to create a whole new paradigm just to enforce such a style?
edejong · 6 years ago
Your question is interesting from the perspective that the actor model could be seen as the precursor to modern object oriented programming. Both the actor model as defined by Carl Hewitt and the early object computational models as they are defined by Alan Kay (Smalltalk) originated during the same period and are based on similar philosophies of computation.

However, on the object oriented model track, due to practical reasons, its definition descended into a single-thread dispatch system with full message delivery guarantees. Locality was dropped (due to singletons) and the distributed model was not maintained. Method dispatch systems were later added, but could be considered a kludge. This also explains the mismatch between remote systems calls (SOAP, REST, etc.) and the internal language. Ideally, these would be the same.

With our modern systems design constraints, especially given distributed systems, we need to revisit those early decisions. The Actor model is a good blueprint for our designs. It is fundamentally decentralized, locality is enforced and at-most-once message delivery is assumed. These allow us to design and implement distributed algorithms which would be hard to implement using traditional OOP methods.

dkn · 6 years ago
I think this is a great summary, and also highlights much of what Joe Armstrong talked about when comparing Erlang to other OO languages, and his earlier decisions to design Erlang to work in the same way whether in a single-node or multi-node environment.
sakian · 6 years ago
Aren't they connected by the idea of active objects? https://en.wikipedia.org/wiki/Active_object
Ari_Ugwu · 6 years ago
Thanks a lot for this quick summary. Computer science can be such a semantic jungle.
wwweston · 6 years ago
If I'm only following about half of what you're saying (I'm familiar with Smalltalk and the OO model, I don't know what the actor model is, I don't know what "locality" means), what's a good place for me to start?
dragonsh · 6 years ago
OOP and Actor model followed parallel paths of evolution: the Actor Model was created by Carl Hewitt based on the message passing semantics of Smalltalk. Alan Kay, in turn had based the message passing semantics of Smalltalk on the goal-driven evaluation of PLANNER, which was designed by Carl Hewitt.

PLANNER was the precursor to Prolog. Erlang a language based on actor model where processes are actor was originally not intended to be a language, rather it started out as a library for fault-tolerant distributed programming in Prolog, and later evolved into a dialect of Prolog, before it became its own language, still to this day heavily influenced by Prolog.

So, the similarities between Objects in OO, and Actors in the Actor Model are far from coincidental.

Isn0gud · 6 years ago
In the Actor model, all function calls are async and have no return value, between the Actors. Each Actor is single threaded (OOP) program. It provides a nice approach to deal with parallel programming.

Object oriented programming is a language feature while the Actor paradigm can be build on top of OOP to ease the mental burden of parallel programming.

dnautics · 6 years ago
Actually I think building oop on top of actor model makes the mental model far easier. Instead of worrying if the knight object uses the sword object to hurt the monster obect then which object .deals_damage? Or should the object take_damage? The actor framework, being all message passing, makes these choices clear. True, originally oop was message passing, but no mainstream modern oop languages except Ruby sorta are message passing frameworks.
microtonal · 6 years ago
In the Actor model, all function calls are async and have no return value, between the Actors. Each Actor is single threaded (OOP) program. It provides a nice approach to deal with parallel programming.

I guess you mean 'concurrent programming', right? I haven't seen actors used a lot for parallelism.

ahasani · 6 years ago
If you mean by return value like function call, actor actually can send reply message back to the caller provided the called actor knows the caller address
anthony_doan · 6 years ago
It's a nice approach to concurrency.

It doesn't guarantee parallelization. Concurrency is a precursor and a requirement for parallelization but it doesn't guarantee it.

jlouis · 6 years ago
I think the key point is that most actor models, at least the ones I know, are truly concurrent with preemption, whereas most models based on OO are sequential. There is only one thread of execution in the OO program, whereas there is no notion of this in an actor system. All processes execute at the same time, so to speak.

There are also some points with the messaging being truly asynchronous, so you can't rely on the order in which messages arrive, usually subject to certain constraints. Erlang, for instance, require that between any two pairs of processes, order is preserved in the messages.

Also, creating a new actor creates a new thread of execution inside that actor. This is not the same as creating a new object.

zackmorris · 6 years ago
To me, the biggest difference is that the actor model has no shared memory between classes like with object-oriented programming. I'd actually like to see OO programming where classes are completely isolated, but to my knowledge, that doesn't really exist. Go, Elixir and Erlang come close.

UNIX shell with isolated processes communicating over streams -> Actor model

Pretty much every C-style language with all of their caveats -> Object-oriented model

jerf · 6 years ago
Elixir/Erlang/BEAM, as far as I know, semantically don't just come close, they arrive. I say "semantically" because there are some optimizations for things like large binaries so the system isn't literally copying a lot of them around unnecessarily, but semantically, BEAM processes are isolated from each other entirely.

Go doesn't come close; technically it's just another shared-state programming language. Culturally, it tends to use more sane concurrency features, and the channels are nice and all, but technically there is no isolation between goroutines.

With discipline, you can program Go with an actor mentality and it's fairly effective. I do it all the time, leaning on my years of experience in Erlang and some Haskell, which teaches you how to build systems that work that way. But you do need non-trivial discipline as the language provides rather less help with than I'd like.

ahasani · 6 years ago
Sharing state is what actor model tries to eliminate, it has a very strong locality concept. Singleton in OOP (which you have to implement atomic and thread safety often by yourself) can be easily implemented as an actor. Erlang has gen_server for this exact scenario. About isolation, you can actually impose class isolation in OO languages by declaring all variables as private. Public variable can never happen in actor model
buckminster · 6 years ago
> OO programming where classes are completely isolated

That sounds like COM, especially the Automation subset.

acjohnson55 · 6 years ago
The other replies have covered this pretty well, but the two models are quite similar. The big difference is the formal constraints of the actor model, which allow people to build robust distributed systems. This is because the lack of certainty of communication and architecture is assumed as a first principle. This makes a big difference, in practice, for what programs actually look like.
zamalek · 6 years ago
The way I like to think of it is: actors combine objects (allocated objects, specifically) and threads. You wouldn't really allocate a thread per object, but that's an implementation detail. Message passing etc. all follow from the restrictions that arise due to objects being threads.

The restrictions you talk about are the key advantage of the actor model. OOP is extremely powerful, and nobody seemingly knows how to use that power responsibly. Actors introduce just enough rails to drive you into the pit of success.

Just like Rust imposes restrictions to improve the reliability and security of software, Actors impose restrictions that improve the human comprehension and reasoning of software architecture.

vbezhenar · 6 years ago
You can run every actor in a separate thread or even in a separate machine, making the whole system highly scalable. Whether you'll consider that a new paradigm or not, is question of definitions.
shawnz · 6 years ago
Isn't that basically the same as remote method invocation in OO systems?
eweise · 6 years ago
I haven't looked at this framework but from the one I am familiar with, once you make the calls async, the objects can live anywhere, locally or remote. Also, you may have to assume that messages don't get processed and thus need to handle that case. The upside is that distributing your app becomes a configuration issue instead of a coding one. This is nice because with microservices, the seams need to be decided upfront and its hard to refactor if you get it wrong.
zelly · 6 years ago
OOP is about passing messages through memory. Actors are about passing messages through time.
habitue · 6 years ago
Highly recommend Bastion if you're looking for a Rust Actor library / runtime. It uses async/await etc, and has supervision trees and restart strategies taken straight from Erlang/OTP

https://docs.rs/bastion/0.3.4/bastion/

https://github.com/bastion-rs/bastion

captain_crabs · 6 years ago
would you even suggest this over riker?
habitue · 6 years ago
I haven't used Riker, is it good?
dantodor · 6 years ago
I'm amazed on how much discussion digressed to actix-web. Understandable, seen the latest happenings there, but still... I tried quite a while ago Actix, coming from Erlang/Elixir and Scala/Akka. While the cognitive load of using it was not high, when I started my first test, I noticed one core being maxed out, and all others sleeping, which was kinda unusual for me. I asked why, and the author answered that it uses an event loop, so if you want it otherwise, go away and use something else, like Riker... So I went away :) ... I would assume this kind of behaviour has been corrected meanwhile (I mean the library, not the comms), because otherway, it's just a Node written in Rust. My 2c :)
andrewzah · 6 years ago
Actix (the actor framework) is separate from what people are discussing here: actix-web, which supports actix). In earlier versions of actix-web it was based around actix; I remember implementing actors and handlers. Since 1.0 or so that got changed to more of a standard setup.

I’ll add my 2c on actix-web: in my opinion it tries to do too much. hyper (simply based on tokio) is all you need for a fast async server. Anecdotally, I know many people who basically use just this stack, over actix-web/warp/tower etc.

There are other actor systems, like kay [0].

[0]: https://citybound.github.io/citybound/kay/index.html

xedrac · 6 years ago
I'm currently in the process of removing actix from one of my projects and replacing it with asyc/await and some channels. Actix comes with a ton of dependencies and doesn't buy you a whole lot anymore.
Huycfhct · 6 years ago
Yes. I would imagine Actix being out of favour now. Funny to see it being a rust project shared on hn
slydo · 6 years ago
What is in favor now?
rofrol · 6 years ago
Can you show some example repo with code?
ncmncm · 6 years ago
Can somebody please summarize the outcome of the recent kerfuffle? I don't mind which way it came out, but it seems worth knowing what it was.

I absolutely don't want any even-slightly-inflammatory answer.

_-___________-_ · 6 years ago
This is from memory, I would welcome any corrections.

Actix was written with a lot of unsafe code[0], which some people considered unnecessary and potentially dangerous in a web framework. In some cases the unsafe code may have been performing better than equivalent safe code. In other cases, it was possible to rewrite with safe code without losing performance.

People submitted patches to replace unsafe code with safe code. The maintainer of Actix responded with hostility to some of these patches, and (at least for some of the patches) did not seem to see the reason why people wanted these changes.

Subsequently, a lot of hostility was directed at the maintainer on various public Internet fora.

Ultimately, the maintainer of Actix deleted the repository from GitHub, but then had a change of heart and restored it, with a new maintainer.

[0] unsafe code according to the Rust definition of unsafe: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html

burntsushi · 6 years ago
A small but crucially important clarification: it wasn't just that there was a lot of `unsafe` code, but that some portion of it was unsound.

You can read more about what I mean by unsound in this context here: https://docs.rs/dtolnay/0.0.7/dtolnay/macro._03__soundness_b...

undecisive · 6 years ago
That seems a pretty balanced summary from my understanding of it.

One thing that I think should be noted: a lot has been said about this framing the original developer as unwilling. I'd say an unfair amount - from what I've seen, "cautiousness" would be a better description of his attitude, and hostility seems to have been shown when people blindly wade in ignoring all the discussion.

So for example, back in 2018, here he is publicly mulling it over: https://github.com/actix/actix-web/issues/289#issuecomment-3... and https://github.com/actix/actix-web/issues/289#issuecomment-3...

Here he is actively working to reduce the reliance on unsafe practices: https://github.com/actix/actix-web/issues/289#issuecomment-3...

Here he actively and very concisely points out his actual viewpoint: https://github.com/actix/actix-web/issues/289#issuecomment-3...

... and there are plenty of other examples in this and other tickets. Massive actions were taken by others and himself to significantly reduce the unsafe code where possible, and yet it seems the abuse kept coming.

I'd be interested to hear whether the new maintainer has had similar experiences. Unfortunately, our preferences in software development, often a product of a desire to generalise a specific overreaction, tend to become quasi-religious and puritanical. Members get outcast from their communities for trying to speak sense. I hope that this debacle will cause the community to mature, though I fear many will see it as a win and galvanise their viewpoint. We must remember that silver bullets can kill more than just werewolves.

tinco · 6 years ago
For non-rusties: unsafe means turning off Rust's advanced safety features, reducing its safety level to that of C or C++. Which is to say, it's as safe as almost all software you're using right now. Of course, one usually turns off the safety features because one is trying to do something tricky to squeeze out performance or achieve some low level feat, so it's also an indicator that something is dangerous is going on.

In your C++ you might add a comment explaining the behaviour you're relying on to convince any reader of the correctness of your code. The cool thing about Rust is that anywhere you don't have the unsafe block, you're (theoretically) certain there's no tricky business going on without even having to read the code.

There was a lot of commotion in the community because many rustaceans take a lot of pride in having this safety features. They took offense at disabling those features, risking Rust's reputation of safety, for seemingly meaningless goals (such as winning the TechEmpower benchmarks). It's not disabling the safety features that makes the code faster btw, it's the tricks you're allowed to do when the safety is off that might yield performance improvements.

imtringued · 6 years ago
I do not understand the motivation for deleting the repository. Most maintainers just quit but they don't go out of their way to take down the project when they go.
Dowwie · 6 years ago
Your description is accurate and fair
milgrim · 6 years ago
The project has a new leader now: https://github.com/actix/actix-web/issues/1289
fpgaminer · 6 years ago
I think the other comment is conflating a previous kerfuffle, not the most recent one (the older event was about a criticism of Actix's previously prolific use of unsafe rather than a specific bug). From my recollection of the most recent brouhaha:

Someone found a bug in some unsafe code and created a Github issue about it. The maintainer requested a PoC to show that the issue wasn't theoretical. A PoC was provided. Maintainer agreed it was a bug, but wanted a different solution than the provided pull-request. The maintainer was then harassed by a handful of Reddit/Twitter for various reasons. Maintainer nuked the GH issue. The internet-harassment escalated, so the maintainer deleted the repo.

The outcome is that a few days later the maintainer re-released the repo but assigned a new maintainer and is no longer publicly involved in the project.

ajflores1604 · 6 years ago
I liked this summary https://youtu.be/enLUX1TtNyE
3fe9a03ccd14ca5 · 6 years ago
I’m really excited about this project. Using Akka was one of those things that made distributed/parallel execution just “click”. Particularly useful was being able to draw your architecture the same way one might draw an organization on a whiteboard. Everyone can quickly understand what happens and who is responsible for what.