by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Matt Joiner
    @anacrolix
    Adriaan Prinsloo
    @AdriaanPrinsloo
    Hi, I'm new to Riker, and i's trying to use it to implement a ZMQ service, one that both received Request/Response commands and one the can subscribe to ZMQ pub/sub channels. The intention is to handle both of these scenarios with Riker actor implementations. I've had a look around, but I can't find an example of such a service. At the moment i'm just looping on the socket.recv and ask() ing specific actor references for a response, and for pub/sub I'm endlessly passing a Listen message, that blocks and listens the subscription channel in the actor implementation. Both of these approaches feel a bit clunky. Does anybody know of an example implementation of something like that I can look at?
    Lee Smith
    @leenozara

    @AdriaanPrinsloo

    There's two main approaches. The first I would recommend would be to handle your ZMQ IO separately from Riker. You could use Tokio for this or any other IO optimized implementation. When you receive your Request 0mq message you can offload the processing of that to Riker by sending to the respective actor. Your ZMQ queue can continue to handle other Requests. The actor handling the message can choose to send a Response. Typically you could either send a ZMQ reference along with your original message, or you could include such a reference when you create/start the actor. You end up with two "reams", ZMQ and Riker, and no blocking would be necessary.

    The other approach would be to handle the ZMQ orchestration and IO inside of Riker. To do this in a non-blocking manner you'd typically use an actor that contains the ZMQ socket and instead of blocking, schedule a message (Check, or Tick, for example) 50ms at the end of recv to be send to myself. Every Tick you check if the ZMQ socket has data and if so get the message. A simple implementation is easy, but if you want to handle a lot of IO then there are patterns you can use to optimize this. The only time you want that Tick message scheduled is when there is no more ZQM messages.

    Ideally, you don't ever want to block. Also note that Ask is a future and will require you to block (await) to get the result to the current thread - therefore it's better suited to futures composition where you have a chain of futures working to completion.

    I'd love to hear more as you progress. ZMQ and nmq are excellent.
    Adriaan Prinsloo
    @AdriaanPrinsloo
    @leenozara thanks so much for your guidance! I'll post an implementation if i manage to do something elegant.
    Mina Galić (deprecated: Igor Galić)
    @igalic
    @leenozara can i have some of that wisdom :arrow_heading_up: in this issue too riker-rs/riker#103 ?
    Daniel Olano
    @olanod
    Hi! I was trying to do a future (tokio::)select! inside a ctx.run(async move {}) that would wait for some futures including a tokio::delay_for ... of course it wasn't going to just work 😆 I realized Riker comes with its own non tokio executor and I would have to find a way to do my delay future. But made me wonder about how hard it would be for Riker to not spawn futures on its own and like async libraries should do nowadays give the use the choice of what executor to use. Going beyond that probably would be more interesting to have the system better integrated with the whole async/await story, right now it doesn't feel so smooth, a bit like a forced add-on 🤔 it would be cool if all components are future based and the actor system be one big future that is awaited on the main function.
    Lee Smith
    @leenozara

    This is a very good point you bring up. Riker isn't using it's own executor, it's using futures::executor::ThreadPool from Futures crate. However, it is using its own instance of the Threadpool executor and futures in a futures chain can't run across different instances. There's also the issue of different versions and implementations of executors. I imagine a way to make Riker (and other application components) share the same executor would be to pass a reference to the executor. In Riker's case, this could be done using:

    let sys = SystemBuilder::new()
                            .name("my-app")
                            .executor(exec.clone()) // <-- pass the executor reference
                            .create()
                            .unwrap();

    This of course would depend on other libraries allowing for something similar, or getting a reference from a default executor. There wasn't a standard practice for this last time I looked, but that might have changed recently. In any case, I think this is a priority. Appreciate you raising this point.

    Adriaan Prinsloo
    @AdriaanPrinsloo

    Hi team, I'm attempting to understand how i can use a BasicActorRef to send one of the Receive implemented messages to. I've modified the messaging.rs example application to illustrate my dilemma: ```
    fn main() {
    let sys = ActorSystem::new().unwrap();

    let actor = sys.actor_of_args::<Counter, _>("counter", 0).unwrap();
    
    actor.tell(Add, None);
    
    let basic_actor_ref : BasicActorRef = actor.clone().into();
    
    match basic_actor_ref.try_tell(Add, None) {
        Ok(_) => println!("Success"),
        Err(_) => println!("Failure")
    }
    
    sys.print_tree();
    // force main to wait before exiting program
    std::thread::sleep(Duration::from_millis(500));

    }
    ```

    I get failure, even though the actor supports the Add message. Am I missing something obvious?
    Steve Biedermann
    @hardliner66

    The actor proc macro creates an internal enum with values for each given type.

    #[actor(Add, Sub, Print)]
    struct Counter {
        count: u32,
    }

    creates the following type:

    enum CounterMsg {
      Add(Add),
      Sub(Sub),
      Print(Print),
    }

    This is the type that is supported by the actor. If you use a typed actor reference you can use Add directly, because the macro implements Into<Counter> for the type, and because the type is known, into() works how it should.

    If you use a BasicActorRef, the conversion doesn't happen. In this case riker fails to enqueue the message.

    In order to use the BasicActorRef you have to use the full type:
        match basic_actor_ref.try_tell(CounterMsg::Add(Add), None) {
            Ok(_) => println!("Success"),
            Err(_) => println!("Failure"),
        }
    Mina Galić (deprecated: Igor Galić)
    @igalic
    https://riker.rs/actors/ link here on the bottom leads to: https://riker.rs/actors/messaging which is wrong, it needs to point to: https://riker.rs/messaging/
    oh, they are all wrong.
    i should submit a PR to fix that.
    Mina Galić (deprecated: Igor Galić)
    @igalic
    oh, and the website repo also needs .gitattributes
    Mina Galić (deprecated: Igor Galić)
    @igalic
    Mina Galić (deprecated: Igor Galić)
    @igalic
    maybe this advanced messaging page is where we could learn how to pass arguments to messages… so that Add would not only add 1, but, whatever we tell it to, maybe even 3!
    Daniel Olano
    @olanod
    Hi! I'm practicing Riker trying to create an event sourcing abstraction, and got a bit blocked trying to decide how to run a future inside a recv function https://github.com/olanod/riker-es/blob/cqrs/src/entity.rs#L61 I thought ctx.run would run the future already but seems it doesn't and so far the only way I see is doing block_on but I run into the error cannot executeLocalPoolexecutor from within another executor I guess block_on is not meant to be run inside recv? is it because of my #[tokio::test]?
    Mina Galić (deprecated: Igor Galić)
    @igalic
    @olanod a potential solution to your problem might be found here in the documentation: https://riker.rs/futures/
    Tom Burdick
    @bfrog
    Is there a simple way to get Riker to log when actors are started/stopped/etc, much like the erlang supervisor progress
    I see that when that stuff happens there's the sys_event channel, would subscribing to that get me what I want?
    Tom Burdick
    @bfrog
    I got it!
    Daniel Olano
    @olanod
    Thanks @igalic but not sure how the info in the docs can help me more, doesn't say much other than mentioning ctx.run exists to run futures :/ has anyone working examples of a futures used inside a the recv function? :)
    Mina Galić (deprecated: Igor Galić)
    @igalic
    @bfrog wanna share how you did it?
    riker-rs/website#46 / riker-rs/website#47 ← fixes example on website to compile.
    Mina Galić (deprecated: Igor Galić)
    @igalic
    can somebody explain where ctx comes from, here: https://riker.rs/channels/ https://riker.rs/selection/ ?
    Mina Galić (deprecated: Igor Galić)
    @igalic

    The ActorSystem is the heart of a Riker application, starting several threads when it is created. Create only one instance of ActorSystem per application.

    so, if i create the ActorSystem in main(), how do i access it in a different part of the application?

    do i have to share a ref? or can i get that somehow "by-name"?
    Lee Smith
    @leenozara
    ctx is passed as a parameter to trait methods of Actor, e.g. recv.
    system can be accessed from context using ctx.system
    Mina Galić (deprecated: Igor Galić)
    @igalic
    @leenozara so if i understand you correctly, if i start the ActorSystem in main() there's no way to get an ActorRef in some disparate part of my application, other than passing an actor or a system, or a reference to those, into that part of the application
    Lee Smith
    @leenozara
    that's right. You need some Riker type to interact with the Riker API. This can be ActorSystem, ActorRef, BasicActorRef.
    within the actor system you have access to any actor references that you provide through endowment and introduction, etc. You also can walk up and down the hierarchy by accessing parents and chilkdren.
    There's also .select on Context and System, which is helpful for interacting with actors through system messages and in some cases user-level messages.
    outside of the actor system you don't have Context, but you are free to pass ActorRef, ActorSystem, etc if you have parts of an application that are not an actor themselves
    Lee Smith
    @leenozara
    I'm not sure if that answers your question exactly. I'm be happy to help in more detail if you can describe your application and what you had in mind.
    Mina Galić (deprecated: Igor Galić)
    @igalic
    so yes, i would like to have a part of the application, which is not in the actor system, send a message to an actor to do jobs
    the reason to do so, is to decouple all the data that we're currently passing around, which, in my youthful zeal, i have, wrongly bundled into a single struct
    there's a database connection, a worker mutex, and a search index ref. (among others
    Mina Galić (deprecated: Igor Galić)
    @igalic
    my thought was that Searcher would lend itself to easily extract into an actor, but it is, itself deeply bundled with two other datastructures, one of them, the post struct, and the other the database connection, because the post struct doesn't hold all data, that Searcher stores about a page
    but, if the Sender isn't part of the ActorSystem i need to pass around a ref, just like with the database connection, and, in my naïvité, i thought i could avoid that, but knowing the actor's name
    Mina Galić (deprecated: Igor Galić)
    @igalic
    on the other hand, i would still be able to talk to three different Actors (broadcast actor, Searcher actor, mail actor) they just one sys ref, instead of three different ones! so that's still a big win
    and that's just the three actors I've identified so far
    i haven't looked into how we compute notifications yes, cuz i was afraid of what I'd find, lol
    Mina Galić (deprecated: Igor Galić)
    @igalic
    I'm really glad i don't have that much time to write code, it leaves much more time for thinking
    Terrence Drozdowski
    @tdrozdowski
    Have a quick question - when you are using channels - are you restricted to using tell with them? Or can you use ask as well?
    Daniel Olano
    @olanod
    Hi all! looking for some inspiration :) ... I'm trying to store references to different kinds of entities in a HashMap, since I can not put different ActorRef together because they are generic over the message type I figured I can do a HashMap of BasicActorRef but I'd like to go back to ActorRef from BasicActorRef later on, is it possible? I see there is a typed function but needs an ExtendedCell as parameter, no idea where to get that, looks like an internal type
    Georg Aigner
    @basalt79
    hi, are there any examples for riker create http rest endpoints and expose them via http