[Open Source] Messenger

Messenger is a lightweight, minimal library that allows for seamless cross-server messaging on the Roblox platform. It’s comprised of topics, which are like channels for servers to communicate in. These topics should each have their own specific use. Topics can be used to listen for data, and send data. Topic threads can be used to create a stream of messages between servers for a specific reason. You can get it from its Github repository or through its Roblox model. If you have any issues with it, please open an issue or create a pull-request.

Usage

Messenger is a fully object-oriented library. Its main class is called Server, which is a messaging server. It doesn’t provide much functionality, but provides similar functions as you would find in Roblox’s built-in MessagingService. A message server can be created as follows.

local messageServer = Server.new()

You can send data using the publish function, which takes in the name of the topic in which to publish the message, along with the message itself. Messenger provides extra data other than the data you send, that contains the server’s PlaceId and JobId.

local SERVER_START_TOPIC = "ServerStart"

-- tell other servers that we've started
-- we do not need to provide any data, as this server's info is automatically provided by messenger
messageServer:publish(SERVER_START_TOPIC)

You can listen for data in a topic by subscribing to it, which can be done using the subscribe function. It takes the name of the topic to subscribe to, along with a callback function to be executed every time data is sent. It returns an RBXScriptConnection, and can be disconnected when needed.

-- subscribe to topic
messageServer:subscribe(SERVER_START_TOPIC, function(message)
    print("New server started!")
    print("Place ID is", message.server.placeId)
    print("Job ID is", message.server.jobId)
end)

Topic

A topic is a channel of communication between servers. A topic can be accessed by the getTopic function of the Server class, or just constructing it through its class table.

local PLAYER_JOIN_TOPIC = "PlayerJoin"

local playerJoinTopic = messageServer:getTopic(PLAYER_JOIN_TOPIC)

We can send data through this topic using the send function, which takes in the data to be sent through the topic.

local Players = game:GetService("Players")

-- connect to whenever a player is added
Players.PlayerAdded:Connect(function(player)
    -- send a message to other servers
    playerJoinTopic:send(player.UserId)
end)

We can listen for messages through this topic by using the subscribe function, which takes in the callback function to be run every time a message is recieved, and returns the RBXScriptConnection.

playerJoinTopic:subscribe(function(message)
    print("Player joined!")
    print("User ID:", message.data)
    print("PlaceID:", message.server.placeId)
    print("Job ID:", message.server.jobId)
end)

Threads

Threads allow us to create a message stream between servers. They are handled by the metadata in the messages sent through topics internally. They can be created by using the createThread function of the Topic class.

local GET_SERVERS_TOPIC = "GetServers"
local getServersTopic = messageServer:getTopic(GET_SERVERS_TOPIC)

-- send message to servers and create thread
local thread = getServersTopic:createThread(getServersTopic:send())

-- listen for responses
local listener = thread:subscribe(function(message)
    -- print the server's information
    print(message.server.placeId, " - ", message.server.jobId)
end)

We can reply to a message by using threads as well. The explanation is below.

-- subscribe to the topic
getServersTopic:subscribe(function(message)
    -- create a thread from the message's thread ID
    local thread = getServersTopic:createThread(message.threadId)

    -- send a message in that thread (equivalent to a reply)
    thread:send()
end)

How it works

This is all useful, but if you’re wondering how threads work, here’s an explanation: When a message is sent through a topic, the topic will create a thread ID. This unique string can be used for any other server to reply to the message. Each message holds the server’s information, the message’s data, and the thread ID for any replies. the createThread function simply creates a thread object from the thread ID returned by the send function. When the topic receives a message, it’ll fire the message event, which will invoke all the subscription functions. It will also check to see if the thread ID is a response to an earlier message. If so, then it’ll call the thread object’s handleMessage function, which will handle any thread-related stuff and fire its message event.

Here is the structure of a message as it is sent through messaging service. Note that it is in the form of an array.

{
    {placeId, jobId},       -- data about the server that sent the message
    threadId,               -- the thread ID of the message
    data                    -- the message's data
}

Here is the structure of a message as it is presented to callbacks and other functions. Note that it is in the form of a dictionary.

{
    server = {              -- data about the server that sent the message
        placeId = placeId,  -- the place ID of the server
        jobId = jobId       -- the job ID of the server
    },
    
    threadId = threadId,    -- the thread ID of the message
    data = data             -- the message's data
}
21 Likes

I had accidently swapped the links earlier. They have been fixed now.

That sounds pretty sweet, where do I put the script?

1 Like

It doesn’t matter where you put the script, as long as you can require it from a server-script. I’d recommend putting it in ServerStorage or ServerScriptService somewhere.

2 Likes

May I ask how you communicate between the 2 servers?

Very nice. I see a lot of use cases for this; nice API too! Great job @OptimisticSide!

Hopefully see more of your creations soon :slight_smile:

1 Like

You can communicate between two servers using messaging service. It’s the same as how you’d communicate between the server and client using remote events and functions.