参考云风大神的例子,对其进行了改进,支持多次提交单个日程,改变时间后,提前日程触发时间。

--[[
t提供了两种方案
方案1和2
]] local skynet = require "skynet"
local service = require "skynet.service" local schedule = {}
local service_addr -- ttime = { month=, day=, wday=, hour= , min= }
function schedule.submit(ttime) return skynet.call(service_addr, "lua", ttime)
-- TOO(do somthing)
-- skynet.error(" schedule.submit")
end function schedule.changetime(ttime)
local tmp = {}
for k, v in pairs(ttime) do
tmp[k] = v
end
tmp.changetime = true
return skynet.call(service_addr, "lua", tmp) end skynet.init(function()
local schedule_service = function()
local skynet = require "skynet"
local task = {session = ,difftime = }
local tasksession = {} local function next_time(now, ttime) -- 参数现在的时间,日程时间
local ntime = {
year = now.year,
month = now.month,
day = now.day,
hour = ttime.hour or ,
min = ttime.min or ,
sec = ttime.sec,
}
-- skynet.error(now.year,now.month,now.day,now.hour,now.min,now.sec,now.wday)
-- skynet.error(ttime.year,ttime.month,ttime.day,ttime.hour,ttime.min,ttime.sec,ttime.wday)
-- skynet.error(ntime.year,ntime.month,ntime.day,ntime.hour,ntime.min,ntime.sec,ntime.wday) if ttime.wday then -- 每周的活动
-- set week
assert(ttime.day == nil and ttime.month == nil)
ntime.day = ntime.day + ttime.wday - now.wday
local t = os.time(ntime)
if t < now.time then
ntime.day = ntime.day +
end
else -- 如果日程时间使日期的话
-- set day,no week day
if ttime.day then
ntime.day = ttime.day
end
if ttime.month then
ntime.month = ttime.month
end
local t = os.time(ntime) -- 换成秒
if t < now.time then --时间和现在比是过去的时间变成下个月或者下一年
if ttime.month then
ntime.year = ntime.year +
else
ntime.month = ntime.month +
end
end
end
skynet.error("next_time ",ntime.year,ntime.month,ntime.day,ntime.hour,ntime.min,ntime.sec,ntime.wday)
return os.time(ntime) -- 将下次日程的时间换成秒返回
end local function changetime(ttime)
local ctime = math.floor(skynet.time()) --向下取整
--local now = math.floor(skynet.time())
skynet.error("changetime",ctime)
local current = os.date("*t",ctime) --将ctime 转换成*t的表结构
current.time = ctime -- 保存原来的时间
if not ttime.hour then -- 如果原来表结构中没有小时,将现在的小时赋值给它
ttime.hour = current.hour
end
if not ttime.min then -- 如果原来表结构中没有分钟,将现在的分钟赋值给它
ttime.min = current.min
end
ttime.sec = current.sec -- 现在的秒赋值给它
local ntime = next_time(current,ttime) -- 计算出下一次日程的时间 skynet.error(string.format("Change time to nex %s",os.date(nil,ntime)))
skynet.error(string.format("Change time to cur %s",os.date(nil,ctime)))
local unique_diff = os.difftime(ntime,ctime) -- 方案1计算出下次日程距离现在时间还有多少秒
--task.difftime = os.difftime(ntime,ctime)
--skynet.error("changetime task.difftime",task.difftime)
skynet.error("changetime unique_diff",unique_diff)
for k, v in pairs(task) do -- 日期改变了才 遍历日程表,唤醒所有挂起的线程
local ttask_diff = --方案1
if type(v) == "table" then
ttask_diff = os.difftime(v.time, math.floor(skynet.time())) -- 方案1 if unique_diff > ttask_diff then --方案1
task[k].difftime = ttask_diff --方案1
--task.difftime = ttask_diff
end
skynet.error("changetime unique_diff",k,unique_diff)
skynet.error("changetime task.difftime",k,task.difftime)
skynet.error("changetime ttask_diff",k,ttask_diff)
skynet.error("changetime session",k, type(v.co))
skynet.wakeup(v.co) -- 唤醒服务
end
end
skynet.ret()
end -- {year = 2020, month=12, day=31, hour=20 , min=30}
local function submit(_, addr, ttime)
if ttime.changetime then
return changetime(ttime)
end
local session = task.session +
task.session = session
task[session] = {time = , address = addr, difftime = }-- 方案1
skynet.error("submit task.session",task.session)
repeat -- 循环 直到时间到了 local now = math.floor(skynet.time()) -- 真的当前时间戳
skynet.error(string.format("submit now %s",os.date(nil,now)))
local ctime = now + task[session].difftime -- 方案1现在的时间+日程距离现在的秒数 = 假的当前的时间戳
local ctime = now + task.difftime -- 方案2
skynet.error("submit task[session].difftime",session,task[session].difftime)
-- if ctime > task[session].time then -- 方案2
-- break -- 方案2
-- end-- 方案2
local current = os.date("*t",ctime) -- 变成结构
current.time = ctime -- 增加一项time local ntime = next_time(current,ttime) -- 计算下次日程时间
skynet.error(string.format("submit ntime %s",os.date(nil,ntime)))
skynet.error(string.format("submit ntime %d",ntime))
skynet.error(string.format("submit ctime %s",os.date(nil,ctime))) task[session].time = ntime -- 方案1
task[session].co = coroutine.running()-- 方案1 local diff = os.difftime(ntime,ctime)
skynet.error("submit sleep",diff,session)
until skynet.sleep(diff * ) ~= "BREAK" -- 休眠diff * 100 task[session] = nil
skynet.ret()
end skynet.start(function()
skynet.dispatch("lua", submit)
skynet.info_func(function()
local info = {}
for k, v in pairs(task) do
if type(v) == "table" then
table.insert(info, {
time = os.date(nil, v.time),
address = skynet.address(v.address),
})
end
return info
end
end)
end)
end
service_addr = service.new("schedule", schedule_service) -- 启动一个服务
end)
return schedule

方案一主要思路是:在repeat循环中每次都会计算一个假的当前时间。通过假的当前时间计算出日程的下次触发时间,然后计算下次日程的触发时间和假的当前时间的差值来决定线程挂起的时长。如何改变假的当前时间是通过changetime接口改变的。在这个api中会改变task.difftime的值,然后把全部线程全都唤醒,继续执行repeat循环,重新计算下次日程的触发时间,然后重新计算假的当时间和下次触发的时差=线程挂起的时长。如果改变的时刻在日程触发时刻的后面,要求改变时刻之前的日程全部触发,方案1和2都可以,如果提交了乐意日程触发时刻比现在真实的会见还靠前,则方案2不可行(不过这种情况一般不会有)

skynet框架之日程表设计的更多相关文章

  1. [自制操作系统] BMP格式文件读取&图形界面系统框架/应用接口设计

    本文将介绍在本人JOS中实现的简单图形界面应用程序接口,应用程序启动器,以及一些利用了图形界面的示例应用程序. 本文主要涉及以下部分: 内核/用户RW/RW调色板framebuffer共享区域 8bi ...

  2. 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序

    如何在Visual Studio 2017中使用C# 7+语法   前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...

  3. Python接口自动化测试框架实战 从设计到开发

    第1章 课程介绍(不要错过)本章主要讲解课程的详细安排.课程学习要求.课程面向用户等,让大家很直观的对课程有整体认知! 第2章 接口测试工具Fiddler的运用本章重点讲解如何抓app\web的htt ...

  4. 十大开源的.NET用户界面框架 让GUI设计不再犯难

    选择一款合适的GUI框架是.NET开发中比较重要但又很棘手的问题,因为用户界面相当于一款应用的"门面",直接面向用户.好的UI更能吸引用户,有时甚至成为决定一款应用成败的关键.下面 ...

  5. ACE框架 同步原语设计

    ACE框架常用的同步机制设计成统一的原语接口.同步原语使用系统平台(操作系统,多线程库)提供的同步原语,并为系统平台不提供的同步原语提供模拟实现.ACE框架使用了外观模式和适配器分两层,将同步原语统一 ...

  6. iOS开源照片浏览器框架SGPhotoBrowser的设计与实现

    简介 近日在制作一个开源加密相册时附带着设计了一个照片浏览器,在进一步优化后发布到了GitHub供大家使用,该框架虽然没有MWPhotoBrowser那么强大,但是使用起来更为方便,操作更符合常规相册 ...

  7. RSF 分布式 RPC 服务框架的分层设计

    RSF 是个什么东西? 一个高可用.高性能.轻量级的分布式服务框架.支持容灾.负载均衡.集群.一个典型的应用场景是,将同一个服务部署在多个Server上提供 request.response 消息通知 ...

  8. 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架

    一.系列简述 本篇起,将通过一系列文章,去描述如何构建一个应用开发框架,并以作者开发的框架为例,逐个点展开分析,如何从零开始,构建自己的开发框架. 本系列文章的目的,是带领有一编程经验的人,通过动手, ...

  9. 基于ASP.Net Core开发一套通用后台框架记录-(数据库设计(权限模块))

    写在前面 本系列博客是本人在学习的过程中搭建学习的记录,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 前期我不会公开源码,我想是一点点敲代码,不然复制.粘贴那就没意思了. ...

随机推荐

  1. vlookup使用

    数据处理过程中,需要excel进行简单的操作,比如vlookup,摸索之后,总结如下:

  2. 2018.5.3 maven

     1  maven基本概念  1.1maven是什么 1)软件项目管理和理解工具      2)项目对象模型(Project Object Model,POM)      3)项目的构建.报告和文档的 ...

  3. Beff的学习

    Beff介绍 BeEF,全称The Browser Exploitation Framework,是一款针对浏览器的渗透测试工具. 首先打开kali,直接点击beef图标打开beef 浏览器会默认弹出 ...

  4. SQL Sever 2012版本数据库的完全卸载

    首先再使用的过程中,遇到当前版本和项目数据库服务器的SQL Sever 版本不一致,导致无法正常的数据导入. 所以需要我们将本地的SQL Sever 数据库,进行一个完整的卸载,进而去安装和项目一致的 ...

  5. Python 基础知识(持续更新中)

    内置数据类型:     整型     浮点型     字符串     布尔值     空值 None     列表 list     元组 tuple     字典 dict     集合 set   ...

  6. robotframework之上传功能

    上传功能,分为上传图片以及上传文件 1.上传文件 A)上传文件的html标签为input类型,可以直接输入文本中input文件路径,可以省略点击[上传文件]这一步骤 B)直接输入使用的关键词为:cho ...

  7. websocket 2 rest api

    需要开发一个prometheus 的exporter 使用jmespath 获取对应metrics的数据,并进行转换处理,但是因为那个服务 提供的接口是通过websoket 的实时api,所以基于no ...

  8. Ubuntu下重新安装软件 配置文件不重新生成得问题解决

    apt-get remove nfs dpkg -P nfs apt-get install nfs 按照先remove然后dpkg -P再重新install的顺序.

  9. markdown特殊符号语法

    符号 说明           对应编码 &    AND符号        & < 小于           < > 大于           > _    ...

  10. 代码漏洞扫描描述Cross Site History Manipulation解决办法[dongcoder.com]

    代码漏洞扫描 漏洞描述:Cross Site History Manipulation 简要描述:产品的行为差异或发送不同的反应,在某种程度上暴露了与安全性相关的产品状态,例如特定的操作是否成功.可能 ...