lib/lita/handlers/task_scheduler.rb in lita-task-scheduler-1.0.0 vs lib/lita/handlers/task_scheduler.rb in lita-task-scheduler-1.1.0

- old
+ new

@@ -1,31 +1,43 @@ -require 'pry' -require 'json' +require 'lita/scheduler' module Lita module Handlers class TaskScheduler < Handler + # START:routes route(/^schedule\s+"(.+)"\s+in\s+(.+)$/i, :schedule_command, command: true) route(/^show schedule$/i, :show_schedule, command: true) route(/^empty schedule$/i, :empty_schedule, command: true) + # END:routes - REDIS_TASKS_KEY = name.to_s - + # START:handlers def show_schedule(payload) - schedule = redis.hgetall(REDIS_TASKS_KEY) - - payload.reply schedule_report(schedule) + payload.reply schedule_report(scheduler.get_all) end def empty_schedule(payload) - redis.del(REDIS_TASKS_KEY) + scheduler.clear show_schedule payload end + # START:schedule_command + def schedule_command(payload) + task, timing = payload.matches.last + run_at = parse_timing(timing) + serialized = command_to_hash(payload.message, new_body: task) + + defer_task(serialized, run_at) + show_schedule payload + end + # END:schedule_command + + def scheduler + @_schedule ||= Scheduler.new(redis: redis, logger: Lita.logger) + end + def schedule_report(schedule) - reply = 'Scheduled tasks: ' descriptions = [] schedule.keys.each do |timestamp| play_time = Time.at(timestamp.to_i) tasks_json = schedule[timestamp] @@ -34,79 +46,20 @@ tasks.each do |task| descriptions << "\n - \"#{task.fetch('body')}\" at #{play_time}" end end - reply + (descriptions.empty? ? 'None.' : descriptions.join) + 'Scheduled tasks: ' + (descriptions.empty? ? 'None.' : descriptions.join) end - def schedule_command(payload) - task, timing = payload.matches.last - run_at = parse_timing(timing) - serialized = serialize_message(payload.message, new_body: task) - - defer_task(serialized, run_at) - show_schedule(payload) - end - + # START:defer_task def defer_task(serialized_task, run_at) - key_time = run_at.to_i.to_s - - redis.watch(REDIS_TASKS_KEY) - - tasks = redis.hget(REDIS_TASKS_KEY, key_time) || [] - - tasks = JSON.parse(tasks) unless tasks.empty? - tasks << serialized_task - - redis.hset(REDIS_TASKS_KEY, key_time, tasks.to_json) - - redis.unwatch - - tasks + scheduler.add(serialized_task, run_at) end + # END:defer_task - def execute_tasks(serialized_tasks) - serialized_tasks.each do |serialized_task| - Lita.logger.debug "Resending task #{serialized_task}" - resend serialized_task - end - end - - def run_loop - Thread.new do - loop do - tick - sleep 1 - end - end - end - - def tick - tasks = find_tasks_due - tasks.each { |t| resend t } - Lita.logger.debug "Task loop done for #{Time.now}" - end - - def find_tasks_due - results = [] - timestamps = redis.hkeys(REDIS_TASKS_KEY) - - timestamps.each do |t| - key_time = Time.at(t.to_i) - next unless key_time <= Time.now - - tasks_raw = redis.hget(REDIS_TASKS_KEY, t) - tasks = JSON.parse(tasks_raw) - - results += tasks - redis.hdel(REDIS_TASKS_KEY, t) - end - - results - end - + # START:parse_timing def parse_timing(timing) count, unit = timing.split count = count.to_i unit = unit.downcase.strip.gsub(/s$/, '') @@ -123,47 +76,61 @@ raise ArgumentError, "I don't recognize #{unit}" end Time.now.utc + seconds end + # END:parse_timing - def rebroadcast(payload) - serialized = serialize_message(payload.message) - - key = "delay_#{rand(100..10_000)}" - redis.set(key, serialized.to_json) - reloaded = JSON.parse redis.get(key), symbolize_names: true - - resend(reloaded) - end - - def resend(serialized) - user = Lita::User.new(serialized.fetch('user_name')) - room = Lita::Room.new(serialized.fetch('room_name')) + # START:resend_command + def resend_command(command_hash) + user = Lita::User.new(command_hash.fetch('user_name')) + room = Lita::Room.new(command_hash.fetch('room_name')) source = Lita::Source.new(user: user, room: room) - body = "#{robot.name} #{serialized.fetch('body')}" + body = "#{robot.name} #{command_hash.fetch('body')}" newmsg = Lita::Message.new( robot, body, source ) robot.receive newmsg end + # END:resend_command - def serialize_message(message, new_body: nil) + # START:serialize_message + def command_to_hash(command, new_body: nil) { - user_name: message.user.name, - room_name: message.source.room, - body: new_body || message.body + user_name: command.user.name, + room_name: command.source.room, + body: new_body || command.body } end + # END:serialize_message - Lita.register_handler(self) + def find_tasks_due + scheduler.find_tasks_due + end - on :loaded do - run_loop + # START:loop_ticks + def run_loop + Thread.new do + loop do + tick + sleep 1 + end + end end + + def tick + tasks = find_tasks_due + tasks.each { |t| resend_command t } + Lita.logger.debug "Task loop done for #{Time.now}" + end + + on(:loaded) { run_loop } + # END:loop_ticks + + Lita.register_handler(self) end end end