Skip to content

Instantly share code, notes, and snippets.

@jorendorff
Last active October 15, 2020 15:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jorendorff/121323bae73d9f92402fe5b0dc276ab0 to your computer and use it in GitHub Desktop.
Save jorendorff/121323bae73d9f92402fe5b0dc276ab0 to your computer and use it in GitHub Desktop.

Socket and channel setup

todo

Server receives a message

  • received first by the OS
  • then by websocket server code we don't control
  • eventually handed over to us
  • we parse the message enough to figure out the topic
  • use router to find the matching Channel
  • is this a join request? (if so, separate business logic for that, call a join method)
  • check that this ws connection is actually allowed to send stuff to this channel (???)
  • deserialize the message payload fully
  • make sure we're not delivering multiple messages simultaneously (using a mutex or an mpsc channel)
  • actually deliver the message to the Channel impl, finally

Then the Channel can do whatever it wants with that.

Downcasting to channel-specific message types

The Router can have a bunch of channels of all different types. How do we get messages decoded to the right types and delivered?

struct IncomingMessage {
    topic: String,
    event: String,
    payload: serde_json::value::Value,
}

trait MessageReceiver {
    fn receive(&mut self, message: IncomingMessage) -> Result<?, ?>;
}

// that way, we can have a single data structure with many MessageReceivers of different types
struct Router
    receivers: Arc<RwLock<HashMap<String, Box<dyn MessageReceiver>>>>,
}

// now we just need a way to treat any Channel as a MessageReceiver:

struct ChannelAsMessageReceiver<C: Channel> {
    channel: C,
}

impl<C: Channel> MessageReceiver for ChannelAsMessageReceiver<C> {
    fn receive(&mut self, message: IncomingMessage) -> Result<?, ?> {
        let payload: C::Message = serde_json::from_value(message.payload)?;
        self.channel.handle_in(payload)
    }
}

impl Router {
    fn add_channel<C: Channel>(&mut self, channel: C) {
        let id = channel.id();
        let receiver = Box::new(ChannelAsMessageReceiver { channel });
        self.receivers.insert(id, receiver);
    }
}

Broadcasting a message

todo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment