1c3t3a / rust-socketio

An implementation of a socket.io client written in the Rust programming language.
MIT License
406 stars 72 forks source link

Server Implementation Checklist #124

Open ctrlaltf24 opened 2 years ago

ctrlaltf24 commented 2 years ago

Development on hold, someone else is welcome to take over

It's that time @1c3t3a , might want to make a branch. How servers are implemented informs discussion about what the best interface method is (for 0.3.X).

TBD:

ctrlaltf24 commented 2 years ago

@1c3t3a It would be easier to implement 0.4.0 if we used async internally, but didn't expose. That alright with you? Async internally but synchronous end-user interfaces? Using https://docs.rs/futures/0.3.17/futures/sink/index.html https://docs.rs/futures/0.3.17/futures/stream/index.html# internally, then consuming the sinks into callbacks.

ctrlaltf24 commented 2 years ago

We might be able to leverage https://tokio.rs/tokio/topics/bridging to use async internally but expose a sync interface. Not sure how that would work for people with conflicting tokio versions though.

Might be smarter to expose this as a feature

@1c3t3a can you please make a 0.4.0 branch?

1c3t3a commented 2 years ago

Yes, just opened it!

ctrlaltf24 commented 2 years ago

@1c3t3a how does this look for a the closure based callback interface for the server? This interface will involve several Arc Mutex locks, after/during implementation we can discuss other interfaces that are more rusty. Planning to make the server async (behind a feature).

async fn main() {
    let server = ServerBuilder::new(4202)
        .on("connection", |_, client, server| {
            client.on("message", |message, client, server| {
                client.emit_with_ack("hello awk", |_, client, server| {
                        // awked
                }).await?;
            });
            client.on("heartbeat", |_, client, server| {

            });
            client.on("error", |message, client, server| {

            });
            client.on("close", |_, client, server| {

            });
            client.emit("hello client").await?;
        })
        .connect().await?;
}

or

async fn main() {
    let server = ServerBuilder::new(4202)
        .on_connection(|_, client, server| {
            client.on_message(|message, client, server| {
                client.emit_with_ack("hello awk", |client, server| {
                    // awked
                }).await?;
            });
            client.on_heartbeat(|client, server| {

            });
            client.on_error(|message, client, server| {

            });
            client.on_close(|client, server| {

            });
            client.emit("hello client").await?;
        })
        .connect().await?;
}

While the latter is cleaner, the first is more consistent with both the js implementation and the client

1c3t3a commented 2 years ago

I would honestly prefer the former, as it sticks more to the socketio API. Also the latter could be more difficult when reacting to a custom event. And I honestly like the Into<Event> Generic bounds which allow passing in strings in a type safe manner. What do you think @nshaaban-cPacket?

ctrlaltf24 commented 2 years ago

Agreed, the former make more sense. I'm writing the code in such a way that should enable us to write different API interfaces in the future (like more rusty/streams ones) .

1c3t3a commented 1 year ago

With 0.4.0 being about reconnect refactor, we should either rename this to 0.5.0 or close.

ctrlaltf24 commented 8 months ago

Looks like someone beat us to it https://github.com/Totodore/socketioxide implemented as a tower layer, interesting