Help to improve my own Data Store

I currently do my own data store by finding other source on YouTube.

However can somebody help me to improve this Data Store.

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("myDataStore")

local tries = 8 -- Change This How Many Want You Want
local dataLoaded = false


local function Set(plr)
	if dataLoaded then
		local key = "plr-" .. plr.UserId
		local count = 0

		local data = {
			["Coins"] = plr.leaderstats.Coins.Value,
		}
		
		
		
		local sucess, err
		
		repeat
			sucess, err = pcall(function()
				myDataStore:UpdateAsync(key, function(oldValue)
					local newValue = data or oldValue or 0
					
					return newValue
		
				end)
			end)
			count = count + 1
			
			if script.Parent["Data - Store"].SelfCheck == true and count >= 2 then -- Prints The progress.
				print(count.. " We retrying to load the data.")
			end
			if count >= 2 then 
				wait(60) -- Slow Down The Process ; Repeats
			end
		until count >= tries or sucess
		if not sucess then
			warn("Failed to set the value. Error code: " .. tostring(err))
			
			return
		end
	else
		return
	end
end

local function Get(plr)
	
	local key = "plr-" .. plr.UserId
	local count = 0
	
	local data
	
	local sucess, err
	
	repeat 
		sucess, err = pcall(function()
			data = myDataStore:GetAsync(key)
		end)
		count = count + 1
		if script.Parent["Data - Store"].SelfCheck == true and count >= 2 then -- Prints The progress.
			print(count.. " We retrying to load the data.")
		end
		if count >= 2 then 
			wait(60) -- Slow Down The Process ; Repeats
		end
	until count >= tries or sucess
	
	dataLoaded = true
	
	if not sucess then
		warn("Failed to read. Data. Error code: " .. tostring(err))
		
		plr:Kick("Sorry were not able to load your data kindly rejoin.")
		
		return
	end
	if sucess then
		if data then
			return data
		else
			return {
				["Coins"] = script.Parent["Data - Store"].Increment.Value,
			}
		end
		
		
	end
end

local function createLeaderstats(plr)
	local values = Get(plr)
	
	local leaderstats = Instance.new("Folder",plr) 
	leaderstats.Name = "leaderstats"

	local Coins = Instance.new("IntValue", leaderstats)
	Coins.Name = "Coins" 
	Coins.Value = 0
	
	Coins.Value = values.Coins
	
	
end

Players.PlayerRemoving:Connect(Set)
Players.PlayerAdded:Connect(createLeaderstats)

game:BindToClose(function()
	for _, Players in ipairs(Players:GetPlayers()) do
		coroutine.wrap(Set)
	end
end)

NOTE : If your here to say use Data Store 2 then stop i want to learn on my own.

Question :

  1. Can i still throttled roblox on my repeat until sucess?
  2. Is my BindToClose is good using courtine wrap?
  3. Can UpdateAsync help me to not overite data?

Plans :

  1. I will change the GetAsync to UpdateAync so i can server lock it…

Question :

  1. do you think UpdateAsync can also use in Loading data ? and lock server just like ProfileService because the ProfileService use it when loading or saving data.

Well, I can start by addressing the feedback you’ve raised.

Yes, you can still be throttled in a repeat loop. The difference between your code existing in and out of one is how many times it will be repeatedly called until the conditional is met so logically you can experience throttling if you don’t handle that scenario carefully. Make sure that you reference DataStore Errors and Limits to see what you may be expected to account for.

Sure, BindToClose is fine, but coroutines aren’t particularly necessary. I’d prefer to call all my operations immediately and in sequence to ensure that each item is going through. You may want to be mindful of using the same save function for leaving as shut downs though; your current save function delays saves by 60 seconds during failures which exceeds the 30 seconds a server is allotted to perform last minute procedures before the server closes out. Consider divorcing the retry logic from the save logic so you can have both exist or something.

No, UpdateAsync can’t help you to not overwrite data. UpdateAsync is (or rather should be) the canonical function to update data as per its name. It’s powerful in the sense that it gives you the opportunity to change data based on what is already saved and that it will retry itself in the case that a conflicting write request is made to ensure that what it needs to update is passed through. That being said, if you use UpdateAsync like a SetAsync then there is a possibility for overwriting since you can’t guarantee that the updates are building off of the player’s latest data.

Yes, UpdateAsync can also be used to load data. ProfileService uses UpdateAsync for every interaction with DataStores. It also performs additional editing procedures due to various features (e.g. session locking, global updates, meta tags) during the loading process but besides metadata none of the actual saved data gets changed. ProfileService only updates the data in the UpdateAsync call when a saving method is called. If you don’t need to do any additional loading procedures though then there’s generally no need to use UpdateAsync to fetch data. Just be wary of GetAsync’s 4 second cache if it’s of any relevance to your system.


In terms of your code, you didn’t specify any explicit changes you were looking at so the improvements above are based on the feedback you wanted. I won’t exactly suggest anything codewise besides the fact that you should probably not make your dataLoaded variable global. It’s set if one player’s data loads but that means any other player that has a data loading issue will also be passed off as their data being loaded, so this could cause potential data loss. Scope it out per player via a dictionary.

3 Likes

Thanks for your feedback i’ll just going to apply it on my code.

1 Like