Ably One-to-One Messaging

771 views Asked by At

So I was trying to implement one-to-one messaging in NextJS with Ably but I couldn't get it done.

I'm stuck between making channels for interactions (e.g. private:<user_1>-<user_2>) and channels for users (e.g. private:<user_1>).

In the second implementation I would need to subscribe only <user_1> to their channel but allow other users to publish to private:<user_1>.

Summary: What would be the best way to use Ably Realtime in NextJS to implement one-to-one messaging

const {data: session, status} = useSession()
    let inputBox = null;
    let messageEnd = null;
    const [time, setTime] = useState("")

    const [messageText, setMessageText] = useState("");
    const [receivedMessages, setMessages] = useState([]);
    const messageTextIsEmpty = messageText.trim().length === 0;
    useEffect(()=>{
        console.log(session);
    }, [session])
    
    if(status === "authenticated"){
        console.log(session.id);
        const [channel, ably] = useChannel(`chat:${session.id}`, (message) =>{
            console.log(message);
        })
    }  

I tried this but quickly realized that the rules of React Hooks make it impossible

Apologies, it is my first time posting to Stack Overflow

1

There are 1 answers

0
Tom Camp On BEST ANSWER

I'm a Developer Advocate at Ably. It largely depends on what sorts of actions you'll wish to perform on user-to-user chats, your limitations on # of channels, and how many concurrent chats are available per user.

The most logical method would be to have a single channel for each 1-to-1 chat (so chat:user1:user2), as this guarantees you have:

  • A consistent message order between the 2
  • It's easy to get the history or any one conversation, as it's available via a single chat request. Generally, the logical division of chats as channels makes any processing you'd want to do on chats simple

However, if you intend for each user to be subscribed to the events of each 1-to-1 chat, and a large number of potential 1-to-1 chats possible per user, you can start to hit a few concerns:

  • If you were to have say on average of 50 1-to-1 chats per user, that's going to start adding up quickly as more users join chats
  • If it's possible for any user to message any other user on your platform, and there are potentially thousands or millions of users, you'd need a way for clients to know what channels to subscribe to to receive messages. This then becomes a whole ordeal for then having meta information being generated to determine what channels are active, what channels they should subscribe to, and when to unsubscribe from a channel to avoid too much usage of channels

Once you're wanting that sort of scale, it's probably worth considering having a user channel that other users publish in to to communicate with them (say chat:user1). If say all other users are given publish-only permissions to use the chat:* namespace in general, but given all needed permissions to their chat (chat:user1), then you can allow any user to message any other user without them being able to view what others have messaged said user.

  • Generally in terms of # of channels, this is helpful as the number of channels for 1-to-1 conversations is capped to the overall number of active users
  • It's easy to ensure any 1 user is subscribed to all the channels they should be, as they're only needing to subscribe to their own channel

The issue here would be that you then need to create some functionality to reproduce usually inherent Ably functionality, such as getting History of a conversation. As you wouldn't have access to another user's chat channel, you'd need some method to make the messages you send available to yourself.

This is where recommendations really come down to your own needs of the chat. If it's ephemeral, you can probably get away with just storing it locally. If you're already storing longer-term history on a server somewhere, you can just make use of that for general history requests. If you're needing it available in Ably, you can just also have a separate channel (say chat:user1:my_sent_messages), which you also send your messages to to act as a temporary store for it all. The issue there is you can potentially end up with disjointed history ordering between the receiving and sending client, but that's something to weigh up when considering these potential solutions.

Overall if you intend to scale up I'd probably recommend having per-user channels which everyone publishes to to communicate with them, but you can go for amalgamations of uses depending on your specific needs.