BindToClose & Data Loss Risk


#1

I have a quick question regarding BingToClose. Would both Options [1 and 2] below attempt to wait until all data is saved before closing down?? Or would it only be the case of Option 2.

The problem with Option 2 is that the forward declaration “save” remains = nil, so error.

  • Is there a way to fix that?
  • How can I synchronously save the players’ data?

Could it then be as simple as Option 3… Should I just let it go with the flow?

  • Would I then risk some data failing to save in time?

DataService:saveData(Player) returns a BindableEvent.

Option 1
game:BindToClose(function()
	local save;
	print("save from close")
	
	for _,Player in pairs(game.Players:GetPlayers()) do
		spawn(function()
			save = DataService:saveData(Player) 
			save:Fire()
			save.Event:Wait()
		end)
	end			

	return;
end)
Option 2
game:BindToClose(function()
	local save;
	print("save from close")
	
	for _,Player in pairs(game.Players:GetPlayers()) do
		spawn(function()
			save = DataService:saveData(Player) 
			save:Fire()
		end)
	end		
		
	save.Event:Wait()
	return;
end)
Option 3
game:BindToClose(function()
	for _,Player in pairs(game.Players:GetPlayers()) do
		DataService:saveData(Player):Fire() 
	end		
end)

#2

BindToClose() will hold off shutting down the data model until one of the following is true:

  • All BindToClose() callbacks have returned (if they yield, it will wait for them) AND all outstanding data store requests have finished
  • 30 seconds have passed

As far as I know, the best thing to do is to:

  • Start all of your player data saving tasks simultaneously.
  • Only return from the BindToClose callback when all tasks have finished.

Your examples seem to rely on a framework. I’ll provide an example in terms that don’t require unspecified framework behavior.

game:BindToClose(function()
    local tasks = {}
    for _,player in pairs(Players:GetPlayers()) do
        tasks[#tasks+1] = function()
            -- this function shouldn't return until it's finished its task
            -- I assume you do that like this using your framework
            save = DataService:saveData(Player) 
	    save:Fire()
	    save.Event:Wait()
        end
    end

    local numComplete = 0
    local finished = Instance.new("BindableEvent")

    for i = 1, #tasks do
        spawn(function()
            pcall(tasks[i]) -- handle errors somehow
            numComplete = numComplete + 1
            if numComplete == #tasks then
                finished:Fire()
            end
        end)
    end

    finished:Wait()
end)