Last active
December 24, 2015 16:08
-
-
Save ianneub/6468925 to your computer and use it in GitHub Desktop.
First attempt at a database backed clockwork scheduler. This was made against Rails 4 with a Job model that can be created like so:
rails g model Job period:string name:string code:text See: https://github.com/tomykaira/clockwork/issues/25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# version 1 | |
require 'clockwork' | |
require './config/boot' | |
require './config/environment' | |
module DBBackedClockwork | |
extend Clockwork | |
# add a periodic job to update @@events | |
# I think a thread is too complex | |
configure do |config| | |
config[:sleep_timeout] = 1 | |
config[:tz] = 'Pacific Time (US & Canada)' | |
config[:max_threads] = 15 | |
end | |
every 1.minute, "update jobs" do | |
db_events.each do |event| | |
event.update_from_db | |
end | |
# add database events | |
Job.all.each do |e| | |
events << DBBackedEvent.new(e) unless db_events.map(&:id).include?(e.id) | |
end | |
end | |
# get the manager object | |
def self.manager | |
Clockwork.class_variable_get(:@@manager) | |
end | |
# get the events array | |
def self.events | |
manager.instance_variable_get(:@events) | |
end | |
# get the db backed events from the events array | |
# NOTE: this creates a new array and is not associated to the "official" events instance variable | |
def self.db_events | |
events.reject{|e| !e.respond_to?(:id) } | |
end | |
class DBBackedEvent < Clockwork::Event | |
# add @id tagged to DB to update a job | |
attr_accessor :id, :updated_at | |
def initialize(event) | |
id = event.id | |
updated_at = event.updated_at | |
super(DBBackedClockwork.manager, eval(event.period), event.name, Proc.new {eval event.code}) | |
end | |
# find the job in the database and update or remove it if necessary | |
def update_from_db | |
begin | |
job = Job.find(id) | |
if job.updated_at != updated_at | |
self.remove | |
DBBackedClockwork.events << DBBackedEvent.new(job) | |
end | |
rescue ActiveRecord::RecordNotFound | |
# remove the event | |
self.remove | |
end | |
end | |
# remove this event from the events array | |
def remove | |
DBBackedClockwork.events.reject!{|e| e.id == id rescue false} | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# version 2 | |
# this allows me to create jobs with an array of at times, version 1 would not | |
require 'clockwork' | |
require './config/boot' | |
require './config/environment' | |
module DBBackedClockwork | |
extend Clockwork | |
configure do |config| | |
config[:sleep_timeout] = 1 | |
config[:tz] = 'America/Los_Angeles' | |
config[:max_threads] = 15 | |
end | |
every 1.minute, "update db jobs" do | |
events.each do |event| | |
# if job has changed then delete event and reload it | |
if event.id | |
begin | |
job = Job.find(event.id) | |
if job.updated_at != event.updated_at | |
remove_event event | |
create_from_db job | |
end | |
rescue ActiveRecord::RecordNotFound | |
# remove job | |
remove_event event | |
end | |
end | |
end | |
# add database events | |
Job.all.each do |e| | |
unless events.map(&:id).include?(e.id) | |
create_from_db(e) | |
end | |
end | |
end | |
def self.remove_event(event) | |
puts "Removing #{event.job}..." | |
events.reject!{|e| e.id == event.id rescue false} | |
end | |
def self.create_from_db(event) | |
puts "Adding #{event.name}..." | |
options = Hash.new | |
options[:tz] = 'America/Los_Angeles' | |
options[:at] = event.at.split(',') if event.at | |
jobs = every eval("#{event.period}.#{event.period_type}"), event.name, options do | |
# do some work | |
end | |
jobs = [jobs] # ensure jobs is an array | |
jobs.flatten.each do |job| | |
job.id = event.id | |
job.updated_at = event.updated_at | |
end | |
jobs | |
end | |
# get the manager object | |
def self.manager | |
Clockwork.class_variable_get(:@@manager) | |
end | |
# get the events array | |
def self.events | |
manager.instance_variable_get(:@events) | |
end | |
class Clockwork::Event | |
attr_accessor :id, :updated_at | |
end | |
class Clockwork::Manager | |
def every_with_multiple_times(period, job, options={}, &block) | |
events = Array.new | |
each_options = options.clone | |
options[:at].each do |at| | |
each_options[:at] = at | |
events << register(period, job, block, each_options) | |
end | |
events | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment