resque-scheduler 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/README.markdown +45 -0
- data/Rakefile +53 -0
- data/lib/resque/scheduler.rb +49 -0
- data/lib/resque_scheduler.rb +36 -0
- data/lib/resque_scheduler/tasks.rb +15 -0
- data/lib/resque_scheduler/version.rb +3 -0
- data/tasks/resque_scheduler.rake +2 -0
- data/test/scheduler_test.rb +23 -0
- data/test/test_helper.rb +14 -0
- metadata +104 -0
data/.gitignore
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
resque-scheduler
|
2
|
+
===============
|
3
|
+
|
4
|
+
Resque-scheduler is basically the union of rufus-scheduler and resque. The goal
|
5
|
+
is to provide simple job scheduling with centralized configuration and
|
6
|
+
distributed workers.
|
7
|
+
|
8
|
+
The schedule is a list of Resque worker classes with arguments and a
|
9
|
+
schedule frequency (in crontab syntax). The schedule is just a hash, but
|
10
|
+
is most likely stored in a YAML:
|
11
|
+
|
12
|
+
queue_documents_for_indexing:
|
13
|
+
cron: "0 0 * * *"
|
14
|
+
class: QueueDocuments
|
15
|
+
args:
|
16
|
+
description: "This job queues all content for indexing in solr
|
17
|
+
|
18
|
+
clear_leaderboards_contributors:
|
19
|
+
cron: "30 6 * * 1"
|
20
|
+
class: ClearLeaderboards
|
21
|
+
args: contributors
|
22
|
+
description: "This job resets the weekly leaderboard for contributions"
|
23
|
+
|
24
|
+
clear_leaderboards_moderator:
|
25
|
+
cron: "30 6 * * 1"
|
26
|
+
class: ClearLeaderboards
|
27
|
+
args: moderators
|
28
|
+
description: "This job resets the weekly leaderboard for moderators"
|
29
|
+
|
30
|
+
And then set the schedule wherever you configure Resque, like so:
|
31
|
+
|
32
|
+
require 'resque-scheduler'
|
33
|
+
ResqueScheduler.schedule = YAML.load_file(File.join(File.dirname(__FILE__), '../resque_schedule.yml'))
|
34
|
+
|
35
|
+
The scheduler process is just a rake task which adds things to resque when they fire
|
36
|
+
based on the schedule. For obvious reasons, this process never exits.
|
37
|
+
|
38
|
+
$ rake resque-scheduler
|
39
|
+
|
40
|
+
You'll need to add this to your rakefile:
|
41
|
+
|
42
|
+
require 'resque_scheduler/tasks'
|
43
|
+
task "resque:setup" => :environment
|
44
|
+
|
45
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
load 'tasks/resque_scheduler.rake'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift 'lib'
|
4
|
+
|
5
|
+
task :default => :test
|
6
|
+
|
7
|
+
desc "Run tests"
|
8
|
+
task :test do
|
9
|
+
Dir['test/*_test.rb'].each do |f|
|
10
|
+
require f
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
desc "Build a gem"
|
16
|
+
task :gem => [ :test, :gemspec, :build ]
|
17
|
+
|
18
|
+
begin
|
19
|
+
begin
|
20
|
+
require 'jeweler'
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler not available. Install it with: "
|
23
|
+
puts "gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'resque_scheduler/version'
|
27
|
+
|
28
|
+
Jeweler::Tasks.new do |gemspec|
|
29
|
+
gemspec.name = "resque-scheduler"
|
30
|
+
gemspec.summary = ""
|
31
|
+
gemspec.description = ""
|
32
|
+
gemspec.email = "bvandenbos@gmail.com"
|
33
|
+
gemspec.homepage = "http://github.com/bvandenbos/resque-scheduler"
|
34
|
+
gemspec.authors = ["Ben VandenBos"]
|
35
|
+
gemspec.version = ResqueScheduler::Version
|
36
|
+
|
37
|
+
gemspec.add_dependency "resque"
|
38
|
+
gemspec.add_dependency "rufus-scheduler"
|
39
|
+
gemspec.add_development_dependency "jeweler"
|
40
|
+
gemspec.add_development_dependency "mocha"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
desc "Push a new version to Gemcutter"
|
46
|
+
task :publish => [ :test, :gemspec, :build ] do
|
47
|
+
system "git tag v#{ResqueScheduler::Version}"
|
48
|
+
system "git push origin v#{ResqueScheduler::Version}"
|
49
|
+
system "git push origin master"
|
50
|
+
system "gem push pkg/resque-scheduler-#{ResqueScheduler::Version}.gem"
|
51
|
+
system "git clean -fd"
|
52
|
+
exec "rake pages"
|
53
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rufus-scheduler'
|
2
|
+
require 'rufus/scheduler'
|
3
|
+
require 'thwait'
|
4
|
+
|
5
|
+
module Resque
|
6
|
+
|
7
|
+
class Scheduler
|
8
|
+
|
9
|
+
extend Resque::Helpers
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# Schedule all jobs and sleep (never returns)
|
14
|
+
def run(wait = true)
|
15
|
+
puts "Schedule empty! Set Resque.schedule" if Resque.schedule.empty?
|
16
|
+
|
17
|
+
Resque.schedule.each do |name, config|
|
18
|
+
puts "Scheduling #{name}..."
|
19
|
+
rufus_scheduler.cron config['cron'] do
|
20
|
+
puts "#{Time.now} queuing #{name}"
|
21
|
+
enqueue_from_config(config)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
# sleep baby, sleep
|
25
|
+
ThreadsWait.all_waits(rufus_scheduler.instance_variable_get("@thread")) if wait
|
26
|
+
end
|
27
|
+
|
28
|
+
def enqueue_from_config(config)
|
29
|
+
params = config['args'].nil? ? [] : Array(config['args'])
|
30
|
+
Resque.enqueue(constantize(config['class']), *params)
|
31
|
+
end
|
32
|
+
|
33
|
+
def rufus_scheduler
|
34
|
+
@rufus_scheduler ||= Rufus::Scheduler.start_new
|
35
|
+
end
|
36
|
+
|
37
|
+
# Stops old rufus scheduler and creates a new one. Returns the new
|
38
|
+
# rufus scheduler
|
39
|
+
def clear_schedule!
|
40
|
+
rufus_scheduler.stop
|
41
|
+
@rufus_scheduler = nil
|
42
|
+
rufus_scheduler
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'resque'
|
3
|
+
require 'resque_scheduler/version'
|
4
|
+
require 'resque/scheduler'
|
5
|
+
|
6
|
+
module ResqueScheduler
|
7
|
+
|
8
|
+
#
|
9
|
+
# Accepts a new schedule configuration of the form:
|
10
|
+
#
|
11
|
+
# {some_name => {"cron" => "5/* * * *",
|
12
|
+
# "class" => DoSomeWork,
|
13
|
+
# "args" => "work on this string",
|
14
|
+
# "description" => "this thing works it"s butter off"},
|
15
|
+
# ...}
|
16
|
+
#
|
17
|
+
# :name can be anything and is used only to describe the scheduled job
|
18
|
+
# :cron can be any cron scheduling string :job can be any resque job class
|
19
|
+
# :class must be a resque worker class
|
20
|
+
# :args can be any yaml which will be converted to a ruby literal and passed
|
21
|
+
# in a params. (optional)
|
22
|
+
# :description is just that, a description of the job (optional). If params is
|
23
|
+
# an array, each element in the array is passed as a separate param,
|
24
|
+
# otherwise params is passed in as the only parameter to perform.
|
25
|
+
def schedule=(schedule_hash)
|
26
|
+
@schedule = schedule_hash
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the schedule hash
|
30
|
+
def schedule
|
31
|
+
@schedule ||= {}
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
Resque.extend ResqueScheduler
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# require 'resque/tasks'
|
2
|
+
# will give you the resque tasks
|
3
|
+
|
4
|
+
namespace :resque do
|
5
|
+
task :setup
|
6
|
+
|
7
|
+
desc "Start Resque Scheduler"
|
8
|
+
task :scheduler => :setup do
|
9
|
+
require 'resque'
|
10
|
+
require 'resque_scheduler'
|
11
|
+
|
12
|
+
Resque::Scheduler.run
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class Resque::SchedulerTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Resque::Scheduler.clear_schedule!
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_enqueue_from_config_puts_stuff_in_the_resque_queue
|
10
|
+
Resque.stubs(:enqueue).once.returns(true).with(SomeIvarJob, '/tmp')
|
11
|
+
Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp")
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_config_makes_it_into_the_rufus_scheduler
|
15
|
+
assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
|
16
|
+
|
17
|
+
Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"}}
|
18
|
+
Resque::Scheduler.run(false)
|
19
|
+
|
20
|
+
assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'mocha'
|
4
|
+
$LOAD_PATH.unshift File.dirname(File.expand_path(__FILE__)) + '/../lib'
|
5
|
+
require 'resque_scheduler'
|
6
|
+
|
7
|
+
class SomeJob
|
8
|
+
def self.perform(repo_id, path)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class SomeIvarJob < SomeJob
|
13
|
+
@queue = :ivar
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: resque-scheduler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben VandenBos
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-21 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: resque
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rufus-scheduler
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: jeweler
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: mocha
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
description: ""
|
56
|
+
email: bvandenbos@gmail.com
|
57
|
+
executables: []
|
58
|
+
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- README.markdown
|
63
|
+
files:
|
64
|
+
- .gitignore
|
65
|
+
- README.markdown
|
66
|
+
- Rakefile
|
67
|
+
- lib/resque/scheduler.rb
|
68
|
+
- lib/resque_scheduler.rb
|
69
|
+
- lib/resque_scheduler/tasks.rb
|
70
|
+
- lib/resque_scheduler/version.rb
|
71
|
+
- tasks/resque_scheduler.rake
|
72
|
+
- test/scheduler_test.rb
|
73
|
+
- test/test_helper.rb
|
74
|
+
has_rdoc: true
|
75
|
+
homepage: http://github.com/bvandenbos/resque-scheduler
|
76
|
+
licenses: []
|
77
|
+
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options:
|
80
|
+
- --charset=UTF-8
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
version:
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
version:
|
95
|
+
requirements: []
|
96
|
+
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.3.5
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: ""
|
102
|
+
test_files:
|
103
|
+
- test/scheduler_test.rb
|
104
|
+
- test/test_helper.rb
|