resque-scheduler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ *.gemspec
2
+ pkg
3
+ nbproject
@@ -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
+
@@ -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,3 @@
1
+ module ResqueScheduler
2
+ Version = '0.0.1'
3
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'resque_scheduler/tasks'
@@ -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
@@ -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