I made a small data store module and I wanted to know if this would be a good way of saving a players data efficiently
--[[
DOCUMENTATION:
LightData.SetDataStore(Name, Scope) | Line 166
Sets the datastore name and scope for LightData.
Name: string
Scope: string
LightData.SetDataTemplate(Template) | Line 170
Sets the data template for LightData.
Template: table
LightData:GetData(player) | Line 176
Gets the player's data.
player: Player
returns: table
LightData:SaveData(player, remove) | Line 186
Saves the player's data.
player: Player
remove: boolean
]]--
-- # Services
local Players = game:GetService('Players')
local DataStoreService = game:GetService('DataStoreService')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local RunService = game:GetService('RunService')
local HttpService = game:GetService('HttpService')
-- # Light Data
local LightData = {
DataStore = nil;
PlayerData = {};
DataTemplate = {};
}
-- # Cache
local Cache = {
Cache = {}
}
-- # Cache Functions
function Cache:Add(player: Player, Data: {})
Cache.Cache[player.UserId] = Data
warn(`{player.UserId}s Data Has Been Added To Cache.`)
end
function Cache:Clear()
local function doSave(UserId, Data)
while true do
local succ, err = pcall(function()
local EncodedData = HttpService:JSONEncode(Data)
LightData.DataStore:SetAsync(tostring(UserId), EncodedData)
end)
if succ then
break
end
task.wait(3)
end
Cache.Cache[UserId] = nil
end
for UserId, Data in pairs(Cache.Cache) do
task.spawn(doSave(UserId, Data))
end
end
function Cache:ClearOne(UserId: number)
local function doSave(UserId, Data)
while true do
local succ, err = pcall(function()
local EncodedData = HttpService:JSONEncode(Data)
LightData.DataStore:SetAsync(tostring(UserId), EncodedData)
end)
if succ then
break
end
task.wait(3)
end
Cache.Cache[UserId] = nil
end
if Cache.Cache[UserId] then
doSave(UserId, Cache.Cache[UserId])
end
end
-- # Utils
local function DeepCopyTable(t)
local copy = {}
for key, value in pairs(t) do
if type(value) == "table" then
copy[key] = DeepCopyTable(value)
else
copy[key] = value
end
end
return copy
end
local function ReconcileTable(target, template)
for key, value in pairs(template) do
if type(key) == "string" then
if target[key] == nil then
if type(value) == "table" then
target[key] = DeepCopyTable(value)
else
target[key] = value
end
elseif type(target[key]) == "table" and type(value) == "table" then
ReconcileTable(target[key], value)
end
end
end
end
-- # Private Functions
local function LoadData(player: Player): {}
assert(LightData.DataStore, 'You must create a data store to load player data.')
local Succ, Data = pcall(function()
return LightData.DataStore:GetAsync(tostring(player.UserId))
end)
if Succ then
Data = HttpService:JSONDecode(Data)
ReconcileTable(Data, LightData.DataTemplate)
return Data
end
return LightData.DataTemplate
end
local function SaveData(player: Player, Data: {}, Remove: boolean)
assert(LightData.DataStore, 'You must create a data store to save player data.')
assert(typeof(Data) == 'table', 'Data must be a table to save.')
local Succ, err = pcall(function()
local EncodedData = HttpService:JSONEncode(Data)
LightData.DataStore:SetAsync(tostring(player.UserId), EncodedData)
end)
if not Succ then
Cache:Add(player, Data)
end
if Remove ~= nil and Remove == true then
if LightData.PlayerData[player] ~= nil then
LightData.PlayerData[player] = nil
end
end
end
-- # Global Functions
function LightData.SetDataStore(Name: string, Scope: string)
LightData.DataStore = DataStoreService:GetDataStore(Name, Scope)
end
function LightData.SetDataTemplate(Template: {})
assert(typeof(Template) == 'table', 'Given template must be a table.')
LightData.DataTemplate = Template
end
function LightData.GetData(player: Player)
local PlayerData = LightData.PlayerData[player] or LoadData(player)
if typeof(PlayerData) == 'table' then
return PlayerData
end
return nil
end
function LightData.SaveData(player: Player, Remove: boolean)
local PlayerData = LightData.GetData(player)
if PlayerData ~= nil then
SaveData(player, PlayerData, Remove)
end
end
-- # Misc
game:BindToClose(function()
Cache:Clear() -- > Make sure all data stored in the cache gets saved.
end)
-- # return
return LightData