Are there any improvements I should make to this data store

I just created this data store and I’ve done some testing, it works well, but are there any flaws?

local dataStore = {}

local DSS = game:GetService("DataStoreService")
local AutoSaveInterval = 30

function dataStore.wrap(self)
	local PlayerId = string.format("Player_%d", self.player.UserId)
	
	local function save()
		if #self.__queue == 0 then
			-- There are no entries, nothing needs to happen
			return
		end
		-- Update the data store to be the last entry
		self.__store:SetAsync(PlayerId, self.__queue[#self.__queue])
	end
	game:BindToClose(function()
		-- The game has been shutdown, wait until the player's next save and call save()
		delay(tick()-self.__lastEntry, save)
	end)
	-- Wait every 30 seconds to save data
	while wait(AutoSaveInterval) do
		-- Change the last entry
		self.__lastEntry = tick()
		-- Call save()
		save()
		for entry, _ in pairs(self.__queue) do
			-- Remove all entries from the queue
			table.remove(self.__queue, entry)
		end
	end
end

function dataStore.new(player, name, defaultValue)
	if dataStore[player] then
		-- Return the data store if it already exists
		return dataStore[player]
	end
	
	-- Create data store object
	dataStore[player] = setmetatable({
		name = name,
		player = player,
		defaultValue = defaultValue,
		__lastEntry = math.huge,
		__queue = {},
		__store = DSS:GetDataStore(name),
		__updateCallbacks = {},
	}, {__index = dataStore})
	
	-- Start auto saving 
	coroutine.wrap(dataStore.wrap)(dataStore[player])
	
	-- Return data store
	return dataStore[player]
end

function dataStore:GetAsync(default)
	local default = default or self.defaultValue or 0
	
	local PlayerId = string.format("Player_%d", self.player.UserId)
	
	if #self.__queue > 0 then
		-- Not all requests are saved right away, so we get the last entry
		return self.__queue[#self.__queue]
	else
		local found, result = pcall(function()
			return self.__store:GetAsync(PlayerId)
		end)
		if found then
			-- Data was found, if there is no saved data then return the default value
			return result or default
		else
			local err = string.format("Data store experienced an error: %q", result)
			warn(err)
		end
	end
end

function dataStore:SetAsync(value)
	-- Add value to queue so it can be saved
	table.insert(self.__queue, value)
	-- Call all update callbacks
	for _, callback in pairs(self.__updateCallbacks) do
		callback(value)
	end
end

function dataStore:OnUpdate(callback)
	table.insert(self.__updateCallbacks, callback)
end

return dataStore
1 Like

It looks good, but if you want to you could use ProfileService.