I made this remote function where you can get the data of all factions as a client. I need this because I am making a faction system so the player can browse and join different factions. However, I am worried about the fact that I am making a datastore request and a groupservice request for each faction. What if there are 1,000 factions? I think that would overflow the datastore.
Here is my code:
FactionsRemotes:WaitForChild("GetAllFactionsData").OnServerInvoke = function(player)
local returnTable = {}
local regPages = FactionsDS:ListKeysAsync()
local numFactions = 0
while true do
for _, datastoreKey in ipairs(regPages:GetCurrentPage()) do
-- GetFactionInfo makes 1 GetAsync request to a datastore.
returnTable[datastoreKey.KeyName] = module.GetFactionInfo(tonumber(datastoreKey.KeyName))
returnTable[datastoreKey.KeyName]["GroupInfo"] = GroupService:GetGroupInfoAsync(tonumber(datastoreKey.KeyName))
numFactions += 1
end
if regPages.IsFinished then -- or numFactions > 1000 here?
break
else
regPages:AdvanceToNextPageAsync()
end
end
return returnTable
end
My reference for this factions system is saber showdown. Is there a better way to get all factions without overflowing the datastore service? Any help would be appreciated.
It will throttle, and is also extremely vulnerable to any DOS attack. you should cache the results on the server and have the remote function just fetch those.
(an exploiter can spam fetch the remote function and throttle datastore requests, data for players won’t load or save)
So when the server starts, I call this function every 10 minutes or so? I think that’s a good idea for preventing a DOS attack, but I’m still concerned about the fact that it’s calling GetAsync on all keys at once. Is there a way to prevent that from throttling?
function exponentialRetry(maxRetries: number, f: (...any) -> any, ...: any)
local retryDelay = 1
for i = 1, maxRetries do
local success, result = pcall(f, ...)
if (success) then return result end
if i < maxRetries then
task.wait(retryDelay)
retryDelay *= 2
end
end
end
--in your case:
exponentialRetry(10, regPages.AdvanceToNextPageAsync, regPages)
--or if you're unfamiliar with oop implicit self:
exponentialRetry(10, function()
regPages:AdvanceToNextPageAsync()
end)
note that this is just for retries, ontop of this you should still task.wait(0.1) between each AdvanceToNextPageAsync() to be safe