Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actix. #3

Open
uwejan opened this issue Apr 24, 2023 · 4 comments
Open

Actix. #3

uwejan opened this issue Apr 24, 2023 · 4 comments

Comments

@uwejan
Copy link

uwejan commented Apr 24, 2023

Hello there,
I am comming from actix actors background, it is working really good, especially with StreamHandlers, and webscokets, Now the project is growing and needs to put in place some sqlx queries, and that added a ton of issues, as sqlx is async, and self can not move while holding db connection.
I am wondering if this crate would be an easy convert from actix, without lossing much, and gaining async await handle?

Thank you.

@hominee
Copy link
Owner

hominee commented Apr 24, 2023

It is glad to see you here! and I'll summary major difference and make a simple comparison between actix and crossbus, and hope you can get a clue base on these.
both of them are capable of dealing with following data types

Stream waiting/blocking delay message
actix ActorStream or impl StreamHandler ActorWaitItem ActorDelayedMessageItem impl Message or ActorMessageItem
crossbus Streaming or impl Stream Blocker or impl Blocking Delayer or impl Delaying impl Message

theoretically crossbus can do what actix does in a lower level way along with more compatibility. but if you wanna use corssbus as an alternative of actix, there are some major differences you should take an eye on:

runtime actor lifecycle actor register concurrent/multi-thread
actix tokio custom creation, control by arbiter actor based, thread local Yes, depends on arbiter
corssbus runtime-less but allow any custom creation/abortion/pause/resume, control by reactor global, static Yes, depends on runtime and reactor

the way that crossbus take to tackle async/await is, to some degree, different from that actix takes.
crossbus just implement Future routines and defines asynchronous event handlers, not the way actix-rt (dependency of actix) takes to directly interact with runtime.

take a more specific example, actix has a set of trait and types to asynchronously handle Message request and directly await the returned response future base on what a lot of crates create services / features / functions, like actix-web, actix-net, but crossbus don't do that way, it use the similar way as javascript callback does (in case you familiar with), you just send the message request and set the handler for the ready response, crossbus will do the rest for you.

So if you wanna an easy version of actix, the answer is obviously NO,

  • you have to implement runtime (though in practice, it's easy)
  • crossbus does not have rich ecosystem as actix

@uwejan
Copy link
Author

uwejan commented Apr 26, 2023

Hey @hominee Thank you for taking the time to look into this, and pull up the good informations provided.
I have a couple of questions;

Take for instance the following snippets from actix;

impl Handler<DbOperations> for McActor {
    type Result = String;
    //type Result = ResponseFuture<String>;
    fn handle(&mut self, msg: DbOperations, ctx: &mut Self::Context) -> Self::Result {
        return match msg {
             DbOperations::Get { key } => {
               block_on(async {
                    sqlx::query_as::<_, DbOperationValues>(select_query)
                        .bind(key)
                        .fetch_one(self.db.as_ref().unwrap())
                        .await
                        .unwrap()
                }).value
                 
            }
            DbOperations::Set { key, value } => {   
                block_on(async {
                    sqlx::query_as::<_, DbOperationValues>(insert_query)
                        .bind(key)
                        .bind(value)
                        .fetch_one(self.db.as_ref().unwrap())
                        .await
                        .unwrap()
                }).value
            }
        };
    }
}

Since Can not use actix way handling future and returning its value with atomicResponse, i used block_on which as result, blocks the thread, causing the system to crash specially in the case of using websockets and while blocked a Pong response is not sent, not to mention other issues.
Now the question, how does crossbus handle futures?
Please do not tkae me wrong here and later on, I like to get clarifications before i digg deep inside the crate.
2. Question; In the table mentioned the ablility to handle streams is available, so am assuming it wont be an issue handling websockets streas read/write within the actor?
3. Question; In terms of platforum, it is neccersy to compile for linux/mac/windows, I notice on the crate page linux/mac only, can you clarify that for me please?
4. Question; Does crossbus have the concept of actor to actor messaging throught threads? Say actorA on thread 1, has a referrence of actorB on thread4, and they are able to pass messages and responses.

Being said, I am thankful to your time here, I am on the phase of finding the right candidate to move on with, not necsserly will opt in but it is always good to know my options.

Thank you.

@hominee
Copy link
Owner

hominee commented Apr 27, 2023

few separate points are stressed regarding to your problem:

  • if you wanna know explicitly how crossbus handle futures, there are some stuff out there you can refer to: how to explicitly handle asynchronous task with crossbus, the integration test contains some detailed example to use blocker delayer, streaming.
  • crossbus is able to handle any types implemented Stream trait just as actix does, and Websocket is essentially a stream of message you can read / write, but crossbus doesn't define / manipulate Websocket directly. this also happens to actix if I recall correctly, actor websocket is a derivative type on top of actix. So crossbus is not your best option if websocket stuff is touched during development
  • it terms of platform, I did test it in windows and tell the docs.rs to make compilation for windows as you you check the targets.package.metadata.docs.rs field in the Cargo.toml, and don't know why it doesn't display, maybe I will fix that in the next version and thanks for this issue.
  • Since crossbus is runtime-less, some thread-based features like multi-thread are not supported, and it's up to the runtime implementor. However it is nothing to do with the messaging interaction (sending, receiving and handling) between actors. that is a difference that I mentioned above that actors are controlled by thread-based arbiter in actix, while those are maintained by a single global static reactor in crossbus.

Last but not the least, I don't recommend you to use crossbus given the situation you provide, instead, you should dig deeper over actix.
As your problem is as simple as to replace block_on with Context::spawn or Addr::send, no more bother to do something else.

@uwejan
Copy link
Author

uwejan commented Apr 27, 2023

Agreed. @hominee Thank you for your time.
I am going to try and see what i can do.
Issue can be closed. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants