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

  1. --[[
  2. t提供了两种方案
  3. 方案12
  4. ]]
  5.  
  6. local skynet = require "skynet"
  7. local service = require "skynet.service"
  8.  
  9. local schedule = {}
  10. local service_addr
  11.  
  12. -- ttime = { month=, day=, wday=, hour= , min= }
  13. function schedule.submit(ttime)
  14.  
  15. return skynet.call(service_addr, "lua", ttime)
  16. -- TOO(do somthing)
  17. -- skynet.error(" schedule.submit")
  18. end
  19.  
  20. function schedule.changetime(ttime)
  21. local tmp = {}
  22. for k, v in pairs(ttime) do
  23. tmp[k] = v
  24. end
  25. tmp.changetime = true
  26. return skynet.call(service_addr, "lua", tmp)
  27.  
  28. end
  29.  
  30. skynet.init(function()
  31. local schedule_service = function()
  32. local skynet = require "skynet"
  33. local task = {session = ,difftime = }
  34. local tasksession = {}
  35.  
  36. local function next_time(now, ttime) -- 参数现在的时间,日程时间
  37. local ntime = {
  38. year = now.year,
  39. month = now.month,
  40. day = now.day,
  41. hour = ttime.hour or ,
  42. min = ttime.min or ,
  43. sec = ttime.sec,
  44. }
  45. -- skynet.error(now.year,now.month,now.day,now.hour,now.min,now.sec,now.wday)
  46. -- skynet.error(ttime.year,ttime.month,ttime.day,ttime.hour,ttime.min,ttime.sec,ttime.wday)
  47. -- skynet.error(ntime.year,ntime.month,ntime.day,ntime.hour,ntime.min,ntime.sec,ntime.wday)
  48.  
  49. if ttime.wday then -- 每周的活动
  50. -- set week
  51. assert(ttime.day == nil and ttime.month == nil)
  52. ntime.day = ntime.day + ttime.wday - now.wday
  53. local t = os.time(ntime)
  54. if t < now.time then
  55. ntime.day = ntime.day +
  56. end
  57. else -- 如果日程时间使日期的话
  58. -- set day,no week day
  59. if ttime.day then
  60. ntime.day = ttime.day
  61. end
  62. if ttime.month then
  63. ntime.month = ttime.month
  64. end
  65. local t = os.time(ntime) -- 换成秒
  66. if t < now.time then --时间和现在比是过去的时间变成下个月或者下一年
  67. if ttime.month then
  68. ntime.year = ntime.year +
  69. else
  70. ntime.month = ntime.month +
  71. end
  72. end
  73. end
  74. skynet.error("next_time ",ntime.year,ntime.month,ntime.day,ntime.hour,ntime.min,ntime.sec,ntime.wday)
  75. return os.time(ntime) -- 将下次日程的时间换成秒返回
  76. end
  77.  
  78. local function changetime(ttime)
  79. local ctime = math.floor(skynet.time()) --向下取整
  80. --local now = math.floor(skynet.time())
  81. skynet.error("changetime",ctime)
  82. local current = os.date("*t",ctime) --将ctime 转换成*t的表结构
  83. current.time = ctime -- 保存原来的时间
  84. if not ttime.hour then -- 如果原来表结构中没有小时,将现在的小时赋值给它
  85. ttime.hour = current.hour
  86. end
  87. if not ttime.min then -- 如果原来表结构中没有分钟,将现在的分钟赋值给它
  88. ttime.min = current.min
  89. end
  90. ttime.sec = current.sec -- 现在的秒赋值给它
  91. local ntime = next_time(current,ttime) -- 计算出下一次日程的时间
  92.  
  93. skynet.error(string.format("Change time to nex %s",os.date(nil,ntime)))
  94. skynet.error(string.format("Change time to cur %s",os.date(nil,ctime)))
  95. local unique_diff = os.difftime(ntime,ctime) -- 方案1计算出下次日程距离现在时间还有多少秒
  96. --task.difftime = os.difftime(ntime,ctime)
  97. --skynet.error("changetime task.difftime",task.difftime)
  98. skynet.error("changetime unique_diff",unique_diff)
  99. for k, v in pairs(task) do -- 日期改变了才 遍历日程表,唤醒所有挂起的线程
  100. local ttask_diff = --方案1
  101. if type(v) == "table" then
  102. ttask_diff = os.difftime(v.time, math.floor(skynet.time())) -- 方案1
  103.  
  104. if unique_diff > ttask_diff then --方案1
  105. task[k].difftime = ttask_diff --方案1
  106. --task.difftime = ttask_diff
  107. end
  108. skynet.error("changetime unique_diff",k,unique_diff)
  109. skynet.error("changetime task.difftime",k,task.difftime)
  110. skynet.error("changetime ttask_diff",k,ttask_diff)
  111. skynet.error("changetime session",k, type(v.co))
  112. skynet.wakeup(v.co) -- 唤醒服务
  113. end
  114. end
  115. skynet.ret()
  116. end
  117.  
  118. -- {year = 2020, month=12, day=31, hour=20 , min=30}
  119. local function submit(_, addr, ttime)
  120. if ttime.changetime then
  121. return changetime(ttime)
  122. end
  123. local session = task.session +
  124. task.session = session
  125. task[session] = {time = , address = addr, difftime = }-- 方案1
  126. skynet.error("submit task.session",task.session)
  127. repeat -- 循环 直到时间到了
  128.  
  129. local now = math.floor(skynet.time()) -- 真的当前时间戳
  130. skynet.error(string.format("submit now %s",os.date(nil,now)))
  131. local ctime = now + task[session].difftime -- 方案1现在的时间+日程距离现在的秒数 = 假的当前的时间戳
  132. local ctime = now + task.difftime -- 方案2
  133. skynet.error("submit task[session].difftime",session,task[session].difftime)
  134. -- if ctime > task[session].time then -- 方案2
  135. -- break -- 方案2
  136. -- end-- 方案2
  137. local current = os.date("*t",ctime) -- 变成结构
  138. current.time = ctime -- 增加一项time
  139.  
  140. local ntime = next_time(current,ttime) -- 计算下次日程时间
  141. skynet.error(string.format("submit ntime %s",os.date(nil,ntime)))
  142. skynet.error(string.format("submit ntime %d",ntime))
  143. skynet.error(string.format("submit ctime %s",os.date(nil,ctime)))
  144.  
  145. task[session].time = ntime -- 方案1
  146. task[session].co = coroutine.running()-- 方案1
  147.  
  148. local diff = os.difftime(ntime,ctime)
  149. skynet.error("submit sleep",diff,session)
  150. until skynet.sleep(diff * ) ~= "BREAK" -- 休眠diff * 100
  151.  
  152. task[session] = nil
  153. skynet.ret()
  154. end
  155.  
  156. skynet.start(function()
  157. skynet.dispatch("lua", submit)
  158. skynet.info_func(function()
  159. local info = {}
  160. for k, v in pairs(task) do
  161. if type(v) == "table" then
  162. table.insert(info, {
  163. time = os.date(nil, v.time),
  164. address = skynet.address(v.address),
  165. })
  166. end
  167. return info
  168. end
  169. end)
  170. end)
  171. end
  172. service_addr = service.new("schedule", schedule_service) -- 启动一个服务
  173. end)
  174. 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. windows下配置maven

    首先下载好maven的压缩包,然后解压到某个目录下,我解压到了D盘 打开readme.txt 1.2步已经完成,第3步的意思是让我们把bin所在的路径添加到系统变量的path中去 第4步意思是确保的你 ...

  2. 基于mpvue搭建微信小程序

    mpvue是美团开源的一套语法,语法与vue.js一致,快速开发小程序的前端框架.框架基于vue.js核心,修改了vue.js的runtime和compiler实现,使用此框架,开发者可以完全使用vu ...

  3. KendoUI 自定义CheckBoxList

    不多说直接上代码 CSS完整代码: .e-selectboxs-container { display: table; } .e-selectbox { min-width: 100px; heigh ...

  4. HNOI2006公路修建问题

    https://www.luogu.org/problemnew/show/P2323 [题目描述] OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发 ...

  5. WMI tester

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. NFPA, UL

    Who or what is NFPA? NFPA (National Fire Protection Association) is an organization in the USA that ...

  7. Noname

    版本: LayaAir IDE 2.0.1beta laya.core.js ___Laya ColorUtils LayaGLQuickRunner DrawTextureCmd Point Col ...

  8. 解决openstack实例主机名后缀问题

    参考地址https://ask.openstack.org/en/question/26918/change-novalocal-suffix-in-hostname/ 问题现象 可以看到主机名的后缀 ...

  9. 脚本添加crontab任务

    #!/bin/bash export LANG=en_US.utf8 cur_dir=$(cd ``;pwd) job_cmd_info="\n# 每天凌晨5点运行定时删除工具\n" ...

  10. zabbix 监控进程

    参考资料 官方文档. 有时候某个进程挂了没有发现,直到业务中断才想起去检查.希望能有个功能在某个进程挂了以后发出告警. zabbix提供proc.num这个key对后台进程进行监控.原理很简单,其实就 ...