Global Leaderboard Not Updating Properly?

I have a global leaderboard that invokes the server every 3 minutes and gets an updated leaderboard. I invoke the server to have the server return the player’s data. This makes it so that I can get multiple values from the player’s data and set the player with the most Wins at the top, as well as show other things such as their Reputation, Losses, and other stuff.

Here’s the Server Script:

local PlayerService = game:GetService("Players")
local DSS = game:GetService("DataStoreService")
local Data = DSS:GetDataStore(game.ServerStorage.ServerValues.LeaderboardVersion.Value)
local Data_Key = "HOOP_DREAMS"
local DataManager = require(game.ServerScriptService.Datastore.Manager)
local GlobalLeaderboardEvent = game.ReplicatedStorage.Events.GetGlobalBoard
wait(10)

local RecordsTable = Data:GetAsync(Data_Key)

if not RecordsTable then
	print("NO TABLE DATA")
	local NewRecordsTable = {}
	local s, e = pcall(function()
		Data:UpdateAsync(Data_Key, function()
			for _, Player in pairs(PlayerService:GetPlayers()) do
				local PlayerProfile = DataManager:Get(Player)
				if PlayerProfile then
					local PlayerStats = PlayerProfile.PlayerStats
					local Reputation = PlayerProfile.Reputation
					NewRecordsTable[Player.Name] = {
						["Rep"] = Reputation.Name,
						["RepNumber"] = Reputation.Number,
						["Wins"] = PlayerStats.ParkWins,
						["Losses"] = PlayerStats.ParkLosses,
					}
				end
			end
			return NewRecordsTable
		end)
	end)
	--UPDATE ASYNC WORKED
	if s then
		print("TABLE SUCCESSFUL UPDATE")
	--USE SETASYNC INSTEAD
	elseif not s then
		print(e)
		for _, Player in pairs(PlayerService:GetPlayers()) do
			local PlayerProfile = DataManager:Get(Player)
			if PlayerProfile then
				local PlayerStats = PlayerProfile.PlayerStats
				local Reputation = PlayerProfile.Reputation
				NewRecordsTable[Player.Name] = {
					["Rep"] = Reputation.Name,
					["RepNumber"] = Reputation.Number,
					["Wins"] = PlayerStats.ParkWins,
					["Losses"] = PlayerStats.ParkLosses,
				}
			end
		end
		local s1, e1 = pcall(function()
			Data:SetAsync(Data_Key, NewRecordsTable)
		end)
		if s1 then
			print("TABLE SUCCESSFUL SET")
		else
			print(e1)
		end
	end
end

local NewRecordsTable = Data:GetAsync(Data_Key)

--AUTOSAVE RECORDSTABLE
spawn(function()
	while wait(180) do
		pcall(function()
			Data:UpdateAsync(Data_Key, function()
				for _, Player in pairs(PlayerService:GetPlayers()) do
					local PlayerProfile = DataManager:Get(Player)
					if PlayerProfile then
						local PlayerStats = PlayerProfile.PlayerStats
						local Reputation = PlayerProfile.Reputation
						NewRecordsTable[Player.Name] = {
							["Rep"] = Reputation.Name,
							["RepNumber"] = Reputation.Number,
							["Wins"] = PlayerStats.ParkWins,
							["Losses"] = PlayerStats.ParkLosses,
						}
					end
				end
				return NewRecordsTable
			end)
		end)
	end
end)

local function GetPlayerRecords()
	local New_RecordsTable = Data:GetAsync(Data_Key)
	for _, Player in pairs(PlayerService:GetPlayers()) do
		local PlayerProfile = DataManager:Get(Player)
		if PlayerProfile then
			local PlayerStats = PlayerProfile.PlayerStats
			local Reputation = PlayerProfile.Reputation
			New_RecordsTable[Player.Name] = {
				["Rep"] = Reputation.Name,
				["RepNumber"] = Reputation.Number,
				["Wins"] = PlayerStats.ParkWins,
				["Losses"] = PlayerStats.ParkLosses,
			}
		end
	end
	return New_RecordsTable
end

GlobalLeaderboardEvent.OnServerInvoke = GetPlayerRecords

Here is the Local Script:

local PlayerService = game:GetService("Players")
local Player = game.Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
local Leaderboard = PlayerGui:WaitForChild("Leaderboard")
local Frame = Leaderboard:WaitForChild("Frame")
local ScrollingFrame = Frame:WaitForChild("Frame")
local UI = ScrollingFrame:WaitForChild("UIListLayout")

local Template = Leaderboard:WaitForChild("Template")

local PlayerService = game:GetService("Players")
local RepStorage = game:GetService("ReplicatedStorage")
local Events = RepStorage:WaitForChild("Events")
local GetGlobalBoard = Events:WaitForChild("GetGlobalBoard")

local cache = {}

wait(15)

local function getUserIdFromUsername(name)
	-- First, check if the cache contains the name
	if cache[name] then return cache[name] end
	-- Second, check if the user is already connected to the server
	local player = PlayerService:FindFirstChild(name)
	if player then
		cache[name] = player.UserId
		return player.UserId
	end 
	-- If all else fails, send a request
	local id
	pcall(function ()
		id = PlayerService:GetUserIdFromNameAsync(name)
	end)
	cache[name] = id
	return id
end

while true do
	
	local PlayerCount = 0

	local function CreateTemplate(PlayerName, WinValue, ProfileTable)
		--REMOVE DUPLICATES
		if not ScrollingFrame:FindFirstChild(PlayerName) then
			PlayerCount = PlayerCount + 1
			if PlayerCount < 100 then
				local RepName
				local RepNumber
				local LossValue
				local ClonedTemplate = Template:Clone()
				local UserId = getUserIdFromUsername(PlayerName)
				local PlayerImage, isReady = PlayerService:GetUserThumbnailAsync(UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
				--SHOW PLAYER WITH HIGHEST WINS
				ClonedTemplate.LayoutOrder = -WinValue
				--SET PLAYER IMAGE AND PLAYER NAME
				ClonedTemplate.PlayerImage.Image = PlayerImage
				ClonedTemplate.Name = PlayerName
				ClonedTemplate.PlayerName.Text = PlayerName
				--SET VALUES
				for StatName, StatValue in pairs(ProfileTable) do
					if StatName == "Losses" then
						LossValue = StatValue
					elseif StatName == "Rep" then
						RepName = StatValue
					elseif StatName == "RepNumber" then
						RepNumber = StatValue
					end
				end
				--RECORD AND REP
				ClonedTemplate.Record.Text = ""..WinValue.." - "..LossValue..""
				ClonedTemplate.RepText.Text = string.upper(""..RepName.." "..RepNumber.."")
				--SHOW CLONED TEMPLATE
				ClonedTemplate.Visible = true
				ClonedTemplate.Parent = ScrollingFrame
				ScrollingFrame.CanvasSize = UDim2.new(0,0,1,UI.AbsoluteContentSize.Y)
			end
		end
	end

	local function GetHundredPlayers(Name, ProfileTable)
		local HundredPlayersTable = {}
		for StatName, StatValue in pairs(ProfileTable) do
			if StatName == "Wins" then
				HundredPlayersTable[Name] = StatValue
			end
		end
		return HundredPlayersTable
	end
	
	local Leaderboard = GetGlobalBoard:InvokeServer()
	UI.Parent = Frame
	ScrollingFrame:ClearAllChildren()
	UI.Parent = ScrollingFrame
	for PlayerName, ProfileTable in pairs(Leaderboard) do
		local HundredPlayers = GetHundredPlayers(PlayerName, ProfileTable)
		for _, WinValue in pairs(HundredPlayers) do
			CreateTemplate(PlayerName, WinValue, ProfileTable)
		end
	end
	wait(180) 
end

I’ve tried multiple ways of trying to get the “new” data by placing the GetAsync within the PlayerRecords function, but it still does not update the people who recently won games. How can I fix this?

Try adding checks print() everywhere until something don’t look like it should. It might help find the problem so people can work on that problem instead of the whole script.

There’s nothing that needs to be printed. I simply get the updated Data at GetAsync, but when the leaderboard updates, it gets the nonupdated version of the leaderboard.

That’s not what he means. print() statements can be crucial for discovering the location of an issue, as it is as simple as checking whether one of them printed or not. Try adding them in several areas of your script to get to the roots of the problem.

Yeah, I get that. But like I said printing isn’t going to solve anything in this case, because it’ll only print the same values lol. But anyways, here’s the solution.

local PlayerService = game:GetService("Players")
local DSS = game:GetService("DataStoreService")
local Data = DSS:GetDataStore(game.ServerStorage.ServerValues.LeaderboardVersion.Value)
local Data_Key = "HOOP_DREAMS"
local DataManager = require(game.ServerScriptService.Datastore.Manager)
local GlobalLeaderboardEvent = game.ReplicatedStorage.Events.GetGlobalBoard

wait(10)

local RecordsTable = Data:GetAsync(Data_Key)

if not RecordsTable then
	print("NO TABLE DATA")
	local NewRecordsTable = {}
	local UpdateSuccess, Error = pcall(function()
		Data:UpdateAsync(Data_Key, function()
			for _, Player in pairs(PlayerService:GetPlayers()) do
				local PlayerProfile = DataManager:Get(Player)
				if PlayerProfile then
					local PlayerStats = PlayerProfile.PlayerStats
					local Reputation = PlayerProfile.Reputation
					NewRecordsTable[Player.Name] = {
						["Rep"] = Reputation.Name,
						["RepNumber"] = Reputation.Number,
						["Wins"] = PlayerStats.ParkWins,
						["Losses"] = PlayerStats.ParkLosses,
					}
				end
			end
			return NewRecordsTable
		end)
	end)
	if UpdateSuccess then
		print("UPDATE SUCCESSFUL")
	else
		print(Error)
		for _, Player in pairs(PlayerService:GetPlayers()) do
			local PlayerProfile = DataManager:Get(Player)
			if PlayerProfile then
				local PlayerStats = PlayerProfile.PlayerStats
				local Reputation = PlayerProfile.Reputation
				NewRecordsTable[Player.Name] = {
					["Rep"] = Reputation.Name,
					["RepNumber"] = Reputation.Number,
					["Wins"] = PlayerStats.ParkWins,
					["Losses"] = PlayerStats.ParkLosses,
				}
			end
		end
		local SetSuccess, Error2 = pcall(function()
			Data:SetAsync(Data_Key, NewRecordsTable)
		end)
		if SetSuccess then
			print("TABLE SUCCESSFUL SET")
		else
			print(Error2)
		end
	end
end

--I had to GetAsync within the UpdateAsync function, that way it'll keep updating the "new" data key instead of the old one.
spawn(function()
	while true do
		--SET VARIABLE
		local UpdatedRecordsTable
		--WRITE IN PCALL
		local FoundUpdatedTable, _ = pcall(function()
			UpdatedRecordsTable = Data:GetAsync(Data_Key)
		end)
		--UPDATE TABLE
		if FoundUpdatedTable then
			pcall(function()
				Data:UpdateAsync(Data_Key, function()
					for _, Player in pairs(PlayerService:GetPlayers()) do
						local PlayerProfile = DataManager:Get(Player)
						if PlayerProfile then
							local PlayerStats = PlayerProfile.PlayerStats
							local Reputation = PlayerProfile.Reputation
							UpdatedRecordsTable[Player.Name] = {
								["Rep"] = Reputation.Name,
								["RepNumber"] = Reputation.Number,
								["Wins"] = PlayerStats.ParkWins,
								["Losses"] = PlayerStats.ParkLosses,
							}
						end
					end
					return UpdatedRecordsTable
				end)
			end)
		end
		wait(180)
	end
end)

local function GetPlayerRecords()
	--SET VARIABLE
	local UpdatedRecordsTable
	--WRITE IN PCALL
	local FoundUpdatedTable, _ = pcall(function()
		UpdatedRecordsTable = Data:GetAsync(Data_Key)
	end)
	if FoundUpdatedTable then
		return UpdatedRecordsTable
	end
end

GlobalLeaderboardEvent.OnServerInvoke = GetPlayerRecords