DataStore queue request. Need help!

The code:

for i = 1,10 do
local Sam = script.Sample:Clone()
Sam.Name = i
Sam.Parent = script.Parent.SurfaceGui.Frame.ScrollingFrame
Sam.UserPos.Text = “[”… tostring(i) …“]”
Sam.Points.Text = “Nil”
Sam.UserName.Text = “”
Sam.LayoutOrder = 1
script.Parent.SurfaceGui.Frame.ScrollingFrame.CanvasSize = UDim2.new(0,0,0,150*i)
end

function UpdateGui()
for i,v in pairs(game.Players:GetChildren()) do
local Data = v.Leaderboard.Points.Value
local DataStore = game:GetService(“DataStoreService”):GetOrderedDataStore(“Points”)
DataStore:SetAsync(v.UserId,Data)
end
local DataStore = game:GetService(“DataStoreService”):GetOrderedDataStore(“Points”)
local Pages = DataStore:GetSortedAsync(false,10)
local Data = Pages:GetCurrentPage()
for k,v in pairs(Data) do
if tonumber(v.key) >= 0 then
local Frame = script.Parent.SurfaceGui.Frame.ScrollingFrame:FindFirstChild(tostring(k))
if Frame then
Frame.UserName.Text = game.Players:GetNameFromUserIdAsync(v.key)
Frame.Points.Text = tostring(v.Value)
end
end

end
end

while true do
UpdateGui()
wait(2)
end

It looks like you are trying to save data too frequently. That’s why requests queue up. Lower the frequency and rather save only from time to time and when player leaves the game.

Formated script

local DataStoreService = game:GetService("DataStoreService")

for i = 1, 10 do
	local Sam = script.Sample:Clone()
	Sam.Name = i
	Sam.UserPos.Text = "[" .. tostring(i) "]"
	Sam.Points.Text = nil
	Sam.UserName.Text = ""
	Sam.LayoutOrder = 1
	Sam.Parent = script.Parent.SurfaceGui.Frame.ScrollingFrame
	script.Parent.SurfaceGui.Frame.ScrollingFrame.CanvasSize = UDim2.new(0,0,0,150 *i)
end

local function UpdateGui()
	local DataStore = DataStoreService:GetOrderedDataStore("Points")
	for i, v in pairs(game:GetService("Players"):GetChildren()) do
		local data = v.Leaderboard.Points.Value
		pcall(function()
			DataStore:SetAsync(v.UserId, data)
		end)
		wait(3) -- perhaps add a wait statement
	end
	
	local pages = DataStore:GetSortedAsync(false, 10)
	local data = pages:GetCurrentPage()
	
	for k, v in pairs(data) do
		if tonumber(v.key) >= 0 then
			local frame = script.Parent.SurfaceGui.Frame.ScrollingFrame:FindFirstChild(tostring(k))
			if frame then
				frame.UserName.Text = game.Players:GetNameFromUserIdAsync(v.key)
				frame.Points.Text = tostring(v.Value)
			end
		end
	end
end

--[[
	Are loops necessary? DataStores have a limit per minute,
	so frequent requests are not advised. Rather save on exit
	and from time to time.
]]
while true do
	UpdateGui()
	wait(30) -- change this
end

EDIT
@TheDevPig I don’t know what is the purpose of your leaderboard. Generally speaking, it’s a very good practice to save in intervals instead of rapidly, because otherwise datastore limitations (which are deliberate and also serve sort of as a security layer), cause requests to start to accumulate. Data cannot be successfully saved that way. If your script requires you to save and get data only from time to time (every 30 - 50 seconds in the above script, which hopefully works, because I can’t test it), the script you are using is alright. Unfortunately, such frequent saving (every 2 seconds) never works out well (depends on number of players and the size of data).
Why not store data temporarily on the server, but save infrequentely?

1 Like

It works but still doesnt show on the High Score list how much points I have. It says still nil somehow.

I am new in data store scripting. This is a blaster shooter ride and I want to save the points they do and then show the top 10 on a highscore.

DataStoreService is intended for saving, updating, and retrieving of the data. Various DataStores are very useful, but deliberately have set network limitations to prevent rapid calls, because that would lead to errors, slow connection with high network traffic, and potential data losses. Follow this link to read about these limits and errors: Data Stores. (Roblox Dev Hub, 2021-03-05)

Think of DataStores as libraries full of books.

When you need to read Data structures and algorithms in Java (2. Edition) and cry after reading it (kidding :sweat_smile:), you have to go into that library, ask the librarian for that book, wait for him/her to bring it to you (which is pretty fast in this case), and leave the library with your fresh reading material. When you get back home or go read in the near park, you read the book and only return it back either after you’ve read it or the borrowing period is over (so you have to re-borrow the book again).
It would be a huge waste of time to read a couple of pages in that book and right after go into the library again to return it, because you don’t have a place to keep it anywhere.

Let’s suppose you are also a publisher and manage your own publishing house. You sometimes provide new books to the local library and support the community. Do you send books one by one each hour? No, you rather bring a package once every 3 days.

It’s the same with DataStores. They are a key element in game development, but are not to be confused with that bookshelf you have at home where you leave books you currently read.

DataStores should only be used infrequently, but routinely. According to the number of players and the data size (data limits are present too), you should save data only now and then routinely, for example every 2 or 3 minutes, and of course at the end of each game session, when player is leaving. Rapid saving and retrieving of data is a no-go.

Because of the previously mentioned limits, requests may start to accumulate. Up to 30 requests long queue forms. Anything beyond that is lost.

How could you create your own in-game shelf you can frequently access? Take a look at the following example:

game:GetService("Players").PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local points = Instance.new("IntValue")
	points.Name = "Points"
	points.Parent = leaderstats
end)

When player joins, a folder called “leaderstats” containing an IntValue is inserted into player object. Player is accessible by the server and no changes done to that value by the client are replicated to the server, which means server can not only read that value, but also modify it.

image

You can read the value and update text of custom TextLabel you have. You can even do calculations with that value. You have a book shelf you can use to store data during the game, and when you want to save it into your DataStore, simply save it along with player’s UserId. Not complicated at all, right?

Perhaps you’d be interested in taking a look at this post, which includes a basic leaderboard without data saving.

If you ever decide to expand your game/project/etc., I suggest you consider contacting an experienced developer to help you take various precautions against data loss.

There are multiple tutorials here on Dev Forum that explain data saving pretty well. You might want to wrap all DataStore requests in pcall(), because errors are not so uncommon. They may appear because of weaker connectivity or some other reason. Second, instead of using SetAsync(), use UpdateAsync(), because it “considers the old value before making changes”. (Roblox Dev Hub - Data Stores, 2021-03-05)

1 Like