How can I improve this matchmatching?

Hey guys, I am making a matchmatching system, but it causes a lot of

DataStore request was added to queue. If request queue fills, further requests will be dropped. Try sending fewer requests.Key = Matchs

How can I improve it?
To make it faster and less requests.

local RepStorage = game:GetService("ReplicatedStorage")
local MessagingService = game:GetService("MessagingService")
local Datastore = game:GetService("DataStoreService")
local Matchmatching = Datastore:GetDataStore("Matchmatching")
local PlayersInside = {}
local Matches = {}
local Settings = require(script.Parent.Handler.Settings)
local Players = game:GetService('Players')
local TeleportService = game:GetService("TeleportService")

RepStorage.Events.EnterMatchmatching.OnServerEvent:Connect(function(Player)
	if (PlayersInside[Player]) then -- If player clicked already :D
		return
	end
	PlayersInside[Player] = true -- Adding to prevent player click multiple times :D
	local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs")
	if (suc) then
		if (returned) then
			RepStorage.Events.NotifyClient:FireClient(Player,"Searching in; "..#returned.." servers for a match.",4) -- Just to see how much people is searching for matchs too :D
		end
	end
	RepStorage.Events.EnterMatchmatching:FireClient(Player,1) -- UI effects, DW :D
	MessagingService:PublishAsync("MatchmatchingEnter",Player.UserId) -- Add him to matchmatching, try to find him a server!
end)

RepStorage.Events.LeaveMatchmatching.OnServerEvent:Connect(function(Player)
	PlayersInside[Player] = nil
	MessagingService:PublishAsync("PlayerLeftMatch",Player.UserId)
end)

local function StartMatch(Table)
	coroutine.wrap(function()
		local Players = Table.Players
		local PlayerNames = {}
		for i,v in pairs(Players) do
			table.insert(PlayerNames,game.Players:GetNameFromUserIdAsync(v))
		end
		warn("Starting match with;",table.concat(PlayerNames," & "))
		if (#Players >= 2) then
			local ReservedServer = TeleportService:ReserveServer(game.PlaceId)
			MessagingService:PublishAsync("TeleportPlayers",{Players = PlayerNames,ServerCode = ReservedServer})
		end
	end)()
end

local function CheckForMatchStart()
	coroutine.wrap(function()
		local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs")
		if (suc) then
			if (returned) then
				for i,v in pairs(returned) do
					if (os.time() - v.TimeCreated) >= 40 then
						StartMatch(v)
						table.remove(returned,i)
					end
				end
			end
			Matchmatching:UpdateAsync("Matchs",function(x)
				return returned or x
			end)
		end
	end)()
end

local function createMatch(owner)
	coroutine.wrap(function()
		local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs")	
		warn(suc)
		if (suc) then
			returned = returned and returned or {}
			table.insert(returned,{Players = {owner},Owner = owner,TimeCreated = os.time()})
			Matchmatching:UpdateAsync("Matchs",function(x)
				return returned or x
			end)
			return returned
		end
	end)()
	return nil
end

local function FindPlayerInMatch(plrID)
	local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs")	
	warn(suc)
	if (suc) then
		if (returned) then
			for i,v in pairs(returned) do
				if (table.find(v.Players,plrID)) then
					return true
				end
			end
		end
	end
	return false
end

local function CheckMatchs()
	coroutine.wrap(function()
		local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs")	
		if (suc) then
			if (returned) then
				print("returned, and running.")
				for index,match in pairs(returned) do
					if (#match.Players <= 0) then
						warn("Delete this match.")
						table.remove(returned,index)
					end
				end
				Matchmatching:UpdateAsync("Matchs",function(x)
					print("save.")
					return returned or x
				end)	
			end
		end
	end)()
end

local function RemovePlayerFromMatch(plrID)
	coroutine.wrap(function()
		local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs")	
		warn(suc)
		if (suc) then
			if (returned) then
				for i,v in pairs(returned) do
					if (table.find(v.Players,plrID)) then
						table.remove(v.Players,table.find(v.Players,plrID))
						print('removed from Players.',plrID)
					end
				end
				Matchmatching:UpdateAsync("Matchs",function(x)
					return returned or x
				end)	 
				CheckMatchs()
			end
		end
	end)()
end

local function InsertPlayerInMatch(userId,returned,index)
	coroutine.wrap(function()
		assert(userId ~= nil,"user ID is nil") -- Want to make sure UserId is NOT nil :D
		if (returned) then -- If returned is not nil.
			warn(returned,index,returned[index],returned[index].Owner) -- To check what returns, all works perfectly!
			local Table = returned[index] -- Just a variable to reduce code :D
			if (table.find(Table.Players,userId)) then -- Oh no, I found the player, it's already in this MATCH!
				table.remove(returned[index].Players,userId) -- Let's remove him and continue.
			end
			print("now inserting.")
			table.insert(returned[index].Players,userId) -- Let's add him to match!
			Matchmatching:UpdateAsync("Matchs",function(x)
				print('oh no, this doesnt PRINTS.')
				return returned or x -- Cool! Time to save this.
			end)
			local x = {Owner = game.Players:GetNameFromUserIdAsync(Table.Owner),Name = game.Players:GetNameFromUserIdAsync(userId),Amount = Table.Players}
			if (game.Players:FindFirstChild(x.Name)) then
				RepStorage.Events.EnterMatchmatching:FireClient(game.Players[x.Name],#x.Amount) -- UI effects :D
			end
			coroutine.wrap(function()
				MessagingService:PublishAsync("PlayerJoined",x) -- Let's notify the players inside match this player Joined.
			end)()
		end
	end)()
end

MessagingService:SubscribeAsync("PlayerLeftMatch",function(Message)
	local UserId = Message.Data
	local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs")
	if (suc) then
		if (returned) then
			for i,v in pairs(returned) do
				if (table.find(v.Players,UserId)) then
					print("remove him.")
					table.remove(v.Players,table.find(v.Players,UserId))
					local name = game.Players:GetNameFromUserIdAsync(UserId)
					if (#v.Players <= 0) then
						coroutine.wrap(function()
							CheckMatchs()
						end)()
					end
					for _,id in pairs(v.Players) do
						local name2 = game.Players:GetNameFromUserIdAsync(id)
						if (game.Players:FindFirstChild(name2)) then
							print("found",name2)
							RepStorage.Events.NotifyClient:FireClient(game.Players[name2],name.." has left the match you are in.",4)
							RepStorage.Events.EnterMatchmatching:FireClient(game.Players[name2],#v.Players)
						end
					end
				end
			end
			Matchmatching:UpdateAsync("Matchs",function(x)
				return returned or x
			end)
		end
	end
end)

MessagingService:SubscribeAsync("TeleportPlayers",function(msg)
	local Data = msg.Data
	local Server = Data.ServerCode
	local Players = Data.Players
	print(table.unpack(Players))
	for i,v in pairs(Players) do
		print("Attempting to find",v)
		if (game.Players:FindFirstChild(v)) then
			TeleportService:TeleportToPrivateServer(game.PlaceId,Server,{game.Players[v]},nil,nil,game.ServerStorage.UI.LoadingScreen)
		end
	end
end)

MessagingService:SubscribeAsync("PlayerJoined",function(msg)
	local Data = msg.Data
	local Owner = Data.Owner
	local Players = #Data.Amount
	local NameOfWhoJoined = Data.Name
	for i,v in pairs(Data.Amount) do
		local name = game.Players:GetNameFromUserIdAsync(v)
		if (game.Players:FindFirstChild(name)) then
			print("found",name)
			RepStorage.Events.NotifyClient:FireClient(game.Players[name],NameOfWhoJoined.." has joined the same match you are in.",4)
			RepStorage.Events.EnterMatchmatching:FireClient(game.Players[name],Players)
		end
	end
end)

MessagingService:SubscribeAsync("MatchmatchingEnter",function(msg)
	local UserId = msg.Data
	CheckMatchs() -- Deletes the matches that has less than 1 players :D
	local suc,returned = pcall(Matchmatching.GetAsync,Matchmatching,"Matchs") -- Retrieving data.
	if (suc) then
		if (returned) then
			table.sort(returned,
				function(a,b)
					return (a.Players < b.Players)
				end
			) -- Sorting the table to find the player the match with more Players :D
			local x = false
			for i,v in pairs(returned) do
				if (#v.Players < Settings.MaxPlayers) then -- Checking to see how much players the match has!
					InsertPlayerInMatch(UserId,returned,i) -- Cool!  Let's insert him to match :D!
					x = true -- forget this :D
					break -- breaking it
				end
			end
			if (not x) then
				createMatch(UserId)
			end
		else
			print('creating a new match. CREATED BY:',game.Players:GetNameFromUserIdAsync(UserId))
			createMatch(UserId)
		end
	end
end)

Players.PlayerRemoving:Connect(function(Player)
	MessagingService:PublishAsync("PlayerLeftMatch",Player.UserId)
end)

game:BindToClose(function()
	CheckMatchs()
end)

CheckMatchs()
coroutine.wrap(function()
	while (wait(60)) do
		print('checking for match starting')
		CheckForMatchStart()
	end
end)()
3 Likes


So uhm, how should I improve?

I would recommend having a table that checks if data isn’t already getting saved to the datastore to prevent this. It should be something like this then

local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetDataStore("Datastore")

local SaveQuee = {}
local function Save(UserId)
	if not SaveQuee[UserId] then
		SaveQuee[UserId] = true
		
		local succ
		repeat
			succ = pcall(function()
				Data:SetAsync('Your Data',UserId)
			end)
		    wait()
		until succ
		SaveQuee[UserId] = false
	end
end

I wrote this in a few seconds, not sure if everything is correct, but it should be!

I am not saving the player data, I am saving the matches, and I have to request when player attempts to join, to put ihm on match