Datastore values not saving?

I have this problem where the data wonโ€™t save. It doesnโ€™t print the error and Iโ€™m clueless on how to solve this.

  • Itโ€™s not saving the values inside the tables at all.
--// ๐™Ž๐™€๐™๐™‘๐™€๐™
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("PlayerData")
local ServerData = {}
local SavingFor = {}

local function newData()
	return {
		Stats = {
			Money = 0,
			Gems = 0,
			Diamonds = 0
		},
		Goals = {
			Five = false,
			Ten = false
		},
	}
end

local function loadData(player)
	local data
	local Success, Error = pcall(function() data = PlayerData:GetAsync("data:"..player.UserId) end)
	if not Success then
		warn("Could not get data for "..player.Name)
		return
	end
	if not data then
		data = newData()
	end
	ServerData[player] = data
end

local function saveData(player)
	if not SavingFor[player] then
		SavingFor[player] = true
		if ServerData[player] then
			local Success, Error = pcall(function() PlayerData:SetAsync("data:"..player.UserId, ServerData[player]) end)
			if not Success then
				warn("Data wasn't saved for "..player.Name..".")
				return
			end
			ServerData[player] = nil
		end
		SavingFor[player] = nil
	end
end

Players.PlayerAdded:Connect(function(player)
	loadData(player)
	ServerData[player].Stats.Money = ServerData[player].Stats.Money + 420
	print("Added money!")
end)

Players.PlayerRemoving:Connect(function(player)
	saveData(player)
	print("Saved " .. player.Name .. "'s data!")
end)

game:BindToClose(function()
	if RunService:IsStudio() then
		print("Not saving data, in studio!")
		return
	end
	
	for i,p in pairs(Players:GetChildren()) do
		saveData(p)
	end
end)
1 Like

I might see the issue.

Could you try removing your condition statement in your saveData function that checks for SavingFor[player] and try again to see if you see anything different?

Also, Iโ€™m not sure if this matters but for your BindToClose event, Iโ€™ve always just put a wait(10) in there. I donโ€™t think itโ€™s necessary to create a for loop to iterate over all the players additionally, so that might be a good quality of life change as well.

Hope this helps, and potentially fixes your issue. :slight_smile:

2 Likes

Oh, wow. Removing the condition statement fixed it, but now it is sending lots of requests. Is that safe?

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

Iโ€™m really confused by that actually. Based on your code, it should only run once for each player when they leave the game. Are you calling this function remotely as well??

@C_Sharper @28Y8 I think the problem here is a logical fallacy in your code. I editted the save function logic, let me know if it works.

local function saveData(player)
	if ServerData[player] and not SavingFor[player] then
		SavingFor[player] = true
		for i,v in pairs(ServerData[player]) do
			for j,k in pairs(v) do
				print(j,k)
			end
		end
			
		local Success, Error = pcall(function() 
			PlayerData:SetAsync("data:"..player.UserId, ServerData[player]) 
			ServerData[player] = nil
		end)

		
		if not Success then
			warn("Data wasn't saved for "..player.Name..".")
			return
		end
	end
	SavingFor[player] = nil
end
2 Likes

Oops, I forgot that BindToClose was enabledโ€ฆ So itโ€™s not requesting 2x anymore :slight_smile:

Thanks for your help!

1 Like

This occurs because SetAsync has a 6-second cool down for writing requests to the same key. It happens because youโ€™re attempting to save the data on player removal, as well as in the BindToClose function.

This is called Throttling. Throttling isnโ€™t anything to worry about, as the request will eventually be handled in the queue itโ€™s in. Though, sometimes you may exceed the limit of the queue, so requests would be dropped and not handled if it ever does

cc @28Y8

2 Likes

You should add some error throttling to your datastore functions because datastores can fail sometimes so you should make it retry calling SaveData, GetData or whatever your datastore call is. For example:

local Retries, MaxRetries = 0, 5

repeat
	local Success = pcall(Datastore.SaveAsync, Datastore, player.UserId, Data)
	Retries = Retries + 1
until Success or Retries == MaxRetries
2 Likes

May I suggest adding a 6-second cooldown between saves, because I mentioned that this will cause throttling and could cause the request queue to overflow and not save the requests. That is if your maximum number of retried is greater than 2.

Also, edit to your code:

local retries, maxRetries = 0, 5
repeat
    local Success = pcall(saveData, player) 
    retries = retries + 1
    wait(6)
until Success or retries == maxRetries
2 Likes

Oops, forgot the cooldown. Thanks for the heads up. :+1:

2 Likes