Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Songtronix
    @Songtronix
    @rustrust I know that riker does not have a webserver. It's an actor system of course :D I just want to integrate one neatly into riker to serve the usecase I described.
    Kelly Thomas Kline
    @kellytk
    I've had a thought that I'd appreciate [+/-] feedback on: The actor model is a hack to handle concurrency that becomes obsolete with proper tools to address concurrency's issues such as async/await and other language and ecosystem synchronization features.
    Arthur Rand
    @ArtRand
    @kellytk I think you could probably make the argument that anything you implement with the actor model, can be implemented without the actor model. However, that's not really the point of the actor model (to enable something that couldn't be done before), right? It's about framing programs within a paradigm that makes certain guarantees (and sacrifices) that draw bounds around how the program will be reasoned about. Practically speaking, I think if you need encapsulation of mutable state, asynchronous processing of tasks, and, importantly, ordered processing of tasks - I bet you'd be hard pressed to find another way to model programs without more dramatic trade-offs.
    Kelly Thomas Kline
    @kellytk
    Fair points @ArtRand. If nothing else I agree from a 'sum is greater than its parts' perspective but I'm unconvinced. I'd be interested to see actor-style supervision hierarchies, ('self-healing') first-class, generalized and ordered communication (messages) between [local/remote] actors, and eventual-consitency state (eg., raft) as separate Future-based crates which do not assume an actor model. What do you think?
    Lee Smith
    @leenozara

    @kellytk raises a point that other's have thought about several times. My view is this:

    • Actors in the traditional Hewitt sense have been used as concurrency primitives. That is, concurrent programming used actors as the building blocks for concurrency. We see languages like Erlang use this model.
    • Actors in the state + behavior sense are used to represent objects and how those objects should behave/flow. Actors are used for this because there are message guarantees that make working with concurrent changes easy to reason about. Languages like Scala use this model.

    Really what needs to be considered is not just the actor model but actor model on a specific language. For Rust, actors are not concurrency primitives. Futures and Streams are concurrency primitives in Rust. Riker and other actor crates in Rust should not be used for IO, since for IO you want to use lower level concurrency primitives.

    Actors in Rust allow us to build highly complex, concurrent systems that work with state and changing behavior. This often works well in combination with concurrency primitives (Futures and Streams), where you use streams to work with bytes to build meaningful data that is then offloaded to actors to do their thing based on the current behavior.

    This is how I approach concurrency in a Rust project:

    • IO: use Futures/Streams directly for smaller parts. Use Tokio if I really have complex IO.
    • Computation: use Rayon.
    • State: use Riker
    • Coordination/orchestration: use Riker

    Examples of 'state' in ecommerce could be an online payment or a shipping item. In computer vision is could be an object that is being tracked. In coordinating IO it could be to monitor sessions. State could exist less than a second, or it could be perpetual and use persistence. Ultimately, actors allow this: State is currently X and I receive message Y, what should happen. It allows us to do this regardless of concurrency.

    @ArtRand has summarized this concisely above where he emphasized "and ordered processing of tasks".

    We have a lot of Erlang programmers in the Rust community and it's natural for folks to see Rust Async/Await (i.e. futures) as a competing concurrency model to Rust Actors, since in Erlang actors are the concurrency primitive. But in Rust they are not comparable and they solve different problems. Actors in Rust are simply a layer on top of Futures to provide futures with ordered processing, messaging, easy state and behavior.

    Kelly Thomas Kline
    @kellytk
    Thanks for the detailed response @leenozara
    Kelly Thomas Kline
    @kellytk
    If the actor model is not optimal for IO does that mean high-load servers shouldn't be written with it?
    Lee Smith
    @leenozara
    For Rust the actor model isn't optimal for IO. So I don't think high- or low-load servers should be written to use Riker or any other actor framework for IO. Performance wise it doesn't make sense but also API. Rust has pretty good IO apis for concurrent IO through Future and Stream. With those you get combinators such as Map, Flatten, and others to manipulate a stream of bytes in a functional way and at what is often called zero cost. Http, TCP based servers should use those solutions in Rust.
    Riker isn't slow by any means and it will get even more optimized. For example, you could use Tokio and Stream to marshal bytes into a data type (object) and send that as a message to an actor. It will scale very well
    Lee Smith
    @leenozara
    Riker in most cases isn't a great fit for building other crates. It's better suited for building end solutions, for being the fabric to glue all the pieces together for that. It works really well in this use case. It's a generalization, there are cases where for complex libraries and crates you want to use Riker, but in general it's a little too high level for it
    Kelly Thomas Kline
    @kellytk
    Noted with thanks
    Kelly Thomas Kline
    @kellytk
    @leenozara I think it could be that for IO-bound servers expected to scale to multiple machines, the performance loss inherent in the actor model [with Rust] could be close enough and offset by the management/inter-machine scaling capabilities it implies. If that's true it becomes more feasible to 'throw hardware at it' for scale
    BTW I'm glad you're thinking of intensive computation->Rayon. Have you thought much about the organization of code, such as my personal favorite 'FRP', of which https://github.com/Pauan/rust-signals/ is an interesting implementation
    I suspect there's a valuable assembly of these various things together functioning both on the server and in a WASM/WASI environment among others
    Arthur Rand
    @ArtRand

    @leenozara @kellytk Thanks for fostering this productive conversation! You both bring up some interesting points.

    actor model isn't optimal for IO

    I interpret this to imply the use case where an application essentially takes tasks (or requests) and performs logic/IO with them largely independently. This is the classic use case for Go. Basically what you're doing is taking the difficulty of handling concurrency and pushing it down a layer (usually the DB). I agree that actors aren't really necessary for this case. You just want an ergonomic way to logic that appears synchronous without sacrificing performance (and ideally algebraic correctness).

    OTOH, if the requests change the state of your application, e.g. you're implementing the database, then actors seem like a natural fit for the reasons elaborated here. I would be interested to know what the bounds of the performance costs are here.

    Riker in most cases isn't a great fit for building other crates.

    I'm surprised to hear this. I've been drafting up a plan to implement Kafka streams-like API on top of RIker or Actix (pluggable back end maybe?). I think there is potential to use actors to build APIs where you can abstract the complexity of handling concurrency. Ideally, the user of the API doesn't need to know anything about actors! I like this idea a lot, and would be happy to collaborate. With FWs like Actix and Riker becoming mature, with Tonic coming out, 1.39 coming soon, a good opportunity to make (to use a buzz word) reactive apps with all the advantages of Rust is coming soon.

    Kelly Thomas Kline
    @kellytk
    Helpful point re: independence of request/response factoring into qualifying the actor model as optimal or not. What's Tonic? What you suggest re: Kafka streams and generally is something I've proposed here several times myself. Actors that implement many standard and user-defined protocols making the extension of actor systems easy without compromising on encapsulation
    The pluggable actor framework backend is interesting. Just as there's a common Service trait that the Tower project is promoting there could be a similar suite of common traits for actor framework
    Then the various actor frameworks could compete on implementing the runtime for code which would be [totally] portable
    Kelly Thomas Kline
    @kellytk
    Are any of the points at https://github.com/rsimmonsjr/axiom#design-principals-of-axiom improvements over Riker?
    Kelly Thomas Kline
    @kellytk
    A comment on these topics by the author of and at https://github.com/Pauan/rust-signals/issues/11#issuecomment-541528315 may be of interest
    Samir Halilčević
    @riemass
    I really like the talks given by Joe Armstrong.
    Arthur Rand
    @ArtRand
    Tonic (https://docs.rs/tonic/0.1.0-alpha.3/tonic/) is the "new" gRPC framework. IMO an ergonomic gRPC is crucial for industry adoption, and it's awesome to see one coming out. As far as this framework vs. that, I say let the best API win. The best part about rewriting is getting the benefit of hindsight, I think Riker is looking very good. I use Actix for work (I chose it before Riker existed, and I would still choose it because it's more mature). I think both have 8/10 APIs with their own trade offs. Would you be interested in collaborating on a Kafka Streams lib? I could start a design doc.
    Samir Halilčević
    @riemass
    @leenozara can you please take a look at my MR: riker-rs/riker#42 .
    fstuess
    @fstuess
    Hi there, any bigger real-world examples of using riker out there? thanks!
    Kelly Thomas Kline
    @kellytk
    Is Riker development going to resume?
    Nhi Tran
    @zentechnhitran
    image.png
    Hi there, I have an error when I try to implement "Actor selection" of Riker.
    Receive<T> can't receive any msg when I use try_tell. Please help me !
    I think, I use try_tell
    impl Receive<String> will log msg
    fstuess
    @fstuess
    @zentechnhitran can you show a complete example of your code and the error shown?
    Nhi Tran
    @zentechnhitran
    yep, thank @fstuess
    this is my project, can you review it here .
    https://github.com/zentechnhitran/nats_riker
    I put it /src/bin
    cargo run --bin natsactormanger
    fstuess
    @fstuess
    @zentechnhitran So what is your problem exactly? if i put back in main() my_actor.tell("hello".to_string(), None); then [natsactormanager] received msg: hello is printed. Btw do you use clippy? And in the Cargo.toml dependencies only riker and log are necessary ;)
    fstuess
    @fstuess
    What is the reason/advantage to use multiple structs as messages over using enum? Can anyone elaborate? thank you.
    Nhi Tran
    @zentechnhitran
    yep @fstuess
    image.png
    my issues: I use hga.try_tell("I've arrived safely".to_string(), None);
    but I don't see log printed
    Can you see that
    https://riker.rs/messaging/
    Riker suggests using Multi-type Messaging
    By utilizing Receive<T> and #[actor], complex message handling can be defined clearly and concisely
    If I use matching with if everything is ok
    Nhi Tran
    @zentechnhitran
    Btw do you use clippy?
    I use vim editor, I install plug Clippy into vim.
    And in the Cargo.toml dependencies only riker and log are necessary
    I created config/riker.toml allow Riker print log :))
    fstuess
    @fstuess
    @zentechnhitran yes i read that about messaging. But i cannot see, why enums are not concise or clear.
    fstuess
    @fstuess
    @zentechnhitran i do not see log printed either and don't understand why. Will look into it tomorrow. interesting..
    fstuess
    @fstuess
    @zentechnhitran for what i see the symptom is in actor/selection.rs, line 97:
    let _ = child.try_tell(msg.clone(), sender.clone());
    yields Err(()) and is silently ignored. If you have an ìnfo!{ block instead of let _ = then you see Err(()).
    We have to find out where this error comes from. Unfortunately, it is a stack of Result<(),()> so no error information given. Will dig in
    fstuess
    @fstuess
    At the first glance, i don't get how the message is dispatched down the stack all the way to channels. Trying to understand.
    fstuess
    @fstuess
    I boiled it down to lib.rs lines 78ff, function pub fn take<T>... in branch if self.one_time { match self.msg.take() { Some(m) => { if m.is::<T>() { Ok(*m.downcast::<T>().unwrap()) } else { Err(()) } } None => Err(()), }
    yields Err(()). But i have no clue what is going on here, haha ;)
    Type <T> is unit (), but isn't supposed to be String?? I don't get it so far.
    Nhi Tran
    @zentechnhitran
    sure @fstuess , I think we must read source code of riker
    https://docs.rs/riker/0.3.2/riker/
    I have another method for this, I will push code, can you help me review code, thank @fstuess .
    fstuess
    @fstuess
    I do not know if i will be of help, since i am a rust beginner and wanted to use riker to set up some kind of event sourced application. Did you see what i meant with the unit error Err(())? I think the master is 0.3.2, isn't it?
    just tell when you updated your repo.
    Nhi Tran
    @zentechnhitran
    yep, I will tell you when I update my repo. I use Riker to manage NATs.