Not running script because past shutdown deadline

hello, my first time working with datastore, I need help optimizing a script where the objective is to save the name and value of more than 150 boolvalues

local DataStoreService = game:GetService("DataStoreService")
local SaveRats = DataStoreService:GetDataStore("SaveRats")

game.Players.PlayerAdded:Connect(function(Player)
	local ratsFolder = Instance.new("Folder", Player)
	ratsFolder.Name = "ratsFolder"
	
	-- rats boolvalue
	local ratsBool = {}
	for i, v in pairs(workspace:WaitForChild("Rats"):GetChildren()) do
		table.insert(ratsBool, v.Name)

		local newRats = Instance.new("BoolValue", ratsFolder)
		newRats.Name = ratsBool[i]
		newRats.Value = false
	end
	
	local success, err = pcall(function()
		return SaveRats:GetAsync(Player.UserId)
	end)
	
	local rats = ratsFolder:GetChildren()
	if success then
		for i = 1, #rats do
			rats[i].Value = SaveRats:GetAsync(Player.UserId..rats[i].Name)
		end
	end
end)

game.Players.PlayerRemoving:Connect(function(Player)
	local rats = Player.ratsFolder:GetChildren()
	for i=1, #rats do
		rats[i].Value = SaveRats:SetAsync(Player.userId..rats[i].Name,rats[i].Value)
	end
end)

The script does not save some bools because this message “Not running script because past shutdown deadline” appears

add this to the bottom of the script

game:BindToClose(function()
	for i, player in pairs(game.Players:GetPlayers()) do
		-- the same thing from PlayersRemoving except it does it for every player
		local rats = player.ratsFolder:GetChildren()
		for i=1, #rats do
			rats[i].Value = SaveRats:SetAsync(player.userId..rats[i].Name,rats[i].Value)
		end
	end
end)

Just Follow datastore tutorail

And i also see no reason in doing table.insert()

it keeps giving the same error because this script is saving the bools one by one causing the server to shut down before it saves, one idea I had was to put the 150 boolvalues ​​inside a table and then call SaveRats:SetAsync just once, but I don’t know how I can do this

table.insert(ratsBool, v.Name) was just to get the name of the rats that are in the workspace and put it in the bools so when the bool is true the rat will be destroyed

(I’m making a find the markers style game)

You’re creating an individual data store address for each rat in the player’s inventory; that’s creating a dozen different data store keys for one player (and will lead to data loss and rate limiting)


You’re doing 2 different data requests here.

  1. One if for the Player’s UserId (which doesn’t seem to have any sort of data saved for it)
  2. Is the Player’s UserId + the rat name, which shouldn’t be set up like that

This can stay the same, because you can store all the rat information to a table connected to the player’s UserId as a datastore address

local success, err = pcall(function()
	return SaveRats:GetAsync(Player.UserId)
end)

The easiest way to fix this is to use tables. Store all the collected rats into a list and return that listen when the player’s data is loaded.

if success and err then -- the request can be successful, but that doesn't mean that the player has any data 
    -- This may not make sense right now because the way you save information is different
    -- but, the way this is working is by looping through the player's data store information
    -- and setting the found rats to the data store info (if found)
	for _, name in err do
        local value = ratsFolder:FindFirstChild(name) -- since you store the rat's name, look for the rat via its name
        if not value then
            warn(`Rat {name} does not exist`) -- This tells you if the rat trying to be loaded still exists within the game
            continue -- Skip this iteration
        end
		value.Value = true -- since it exists in the data store, set the value of the rat BoolValue to true
	end
elseif not success then
    warn(err) -- THIS IS IMPORTANT!!! This tells you if there was a problem saving/loading data!
end

You don’t need to assign anything using SetAsync. SetAsync also returns DataStore key information, not the value being stored. (Docs)

You really just need to iterate over the player’s rat folder and store all of the info to a table.

local info = {} -- create a blank table to be saved
for _, rat in Player.ratsFolder:GetChildren() do
    if rat.Value == true then -- check if this rat was found
        table.insert(info, rat.Name) -- add the rat to the table
    end
end

Now, you would do the same thing you did for loading the information (use a pcall).

local success, err = pcall(function()
    SaveRats:SetAsync(Player.UserId, info) -- save the info using the player's userid as the key.
end)

if not success then
    warn(err) -- like before, if there was a problem saving, let the console tell you what the issue is!
end

However, this is still not the most efficient way to save data. You’d want to also utilize game.BindToClose like @teamassists mentioned. Additionally, you should have a separate function to save data to make your code less repetitive (when talking about game.BindToClose).

local function SavePlayerData(Player: Player)
    --... save info
end

game.Players.PlayerRemoving:Connect(SavePlayerData) -- this will call the function when the event fires
game:BindToClose(function()
   for _, p in game.Players:GetPlayers() do -- loop through all the players still in the game
       task.spawn(SavePlayerData, p) -- call the function on players still left in the game
   end
end)

This was a guide on how to fix your data store script, also, the reason why you were running into shutdown deadline errors was because of the aforementioned multiple key storing.

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.