Data isn't saving at timed intervals and upon player leaving

Hi everyone, I am recently making a new game, and I’m a day from release day. However, I just held a huge testing session and I learned some pretty terrible things about my datastore saving; it doesn’t work at all. My sample size was a few hours of hopping in and out of servers and nothing saved.

function SaveAllData(playerToSave)
	local boughtItems = inventoryToSave
	
	local function Save(players)
		
		for _, player in pairs(players) do
			
			coroutine.wrap(function()
				local data = defaultData
				
				local jadeToSave = player.PlayerInfo.Jade.Value
				local levelToSave = player.PlayerInfo.Level.Value
				local expToSave = player.PlayerInfo.Exp.Value
				
				data["Jade"] = jadeToSave
				data["Level"] = levelToSave
				data["Exp"] = expToSave
				
				local inventory = Deluge2Store:GetAsync(dataKey .. player.UserId)["Inventory"]
				
				for i, v in pairs(boughtItems) do
					if i == tostring(player.UserId) then
						for _, k in pairs(v) do
							table.insert(inventory, k)
						end
					end
				end
				
				data["Inventory"] = inventory
				
				Deluge2Store:SetAsync(dataKey .. player.UserId, data)
				
			end)()
			
		end
		
		inventoryToSave = {}
	
	end
	
	if playerToSave then
		playerToSave = {playerToSave}
	else
		playerToSave = game.Players:GetPlayers()
	end
	
	Save(playerToSave)
	
end

while wait(60) do
	SaveAllData()
end

game:BindToClose(SaveAllData)

game.Players.PlayerRemoving:Connect(SaveAllData)

So as you can see, this SaveAllData function runs at timed intervals, when a player leaves, and when the game binds to a close. However, the script throws no errors, and saves nothing at all for when I return. DataKey = “Data-”. All the values are integers in a fake leader-board I made. The bought items loop is for getting all the items the player bought and saves them. So as you can see, I’m kind of just dumbfounded on how this could not have worked.

The issue is since the while loop above is never ending, the DataModel::BindToClose method is never able to be called, neither is the RBXScriptSignal::Connect.

The fix is to move the loop to the bottom:

game:BindToClose(SaveAllData)
game:GetService("Players").PlayerRemoving:Connect(SaveAllData)

while true do
    wait(60)
    SaveAllData()
end

And finally, the while wait() do idiom is bad practice.

Just how slow am I :man_facepalming: Thanks, I’ll check out the alternative while wait() practice and I’ll fix my code and test it.