Function will not run after script gets destroyed

I have a server script under a tool that calls a function from a module script under replicatedstorage, that runs a function after a certain duration. But if the tool gets removed, it does not continue running.

ServerScript Under tool

Combat:SetCombatEnabled(Target, false, Config.RagdollDuration)

Module

local Combat = {
	GetCombatEnabled = function(_, Player)
		return Player:GetAttribute("CombatEnabled")
	end,
}

Combat.SetCombatEnabled = function(_, Player, Enabled, Duration)
	Player:SetAttribute("CombatEnabled", Enabled)
	
	if Duration then
		task.delay(Duration, function()
			Player:SetAttribute("CombatEnabled", not Enabled)
		end)
	end
end

return Combat

Couple of options,

  1. Hacky, but simpler, parent the tool to nil instead of destroying. This will allow the script to finish execution. idr if it will GC automatically in this case, personally id just call :Destroy() internally to ensure it does once you have toggled combat.

  2. Still use :Destroy() to remove the tool, in a separate script monitor the players backpack. When .ChildRemoved is fired, run a check on the backpack to see if they should be in combat and update accordingly. This just moves the logic out from inside the tool.

2 is probably the better option to prevent having repeated code in tools and minimize clutter.

I dug into it and this sounds like a bug. The thread never gets closed, and it’s still registered in the scheduler. Maybe worth sending a bug report. There’s no way this can be desired. It even breaks on my own timer implementation using RunService.Heartbeat. I’m guessing it’s an overzealous optimization.