skynet框架:日程表服务
实现一个日程表服务(crontab),支持
- 服务启动自动对齐系统时间,以秒为单位检查触发定时任务(task);
- 以服务(同节点)为单位注册定时任务方式:
1)以自然时间字符串方式:2024-01-01 00:00:00
2)以定时间隔方式:每秒/每分/每时/每天/每周/每月/每年 - 取消指定定时任务;
- 定时任务触发逻辑支持超时释放;
- 单例;
对齐系统时间:服务启动时计算当前时间到下一秒的间隔,定时驱动日程表心跳raw_timeout
local _, offset = math.modf(skynet.time())
local leftms = 100 - timeout_factor(offset) -- 到下一秒的间隔值
skynet.timeout(leftms, raw_timeout)
function raw_timeout()
skynet.timeout(100, raw_timeout) -- 每秒触发
skynet.fork(remind_tasks)
end
function remind_tasks()
local cbt = skynet.timefloor()
self._t_frames[cbt-1] = nil -- 释放上一秒的任务集
local frames = self._t_frames[cbt]
if table.empty(frames) then
return
end
for _, frame in ipairs(frames) do
frame:remind() -- 触发任务处理
end
end
提供注册任务API
---@description 为source服务注册自然时间为timestr的定时任务
---@param
---| '"time2str"' # 自然时间字符串
---| '"source"' # 服务id
---| '"proto"' # 触发回调时使用的协议类型,默认是lua
---| '"cmd"' # 任务回调的CMD
---| '"ltype"' # 循环任务的类型:每秒/每分等
---| '"..."' # 透传给任务回调处理的参数
function mark(timestr, source, proto, cmd, ltype, ...) end
---@description 为source服务注册循环类型定时任务,默认使用lua类型
---@param
---| '"ltype"' # 循环任务的类型:每秒/每分等
---| '"lparam"' # 循环任务的自定义参数
function loopmark(ltype, lparam, source, cmd, ...) end
---@description 循环任务的类型
TASK_LOOP_TYPE_SEC = 1 ---# 每秒
TASK_LOOP_TYPE_MIN = 2 ---# 每分钟
TASK_LOOP_TYPE_HUR = 3 ---# 每小时
TASK_LOOP_TYPE_DAY = 4 ---# 每天
TASK_LOOP_TYPE_WEK = 5 ---# 每周
TASK_LOOP_TYPE_MON = 6 ---# 每月
TASK_LOOP_TYPE_YEA = 7 ---# 每年
取消定时任务API
---@description 取消source服务的定时任务
function unmark(timestr, source, cmd, ltype) end
任务处理逻辑需要处理容错、与主流程解耦
---@description 对source服务发起请求,超时interval返回失败处理
function safe_call(interval, source, proto, cmd, ...)
interval = interval or 1
local co = coroutine.running()
local ret
skynet.fork(function(...)
ret = table.pack(skynet.call(source, proto, cmd, ...) or false)
if co then skynet.wakeup(co) end
end, ...)
skynet.sleep(interval * 100)
co = nil
if not ret then return false end
return table.unpack(ret)
end
设计skynet框架下服务
local skynet = require "skynet"
local debug = require "skynet.debug"
local Command = { _crontab = nil }
function Command.init()
Command._crontab = require "crontab"
assert(Command._crontab, "_crontab init error")
end
local function proto_lua_dispatch(_, _, cmd, ...)
local f = Command._crontab[cmd]
if f then
local msg, len = skynet.pack(f(Command._crontab, ...))
skynet.ret(msg, len)
else
skynet.error(string.format("Unknown command : [%s]", tostring(cmd)))
skynet.response()(false)
end
end
local function init()
skynet.init(Command.init)
skynet dispatch("lua", proto_lua_dispatch)
end
skynet.start(init)
本文来自博客园,作者:linxx-,转载请注明原文链接:https://www.cnblogs.com/linxx-/p/18299467