Any issues with my current dataModule and dataHandler methods?

My current data store I’ve designed to -try- and inhibit most chances of data loss, but as I am very much still a beginner when it comes to scripting in Roblox, I am not sure if everything is done in the best way. Everything seems to function as intended, though I haven’t checked how well it works with over 2 people yet. So, is there any possible issues that could come from my system? Below I have two scripts, the dataHandler and dataModule. (Excuse my use of semi-colons, it’s a habit I picked up from earlier endeavors into programming, working on dropping it as it’s not necessary in lua.)

Personally I’m most concerned if any issues will come from my dataHandler, as well as my current system for backing up data in the saveData method.

DataHandler


local dataModule = require(game:GetService("ServerScriptService").modules:WaitForChild("dataModule"));
local autoSaveStarted = 0;


game:GetService("Players").PlayerAdded:Connect(function(plr)
	local loadedData = dataModule.loadData(plr);
	getData:FireClient(plr, loadedData);
end)

game:GetService("Players").PlayerRemoving:Connect(function(plr)
	local success, save = pcall(function()
		dataModule.saveData(plr)
	end)
	if success and autoSaveStarted == 0 then
		dataModule.removeData(plr);
	end
end)

game:BindToClose(function()
	print("Server: Shutting down, checking for data to save...");
	local players = game:GetService("Players"):GetChildren()
	if players ~= nil then
		for i, v in pairs(players) do
			local success, save = pcall(function()
				dataModule.saveModule(v);
			end)
			if success then
				
			else
				print("Server: Data already removed for..."..v.UserId);
			end
		end		
	else
		print("Server: No players found.")
	end
end)

function resetData(plr)
	dataModule.createData(plr);
	local returnedData = dataModule.returnData(plr)
	getData:FireClient(plr, returnedData);
end

function autosave()
	local players = game:GetService("Players"):GetChildren();
	if players ~= nil then
		autoSaveStarted = 1;
		for i, v in pairs(players) do
			local success, save = pcall(function()
				dataModule.saveData(v);				
			end)
			if success then
				print("Autosave: Successfully autosaved data for..."..v.UserId);
			else
				print("Autosave: Couldn't autosave data for..."..v.UserId);
			end
		end
		wait(6);
		autoSaveStarted = 0;
	end
end

while true do
	wait(300)
	autosave();
end

resetEvent.OnServerEvent:Connect(resetData);

DataModule

local key = "A";
local version = 6;
local plrData = game:GetService("DataStoreService"):GetDataStore(key..version);
local plrDataBackup = game:GetService("DataStoreService"):GetDataStore(key..version.."backup");

local tempStorage = {};

local module = {}

function module.createData(plr)
	local id = plr.UserId;
	
	local defaultData = {
		userid = id,
		class="Human",
		level=1,
		exp=0,
		points=0,
		strength=0,
		constitution=0,
		agility=0,
		mana=0,
		tries=5
	}
	
	local success, save = pcall(function()
		--plrData:SetAsync(id, defaultData)
		module.removeData(plr);
		table.insert(tempStorage, #tempStorage+1, defaultData);
	end)
	
	if not success then
		print("Create Data: Failed to properly create data for..."..id);
	else
		print("Create Data: Successfully created data for..."..id);
		return defaultData;
	end
end

function module.loadData(plr)
	local loaded = false;
	for i, v in pairs(tempStorage) do
		if v.userid == plr.UserId then
			loaded = true;
		end
	end
	
	if not loaded then
		local data = nil;
		local success, save = pcall(function()
			data = plrData:GetAsync(plr.UserId);
		end)
		if success and data ~= nil then
			table.insert(tempStorage, #tempStorage+1, data);
			print("Load Data: Successfully got data for..."..plr.UserId);
			return data;
		else
			print("Load Data: Failed to get data for..."..plr.UserId.."...trying backup data.");
			local backupData = nil;
			local backupSuccess, save = pcall(function()
				backupData = plrDataBackup:GetAsync(plr.UserId);
			end)
			
			if backupSuccess and backupData ~= nil then
				table.insert(tempStorage, #tempStorage+1, backupData)
				return backupData;
			else
				print("Load Data: Failed to get backup data for..."..plr.UserId.."...initializing new data.");
				local newDataL = module.createData(plr);
				return newDataL;		
			end
		end
	else
		print("Load Data: Data already loaded for..."..plr.UserId);
	end
end

function module.saveData(plr)
	local currentData = nil;
	for i, v in pairs(tempStorage) do
		if v.userid == plr.UserId then
			currentData = v;
		end
	end
	local success, save = pcall(function()
		plrData:UpdateAsync(plr.UserId, function(od)
			local data = currentData;
			return data;
		end)
	end)
	
	local backupSuccess, save = pcall(function()
		plrDataBackup:UpdateAsync(plr.UserId, function(od)
			local data = currentData;
			return data;
		end)
	end)
	
	if success then
		print("Save Data: Successfully saved data for..."..plr.UserId);
	else
		print("Save Data: Failed to save data for..."..plr.UserId);		
	end
	
	if backupSuccess then
		print("Save Data: Successfully saved backup data for..."..plr.UserId);
	else
		print("Save Data: Failed to save backup data for..."..plr.UserId);
	end
end

function module.updateData(plr, key, change)
	if key == "class" then
		for i, v in pairs(tempStorage) do
			if v.userid == plr.UserId then
				v[key] = change;
			end
		end
	else
		for i, v in pairs(tempStorage) do
			if v.userid == plr.UserId then
				v[key] = v[key] + change;
			end
		end
	end
	
	updateStats:FireClient(plr, key, change);
end

function module.returnData(plr)
	local userData = nil;
	for i, v in pairs(tempStorage) do
		if v.userid == plr.UserId then
			userData = v;
			break;
		end
	end
	return userData;
end

function module.removeData(plr)
	for i, v in pairs(tempStorage) do
		if v.userid == plr.UserId then
			table.remove(tempStorage, i);
			print("Remove Data: Successfully removed stored data for..."..plr.UserId);
		end
	end
end

return module

Have you considered using DataStore2? I imagine it would be easier to use and interact with considering how bulletproof it seems to be. Check it out: How to use DataStore2 - Data Store caching and data loss prevention.

1 Like

I tried it in the past, but my aim right now is to get a great grasp on datastores and scripting in general. :slight_smile:

I’m not sure if you want advice on formatting and et cetera, so I won’t bother with that; there are some parts of your code I don’t see as idiomatic Luau. While I don’t see anything blatantly wrong with the semantics of either file, perhaps you can store each value in a BaseValue instance as opposed to constantly interacting with tempStorage? This means you could also attach listeners to each value for whatever reason.