Skip to content

Commit

Permalink
Added constraints to mimick real API behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
IconPippi committed Apr 19, 2023
1 parent 809d83e commit 19da8f1
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 24 deletions.
11 changes: 0 additions & 11 deletions lib/MockMessagingService/init.lua
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
local MockMessagingService = {}

--[[ TODO constraints:
[Limit] [Maximum]
Size of message 1kB
Messages sent per game server 150 + 60 * (number of players in this game server) per minute
Messages received per topic (10 + 20 * number of servers) per minute
Messages received for entire game (100 + 50 * number of servers) per minute
Subscriptions allowed per game server 5 + 2 * (number of players in this game server)
--]]

local function _getOrNew(name)
local rq = script:FindFirstChild(name, false)

Expand Down
110 changes: 97 additions & 13 deletions plugin/init.server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ if not plugin then return end
local toolbar = plugin:CreateToolbar("MockMessagingService plugin")
local enabled = false

function _clone()
_remove()
local clone = script.Parent.MessagingService.MockMessagingService:Clone()
clone.Parent = game.ServerScriptService.MessagingService
end

function _remove()
local function _remove()
if game.ServerScriptService.MessagingService:FindFirstChild("MockMessagingService") ~= nil then
game.ServerScriptService.MessagingService.MockMessagingService:Destroy()
end
end

local function _clone()
_remove()
local clone = script.Parent.MessagingService.MockMessagingService:Clone()
clone.Parent = game.ServerScriptService.MessagingService
end

-- TODO: proper icon
local toggleButton = toolbar:CreateButton("Toggle MMS", "Enables or disables MockMessagingService", "rbxassetid://484838285")
toggleButton.ClickableWhenViewportHidden = true
Expand All @@ -36,11 +36,6 @@ end

toggleButton.Click:Connect(toggleButtonClicked)

plugin.Unloading:Connect(function()
enabled = false
_remove()
end)

-- ################## Data exchange logic ##################
local MMS = game.ServerScriptService:WaitForChild("MessagingService"):WaitForChild("MockMessagingService")

Expand All @@ -49,25 +44,114 @@ local subscribeRequest: BindableEvent = MMS:WaitForChild("SubscribeRequest")

local subscribedTopics = {}

local function _elapsedSeconds(lastTime)
local currentTimestamp = os.time()
return currentTimestamp - lastTime
end

local function _serverCount()
return plugin:GetSetting("_serverCount") or 0
end

-- increase the number of servers currently using MMS by one
plugin:SetSetting("_serverCount", _serverCount() + 1)

--[[ Constraints:
[Limit] [Maximum]
Size of message 1kB
Messages sent per game server 150 + 60 * (number of players in this game server) per minute
Messages received per topic (10 + 20 * number of servers) per minute
Messages received for entire game (100 + 50 * number of servers) per minute
Subscriptions allowed per game server 5 + 2 * (number of players in this game server)
--]]
local Constraints = {
sentMessages = {
max = (150 + 60 * #game.Players:GetPlayers()) / 60,
count = 0,
lastTime = os.time()
},
subscriptions = {
max = 5 + 2 * #game.Players:GetPlayers(),
count = 0
},
receivedMessagesTopic = {
max = (10 + 20 * _serverCount()) / 60,
count = 0,
lastTime = os.time()
},
receivedMessagesTotal = {
max = (100 + 50 * _serverCount()) / 60,
count = 0,
lastTime = os.time()
}
}

publishRequest.Event:Connect(function (topic: string, message)
-- check if message size exceeds 1kB
if string.len(tostring(message)) > 1024 then
error("Message size exceeds 1kB")
end

-- check if message limit per game server is reached
Constraints.sentMessages.count += 1
local elapsed = _elapsedSeconds(Constraints.sentMessages.lastTime)
if Constraints.sentMessages.count > Constraints.sentMessages.max * elapsed then
error("Message limit per game server per minute reached")
end

-- plugin:SetSetting hits disc instead of memory, so it can be slow. Spawn so we don't hang.
task.spawn(plugin.SetSetting, plugin, topic, message)

Constraints.lastTimestamp = os.time()
end)

subscribeRequest.Event:Connect(function (topic: string)
-- check if already subscribed to topic
if subscribedTopics[topic] ~= nil then return end

-- check if subscription limit per game server is reached
Constraints.subscriptions.count += 1
if Constraints.subscriptions.count >= Constraints.subscriptions.max then
error("Subscription limit per game server reached")
end

table.insert(subscribedTopics, topic)

Constraints.lastTimestamp = os.time()
end)

game:GetService("RunService").Heartbeat:Connect(function()
-- Check if message limit for entire game is reached
local elapsed = _elapsedSeconds(Constraints.receivedMessagesTotal.lastTime)
if Constraints.receivedMessagesTotal.count >= Constraints.receivedMessagesTotal.max * elapsed then
return
end

for i, topic in ipairs(subscribedTopics) do
-- check if message limit per topic is reached
local elapsed = _elapsedSeconds(Constraints.receivedMessagesTopic.lastTime)
if Constraints.receivedMessagesTopic.count >= Constraints.receivedMessagesTopic.max * elapsed then
continue
end

local data = plugin:GetSetting(topic)
if data then
-- we want to clear the setting field even if there's
-- no one subscribed to this topic ready to accept the data
plugin:SetSetting(topic, nil)
task.spawn(plugin.SetSetting, plugin, topic, nil)

local callback: BindableEvent = MMS:WaitForChild(topic .. "_CallbackEvent")
callback:Fire(data)
end
end
end)

-- Unloading
plugin.Unloading:Connect(function()
plugin:SetSetting("_serverCount", _serverCount() - 1)

enabled = false
_remove()
end)

0 comments on commit 19da8f1

Please sign in to comment.