mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 09:18:53 +00:00
1b5e29c62b
OnTime always built scheduledTimestamp from the date of the current tick, so a tick that skipped the 23:59 minute compared it against 23:59 of the next day. The run was dropped without a trace. Fall back to the previous day when the scheduled time lands in the future.
84 lines
2.3 KiB
Lua
84 lines
2.3 KiB
Lua
---@class CronJob
|
|
---@field h number
|
|
---@field m number
|
|
---@field cb function|table
|
|
|
|
---@type CronJob[]
|
|
local cronJobs = {}
|
|
---@type number|false
|
|
local lastTimestamp = false
|
|
|
|
---@param h number
|
|
---@param m number
|
|
---@param cb function|table
|
|
function RunAt(h, m, cb)
|
|
cronJobs[#cronJobs + 1] = {
|
|
h = h,
|
|
m = m,
|
|
cb = cb,
|
|
}
|
|
end
|
|
|
|
---@return number
|
|
function GetUnixTimestamp()
|
|
return os.time()
|
|
end
|
|
|
|
---@param timestamp number
|
|
function OnTime(timestamp)
|
|
local function scheduledAt(job, dayOffset)
|
|
return os.time({
|
|
hour = job.h,
|
|
min = job.m,
|
|
sec = 0, -- Assuming tasks run at the start of the minute
|
|
day = os.date("%d", timestamp) + dayOffset,
|
|
month = os.date("%m", timestamp),
|
|
year = os.date("%Y", timestamp),
|
|
})
|
|
end
|
|
|
|
for i = 1, #cronJobs, 1 do
|
|
local scheduledTimestamp = scheduledAt(cronJobs[i], 0)
|
|
|
|
if scheduledTimestamp > timestamp then
|
|
scheduledTimestamp = scheduledAt(cronJobs[i], -1)
|
|
end
|
|
|
|
if not lastTimestamp or lastTimestamp < scheduledTimestamp then
|
|
local d = os.date('*t', scheduledTimestamp).wday
|
|
cronJobs[i].cb(d, cronJobs[i].h, cronJobs[i].m)
|
|
end
|
|
end
|
|
end
|
|
|
|
---@return nil
|
|
function Tick()
|
|
local timestamp = GetUnixTimestamp()
|
|
|
|
if not lastTimestamp or os.date("%M", timestamp) ~= os.date("%M", lastTimestamp) then
|
|
OnTime(timestamp)
|
|
lastTimestamp = timestamp
|
|
end
|
|
|
|
SetTimeout(60000, Tick)
|
|
end
|
|
|
|
lastTimestamp = GetUnixTimestamp()
|
|
Tick()
|
|
|
|
---@param h number
|
|
---@param m number
|
|
---@param cb function|table
|
|
AddEventHandler("cron:runAt", function(h, m, cb)
|
|
local invokingResource = GetInvokingResource() or "Unknown"
|
|
local typeH = type(h)
|
|
local typeM = type(m)
|
|
local typeCb = type(cb)
|
|
|
|
assert(typeH == "number", ("Expected number for h, got %s. Invoking Resource: '%s'"):format(typeH, invokingResource))
|
|
assert(typeM == "number", ("Expected number for m, got %s. Invoking Resource: '%s'"):format(typeM, invokingResource))
|
|
assert(typeCb == "function" or (typeCb == "table" and type(getmetatable(cb)?.__call) == "function"), ("Expected function for cb, got %s. Invoking Resource: '%s'"):format(typeCb, invokingResource))
|
|
|
|
RunAt(h, m, cb)
|
|
end)
|