qe 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,53 +1,53 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- qe (0.2.0)
4
+ qe (0.2.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
- activemodel (3.2.9)
10
- activesupport (= 3.2.9)
9
+ activemodel (3.2.11)
10
+ activesupport (= 3.2.11)
11
11
  builder (~> 3.0.0)
12
- activerecord (3.2.9)
13
- activemodel (= 3.2.9)
14
- activesupport (= 3.2.9)
12
+ activerecord (3.2.11)
13
+ activemodel (= 3.2.11)
14
+ activesupport (= 3.2.11)
15
15
  arel (~> 3.0.2)
16
16
  tzinfo (~> 0.3.29)
17
- activesupport (3.2.9)
17
+ activesupport (3.2.11)
18
18
  i18n (~> 0.6)
19
19
  multi_json (~> 1.0)
20
20
  arel (3.0.2)
21
21
  awesome_print (1.1.0)
22
- backburner (0.3.0)
23
- beaneater (~> 0.2.0)
22
+ backburner (0.3.2)
23
+ beaneater (~> 0.3.0)
24
24
  dante (~> 0.1.5)
25
- beaneater (0.2.0)
25
+ beaneater (0.3.0)
26
26
  builder (3.0.4)
27
- celluloid (0.12.3)
27
+ celluloid (0.12.4)
28
28
  facter (>= 1.6.12)
29
29
  timers (>= 1.0.0)
30
30
  coderay (1.0.8)
31
- connection_pool (0.9.2)
31
+ connection_pool (1.0.0)
32
32
  dante (0.1.5)
33
- delayed_job (3.0.4)
33
+ delayed_job (3.0.5)
34
34
  activesupport (~> 3.0)
35
35
  delayed_job_active_record (0.3.3)
36
36
  activerecord (>= 2.1.0, < 4)
37
37
  delayed_job (~> 3.0)
38
38
  diff-lcs (1.1.3)
39
- facter (1.6.14)
39
+ facter (1.6.17)
40
40
  i18n (0.6.1)
41
41
  method_source (0.8.1)
42
- multi_json (1.3.7)
43
- pry (0.9.10)
42
+ multi_json (1.5.0)
43
+ pry (0.9.11.4)
44
44
  coderay (~> 1.0.5)
45
45
  method_source (~> 0.8)
46
- slop (~> 3.3.1)
46
+ slop (~> 3.4)
47
47
  qu (0.2.0)
48
48
  multi_json
49
- rack (1.4.1)
50
- rack-protection (1.2.0)
49
+ rack (1.5.1)
50
+ rack-protection (1.3.2)
51
51
  rack
52
52
  redis (3.0.2)
53
53
  redis-namespace (1.2.1)
@@ -57,28 +57,34 @@ GEM
57
57
  redis-namespace (~> 1.0)
58
58
  sinatra (>= 0.9.2)
59
59
  vegas (~> 0.1.2)
60
+ resque-scheduler (2.0.0)
61
+ redis (>= 2.0.1)
62
+ resque (>= 1.20.0)
63
+ rufus-scheduler
60
64
  rspec (2.12.0)
61
65
  rspec-core (~> 2.12.0)
62
66
  rspec-expectations (~> 2.12.0)
63
67
  rspec-mocks (~> 2.12.0)
64
- rspec-core (2.12.0)
65
- rspec-expectations (2.12.0)
68
+ rspec-core (2.12.2)
69
+ rspec-expectations (2.12.1)
66
70
  diff-lcs (~> 1.1.3)
67
- rspec-mocks (2.12.0)
68
- sidekiq (2.5.3)
71
+ rspec-mocks (2.12.2)
72
+ rufus-scheduler (2.0.17)
73
+ tzinfo (>= 0.3.23)
74
+ sidekiq (2.6.5)
69
75
  celluloid (~> 0.12.0)
70
- connection_pool (~> 0.9.2)
76
+ connection_pool (~> 1.0)
71
77
  multi_json (~> 1)
72
78
  redis (~> 3)
73
79
  redis-namespace
74
- sinatra (1.3.3)
75
- rack (~> 1.3, >= 1.3.6)
76
- rack-protection (~> 1.2)
80
+ sinatra (1.3.4)
81
+ rack (~> 1.4)
82
+ rack-protection (~> 1.3)
77
83
  tilt (~> 1.3, >= 1.3.3)
78
- slop (3.3.3)
79
- sqlite3 (1.3.6)
84
+ slop (3.4.3)
85
+ sqlite3 (1.3.7)
80
86
  tilt (1.3.3)
81
- timers (1.0.1)
87
+ timers (1.1.0)
82
88
  tzinfo (0.3.35)
83
89
  vegas (0.1.11)
84
90
  rack (>= 1.0.0)
@@ -95,6 +101,7 @@ DEPENDENCIES
95
101
  qe!
96
102
  qu
97
103
  resque
104
+ resque-scheduler
98
105
  rspec
99
106
  sidekiq
100
107
  sqlite3
data/README.md CHANGED
@@ -75,6 +75,17 @@ MailerWorker.enqueue({
75
75
  })
76
76
  ```
77
77
 
78
+ You can specify when this job must be processed by setting the <tt>:run_at</tt> option.
79
+
80
+ ``` ruby
81
+ MailerWorker.enqueue({
82
+ :mail => :follow_up,
83
+ :email => "john@example.org",
84
+ :name => "John Doe",
85
+ :run_at => 5.days.from_now
86
+ })
87
+ ```
88
+
78
89
  ### Defining actions
79
90
 
80
91
  Sometimes you want to create several actions in a single worker, just because is easier. Instead of manually dispatch the action on your perform method, you can
@@ -109,6 +120,23 @@ NotificationWorker.enqueue(:message => "wat?")
109
120
 
110
121
  The action must be a existing public method. If not defined, `Qe::Action::MissingActionError` exception is raised.
111
122
 
123
+ ### Working with I18n
124
+
125
+ When you're working in internationalized app, you need to perform some jobs with the correct locale set (sending an e-mail, maybe?). Instead of doing it manually, you can just use the `Qe::Locale` extension.
126
+
127
+ This extension will set the `:locale` option when you enqueue some job and set it to `I18n.locale` when you perform it. Just include it after the `Qe::Worker` module.
128
+
129
+ ``` ruby
130
+ class MailerWorker
131
+ include Qe::Worker
132
+ include Qe::Locale
133
+
134
+ def perform
135
+ Mailer.public_send(options[:mail], options).deliver
136
+ end
137
+ end
138
+ ```
139
+
112
140
  ### Development support
113
141
 
114
142
  Qe comes with development support. Instead of starting up workers on development environment, you can use the `Qe::Immediate` adapter, which executes your worker right away!
@@ -130,7 +158,7 @@ require "qe/testing"
130
158
  Qe.adapter = Qe::Testing
131
159
  ```
132
160
 
133
- If you"re using RSpec, you can require the `qe/testing/rspec.rb` file
161
+ If you are using RSpec, you can require the `qe/testing/rspec.rb` file
134
162
  instead. This will reset `Qe.jobs` before every spec and will add a
135
163
  `enqueue` matcher.
136
164
 
@@ -1,3 +1,4 @@
1
- QUEUES="mail,default"
2
- QUEUE="mail,default"
1
+ QUEUE="later,mail,default"
2
+ QUEUES="later,mail,default"
3
3
  BEANSTALK_URL="beanstalk://localhost/"
4
+ GROUP=delayed_job
@@ -1,14 +1,35 @@
1
1
  source :rubygems
2
2
 
3
- gem "sidekiq"
4
- gem "backburner"
5
- gem "beanstalkd_view"
6
3
  gem "rake"
7
4
  gem "thin"
8
- gem "resque"
9
- gem "activerecord"
10
- gem "delayed_job_active_record"
11
- gem "sqlite3"
12
5
  gem "daemons"
13
- gem "qu-redis"
14
- gem "slim"
6
+ gem "pry"
7
+ gem "pry-remote"
8
+ gem "awesome_print"
9
+
10
+ group :sidekiq do
11
+ gem "activesupport", :require => "active_support/all"
12
+ gem "sidekiq"
13
+ gem "slim"
14
+ end
15
+
16
+ group :resque do
17
+ gem "resque"
18
+ gem "resque-scheduler"
19
+ end
20
+
21
+ group :beanstalk do
22
+ gem "backburner"
23
+ gem "beanstalkd_view"
24
+ end
25
+
26
+ group :delayed_job do
27
+ gem "activerecord"
28
+ gem "delayed_job_active_record"
29
+ gem "delayed_job_web"
30
+ gem "sqlite3"
31
+ end
32
+
33
+ group :qu do
34
+ gem "qu-redis"
35
+ end
@@ -1,25 +1,27 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- activemodel (3.2.8)
5
- activesupport (= 3.2.8)
4
+ activemodel (3.2.9)
5
+ activesupport (= 3.2.9)
6
6
  builder (~> 3.0.0)
7
- activerecord (3.2.8)
8
- activemodel (= 3.2.8)
9
- activesupport (= 3.2.8)
7
+ activerecord (3.2.9)
8
+ activemodel (= 3.2.9)
9
+ activesupport (= 3.2.9)
10
10
  arel (~> 3.0.2)
11
11
  tzinfo (~> 0.3.29)
12
- activesupport (3.2.8)
12
+ activesupport (3.2.9)
13
13
  i18n (~> 0.6)
14
14
  multi_json (~> 1.0)
15
15
  arel (3.0.2)
16
- backburner (0.2.0)
17
- beaneater (~> 0.1.2)
16
+ awesome_print (1.1.0)
17
+ backburner (0.3.0)
18
+ beaneater (~> 0.2.0)
18
19
  dante (~> 0.1.5)
19
20
  backports (2.6.5)
20
- beaneater (0.1.2)
21
- beanstalkd_view (1.1.0)
22
- beaneater (~> 0.1.0)
21
+ beaneater (0.2.2)
22
+ beanstalk-client (1.1.1)
23
+ beanstalkd_view (1.0.2)
24
+ beanstalk-client (>= 1.1.1)
23
25
  json
24
26
  sinatra (>= 1.3.0)
25
27
  sinatra-assetpack (>= 0.0.11)
@@ -29,20 +31,36 @@ GEM
29
31
  celluloid (0.12.3)
30
32
  facter (>= 1.6.12)
31
33
  timers (>= 1.0.0)
34
+ coderay (1.0.8)
32
35
  connection_pool (0.9.2)
33
36
  daemons (1.1.9)
34
37
  dante (0.1.5)
35
- delayed_job (3.0.3)
38
+ delayed_job (3.0.4)
36
39
  activesupport (~> 3.0)
37
40
  delayed_job_active_record (0.3.3)
38
41
  activerecord (>= 2.1.0, < 4)
39
42
  delayed_job (~> 3.0)
43
+ delayed_job_web (1.1.2)
44
+ activerecord (> 3.0.0)
45
+ delayed_job (> 2.0.3)
46
+ haml (~> 3.1.3)
47
+ rdoc
48
+ sinatra (>= 0.9.2)
40
49
  eventmachine (1.0.0)
41
- facter (1.6.14)
50
+ facter (1.6.16)
51
+ haml (3.1.7)
42
52
  i18n (0.6.1)
43
53
  jsmin (1.0.1)
44
54
  json (1.7.5)
45
- multi_json (1.3.7)
55
+ method_source (0.8.1)
56
+ multi_json (1.4.0)
57
+ pry (0.9.10)
58
+ coderay (~> 1.0.5)
59
+ method_source (~> 0.8)
60
+ slop (~> 3.3.1)
61
+ pry-remote (0.1.6)
62
+ pry (~> 0.9)
63
+ slop (~> 3.0)
46
64
  qu (0.2.0)
47
65
  multi_json
48
66
  qu-redis (0.2.0)
@@ -54,7 +72,9 @@ GEM
54
72
  rack
55
73
  rack-test (0.6.2)
56
74
  rack (>= 1.0)
57
- rake (0.9.2.2)
75
+ rake (10.0.2)
76
+ rdoc (3.12)
77
+ json (~> 1.4)
58
78
  redis (3.0.2)
59
79
  redis-namespace (1.2.1)
60
80
  redis (~> 3.0.0)
@@ -63,13 +83,19 @@ GEM
63
83
  redis-namespace (~> 1.0)
64
84
  sinatra (>= 0.9.2)
65
85
  vegas (~> 0.1.2)
66
- sidekiq (2.5.2)
86
+ resque-scheduler (2.0.0)
87
+ redis (>= 2.0.1)
88
+ resque (>= 1.20.0)
89
+ rufus-scheduler
90
+ rufus-scheduler (2.0.17)
91
+ tzinfo (>= 0.3.23)
92
+ sidekiq (2.5.4)
67
93
  celluloid (~> 0.12.0)
68
94
  connection_pool (~> 0.9.2)
69
95
  multi_json (~> 1)
70
96
  redis (~> 3)
71
97
  redis-namespace
72
- simple_uuid (0.2.0)
98
+ simple_uuid (0.3.0)
73
99
  sinatra (1.3.3)
74
100
  rack (~> 1.3, >= 1.3.6)
75
101
  rack-protection (~> 1.2)
@@ -86,9 +112,10 @@ GEM
86
112
  rack-test
87
113
  sinatra (~> 1.3.0)
88
114
  tilt (~> 1.3)
89
- slim (1.3.3)
115
+ slim (1.3.4)
90
116
  temple (~> 0.5.5)
91
117
  tilt (~> 1.3.3)
118
+ slop (3.3.3)
92
119
  sqlite3 (1.3.6)
93
120
  temple (0.5.5)
94
121
  thin (1.5.0)
@@ -106,13 +133,19 @@ PLATFORMS
106
133
 
107
134
  DEPENDENCIES
108
135
  activerecord
136
+ activesupport
137
+ awesome_print
109
138
  backburner
110
139
  beanstalkd_view
111
140
  daemons
112
141
  delayed_job_active_record
142
+ delayed_job_web
143
+ pry
144
+ pry-remote
113
145
  qu-redis
114
146
  rake
115
147
  resque
148
+ resque-scheduler
116
149
  sidekiq
117
150
  slim
118
151
  sqlite3
@@ -1,20 +1,25 @@
1
- redis: redis-server redis.conf
1
+ # redis: redis-server redis.conf
2
2
  # beanstalkd: beanstalkd
3
3
 
4
4
  # Uncomment the following lines to enable Sidekiq
5
- sidekiq: bundle exec sidekiq -r ./workers.rb -q default -q mail
6
- sidekiq_web: bundle exec thin -R sidekiq.ru -p 9292 -V start
5
+ # sidekiq: bundle exec sidekiq -r ./workers.rb -q default -q mail -q later
6
+ # sidekiq_web: bundle exec thin -R sidekiq.ru -p 9292 -V start
7
7
 
8
8
  # Uncomment the following lines to enable Beanstalk/Backburner
9
9
  # backburner: bundle exec rake backburner:work
10
10
  # beanstalkd_view: bundle exec thin -R beanstalkd.ru -p 9292 -V start
11
11
 
12
12
  # Uncomment the following line to enable DelayedJob
13
- # delayed_job: bundle exec rake jobs:work
13
+ delayed_job: bundle exec rake delayed_job
14
+ delayed_job_web: bundle exec thin -R delayed_job.ru -p 9292 -V start
14
15
 
15
16
  # Uncomment the following line to enable Qu
16
17
  # qu: bundle exec rake qu:work
17
18
 
18
19
  # Uncomment the following lines to enable Resque
19
20
  # resque: bundle exec rake resque:work
21
+ # resque_scheduler: bundle exec rake resque:scheduler
20
22
  # resque_web: bundle exec thin -R resque.ru -p 9292 -V start
23
+
24
+ # Add jobs every 3 seconds
25
+ add_jobs: ruby add_jobs.rb
@@ -1,9 +1,7 @@
1
1
  # Running examples
2
2
 
3
- 1. First, start processes with `$ foreman start`
4
- 2. Then execute `$ ruby sample.rb`
3
+ 1. Change the bundler group name on the `.env` file.
4
+ 2. Start processes with `$ foreman start`
5
5
  3. Go back to the Foreman's terminal and watch the output
6
6
 
7
- Tweak the `Procfile` to enable different libraries and web panels.
8
-
9
- You'll need to install Redis and/or Beanstalkd.
7
+ Tweak the `Procfile` and `.env` files to enable different libraries and web panels.
@@ -1,14 +1,15 @@
1
- require "backburner/tasks"
2
- require "resque/tasks"
3
- require "delayed/tasks"
4
- require "qu/tasks"
1
+ require "./workers"
5
2
 
6
3
  task :environment do #=> required by Backburner
7
- require "./workers"
8
4
 
9
- Backburner.configure do |config|
10
- config.logger = Logger.new(STDOUT)
11
- end
12
5
  end
13
6
 
14
7
  task "resque:setup" => :environment
8
+
9
+ desc "Setup delayed job consumer"
10
+ task :delayed_job do
11
+ ENV["QUEUES"] = "later,mail,default"
12
+ ENV.delete("QUEUE")
13
+ Rake::Task["jobs:work"].reenable
14
+ Rake::Task["jobs:work"].invoke
15
+ end
@@ -1,10 +1,9 @@
1
1
  require "./workers"
2
2
 
3
3
  loop do
4
- puts "=> Enqueuing jobs [#{Time.now}]"
5
-
6
4
  MailerWorker.enqueue(:name => "John Doe", :email => "john@example.org")
7
5
  ClockWorker.enqueue
6
+ LaterWorker.enqueue :run_at => Time.now + 5, :time => Time.now
8
7
 
9
8
  sleep 3
10
9
  end
@@ -1,5 +1,5 @@
1
1
  require "bundler"
2
- Bundler.setup(:default)
3
- Bundler.require(:default)
2
+ Bundler.setup(:default, :beanstalk)
3
+ Bundler.require(:default, :beanstalk)
4
4
 
5
5
  run BeanstalkdView::Server
@@ -0,0 +1,10 @@
1
+ require "bundler"
2
+ Bundler.setup(:default, :delayed_job)
3
+ Bundler.require(:default, :delayed_job)
4
+
5
+ ActiveRecord::Base.establish_connection(
6
+ :adapter => "sqlite3", :database => "jobs.sqlite3"
7
+ )
8
+
9
+ require "delayed_job_web"
10
+ run DelayedJobWeb
@@ -1,6 +1,6 @@
1
1
  require "bundler"
2
- Bundler.setup(:default)
3
- Bundler.require(:default)
2
+ Bundler.setup(:default, :resque)
3
+ Bundler.require(:default, :resque)
4
4
 
5
5
  require "resque/server"
6
6
  run Resque::Server
@@ -1,6 +1,6 @@
1
1
  require "bundler"
2
- Bundler.setup(:default)
3
- Bundler.require(:default)
2
+ Bundler.setup(:default, :sidekiq)
3
+ Bundler.require(:default, :sidekiq)
4
4
 
5
5
  Sidekiq.configure_client do |config|
6
6
  config.redis = { :size => 1 }
@@ -1,26 +1,53 @@
1
1
  require "bundler"
2
- Bundler.setup(:default)
2
+ Bundler.setup(:default, ENV.fetch("GROUP"))
3
3
  Bundler.require
4
4
 
5
+ require "time"
6
+
5
7
  $:.unshift File.expand_path("../../lib", __FILE__)
6
- require "qe"
7
8
 
8
- $stdout.sync = true
9
+ case ENV.fetch("GROUP")
10
+ when "sidekiq"
11
+ require "qe/sidekiq"
12
+ when "beanstalk"
13
+ require "qe/beanstalk"
14
+ require "backburner/tasks"
9
15
 
10
- Qe.adapter = Qe::Sidekiq
11
- # Qe.adapter = Qe::Beanstalk
12
- # Qe.adapter = Qe::Resque
13
- # Qe.adapter = Qe::DelayedJob
14
- # Qe.adapter = Qe::Qu
15
- # Qe.adapter = Qe::Testing
16
+ Backburner.configure do |config|
17
+ config.logger = Logger.new($stdout)
18
+ end
19
+ when "resque"
20
+ require "qe/resque"
21
+ require "resque/tasks"
22
+ require "resque_scheduler/tasks"
23
+ when "delayed_job"
24
+ require "delayed_job"
25
+ require "delayed_job_active_record"
26
+ require "qe/delayed_job"
27
+ require "active_record"
28
+ require "delayed/tasks"
29
+ when "qu"
30
+ require "qe/qu"
31
+ require "qu/tasks"
32
+ end
16
33
 
17
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "jobs.sqlite3")
34
+ $stdout.sync = true
35
+
36
+ if defined?(Qe::DelayedJob)
37
+ ActiveRecord::Base.establish_connection(
38
+ :adapter => "sqlite3", :database => "jobs.sqlite3"
39
+ )
40
+ end
18
41
 
19
42
  class ClockWorker
20
43
  include Qe::Worker
21
44
 
22
45
  def perform
46
+ puts
47
+ puts "---"
23
48
  puts "=> Time: #{Time.now}"
49
+ puts "---"
50
+ puts
24
51
  end
25
52
  end
26
53
 
@@ -29,6 +56,8 @@ class MailerWorker
29
56
  queue :mail
30
57
 
31
58
  def before
59
+ puts
60
+ puts "---"
32
61
  puts "=> Running before"
33
62
  end
34
63
 
@@ -39,5 +68,20 @@ class MailerWorker
39
68
 
40
69
  def after
41
70
  puts "=> Running after"
71
+ puts "---"
72
+ puts
73
+ end
74
+ end
75
+
76
+ class LaterWorker
77
+ include Qe::Worker
78
+
79
+ def perform
80
+ puts
81
+ puts "---"
82
+ puts "=> Job scheduled on #{options.inspect}"
83
+ puts "=> But executed on #{Time.now}"
84
+ puts "---"
85
+ puts
42
86
  end
43
87
  end
data/lib/qe.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require "qe/action"
2
+ require "qe/locale"
2
3
  require "qe/immediate"
3
4
  require "qe/version"
5
+ require "qe/worker/class_methods"
6
+ require "qe/worker/instance_methods"
4
7
  require "qe/worker"
5
8
 
6
9
  # In this wild world where a new asynchronous job processing
@@ -50,6 +53,16 @@ require "qe/worker"
50
53
  # :name => "John Doe"
51
54
  # })
52
55
  #
56
+ # You can specify when this job must be processed by setting the <tt>:run_at</tt>
57
+ # option.
58
+ #
59
+ # MailerWorker.enqueue({
60
+ # :mail => :follow_up,
61
+ # :email => "john@example.org",
62
+ # :name => "John Doe",
63
+ # :run_at => 5.days.from_now
64
+ # })
65
+ #
53
66
  # == Testing support
54
67
  #
55
68
  # Qe comes with testing support. Just require the <tt>qe/testing.rb</tt> file
@@ -77,4 +90,12 @@ module Qe
77
90
  class << self
78
91
  attr_accessor :adapter
79
92
  end
93
+
94
+ # Error that is raised when trying to use a feature
95
+ # that isn't supported by some adapter.
96
+ UnsupportedFeatureError = Class.new(StandardError)
97
+
98
+ # Error that is raised when trying to include a
99
+ # module before Qe::Worker is included.
100
+ OutOfOrderError = Class.new(StandardError)
80
101
  end
@@ -15,6 +15,12 @@ module Qe
15
15
  Worker.queue worker.queue
16
16
  Backburner.enqueue Worker, worker.name, options
17
17
  end
18
+
19
+ def self.schedule(worker, run_at, options = {})
20
+ delay = run_at - Time.now
21
+ Worker.queue worker.queue
22
+ Backburner::Worker.enqueue Worker, [worker.name, options], :delay => delay
23
+ end
18
24
  end
19
25
 
20
26
  self.adapter = Beanstalk
@@ -10,7 +10,14 @@ module Qe
10
10
  end
11
11
 
12
12
  def self.enqueue(worker, options = {})
13
- Delayed::Job.enqueue Worker.new(worker.name, options), :queue => worker.queue
13
+ Delayed::Job.enqueue Worker.new(worker.name, options),
14
+ :queue => worker.queue
15
+ end
16
+
17
+ def self.schedule(worker, run_at, options = {})
18
+ Delayed::Job.enqueue Worker.new(worker.name, options),
19
+ :queue => worker.queue,
20
+ :run_at => run_at
14
21
  end
15
22
  end
16
23
 
@@ -0,0 +1,29 @@
1
+ module Qe
2
+ module Locale
3
+ def self.included(base)
4
+ unless base.included_modules.include?(Qe::Worker)
5
+ raise OutOfOrderError, "must be included after Qe::Worker"
6
+ end
7
+
8
+ class << base
9
+ # Intercept <tt>Worker.enqueue</tt> method, adding
10
+ # the current locale to the options.
11
+ enqueue = instance_method(:enqueue)
12
+ define_method :enqueue do |options = {}|
13
+ options[:locale] = I18n.locale
14
+ enqueue.bind(self).call(options)
15
+ end
16
+ end
17
+
18
+ base.class_eval do
19
+ # Intercept <tt>Worker#before</tt> method, adding
20
+ # the setting the current locale.
21
+ before = instance_method(:before)
22
+ define_method :before do
23
+ I18n.locale = options.delete(:locale)
24
+ before.bind(self).call
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -4,8 +4,6 @@ require "qu"
4
4
  module Qe
5
5
  class Qu
6
6
  class Worker
7
- include ::Sidekiq::Worker
8
-
9
7
  def self.perform(*args)
10
8
  Qe::Worker.perform(*args)
11
9
  end
@@ -15,6 +13,10 @@ module Qe
15
13
  Worker.instance_variable_set("@queue", worker.queue)
16
14
  ::Qu.enqueue Worker, worker.name, options
17
15
  end
16
+
17
+ def self.schedule(*)
18
+ raise UnsupportedFeatureError, "scheduling isn't supported on Qu"
19
+ end
18
20
  end
19
21
 
20
22
  self.adapter = Qu
@@ -1,5 +1,6 @@
1
1
  require "qe"
2
2
  require "resque"
3
+ require "resque_scheduler"
3
4
 
4
5
  module Qe
5
6
  class Resque
@@ -13,6 +14,12 @@ module Qe
13
14
  Worker.instance_variable_set "@queue", worker.queue
14
15
  ::Resque.enqueue Worker, worker.name, options
15
16
  end
17
+
18
+ def self.schedule(worker, run_at, options = {})
19
+ Worker.instance_variable_set "@queue", worker.queue
20
+
21
+ ::Resque.enqueue_at(run_at, Worker, worker.name, options)
22
+ end
16
23
  end
17
24
 
18
25
  self.adapter = Resque
@@ -15,6 +15,11 @@ module Qe
15
15
  Worker.sidekiq_options :queue => worker.queue
16
16
  Worker.perform_async(worker.name, options)
17
17
  end
18
+
19
+ def self.schedule(worker, run_at, options = {})
20
+ Worker.sidekiq_options :queue => worker.queue
21
+ Worker.perform_at(run_at, worker.name, options)
22
+ end
18
23
  end
19
24
 
20
25
  self.adapter = Sidekiq
@@ -1,3 +1,3 @@
1
1
  module Qe
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -7,45 +7,6 @@ module Qe
7
7
  end
8
8
  end
9
9
 
10
- module InstanceMethods
11
- def initialize(options)
12
- @options = options
13
- end
14
-
15
- # Return options that were provided when
16
- # adding job to the queue.
17
- def options
18
- @options
19
- end
20
-
21
- # Set before hook.
22
- def before
23
- end
24
-
25
- # Set after hook.
26
- def after
27
- end
28
-
29
- # Set the error hook.
30
- def error(error)
31
- raise error
32
- end
33
- end
34
-
35
- module ClassMethods
36
- # Enqueue job on given worker class.
37
- def enqueue(options = {})
38
- Qe.adapter.enqueue(self, options)
39
- end
40
-
41
- # Set the queue name when receiving on argument.
42
- # Return queue name otherwise.
43
- def queue(*args)
44
- @queue = args.first unless args.empty?
45
- (@queue || :default).to_s
46
- end
47
- end
48
-
49
10
  # Find a worker by its name.
50
11
  # If worker constant is not found, raises a +NameError+
51
12
  # exception.
@@ -0,0 +1,23 @@
1
+ module Qe
2
+ module Worker
3
+ module ClassMethods
4
+ # Enqueue job on given worker class.
5
+ def enqueue(options = {})
6
+ run_at = options.delete(:run_at)
7
+
8
+ if run_at
9
+ Qe.adapter.schedule(self, run_at, options)
10
+ else
11
+ Qe.adapter.enqueue(self, options)
12
+ end
13
+ end
14
+
15
+ # Set the queue name when receiving on argument.
16
+ # Return queue name otherwise.
17
+ def queue(*args)
18
+ @queue = args.first unless args.empty?
19
+ (@queue || :default).to_s
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module Qe
2
+ module Worker
3
+ module InstanceMethods
4
+ def initialize(options)
5
+ @options = options
6
+ end
7
+
8
+ # Return options that were provided when
9
+ # adding job to the queue.
10
+ def options
11
+ @options
12
+ end
13
+
14
+ # Set before hook.
15
+ def before
16
+ end
17
+
18
+ # Set after hook.
19
+ def after
20
+ end
21
+
22
+ # Set the error hook.
23
+ def error(error)
24
+ raise error
25
+ end
26
+ end
27
+ end
28
+ end
data/qe.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "delayed_job_active_record"
23
23
  s.add_development_dependency "backburner"
24
24
  s.add_development_dependency "resque"
25
+ s.add_development_dependency "resque-scheduler"
25
26
 
26
27
  s.add_development_dependency "activerecord"
27
28
  s.add_development_dependency "awesome_print"
@@ -42,4 +42,33 @@ describe Qe::Beanstalk do
42
42
  Qe::Beanstalk.enqueue(worker, :a => 1)
43
43
  end
44
44
  end
45
+
46
+ context "scheduling" do
47
+ let(:worker) {
48
+ mock("worker", :queue => "some_queue", :name => "SomeWorker")
49
+ }
50
+
51
+ let(:date) { Time.parse("2012-12-05 02:00:00") }
52
+
53
+ before do
54
+ Time.stub :now => date - 3600
55
+ Backburner::Worker.stub :enqueue
56
+ end
57
+
58
+ it "sets queue name" do
59
+ Qe::Beanstalk::Worker
60
+ .should_receive(:queue)
61
+ .with("some_queue")
62
+
63
+ Qe::Beanstalk.schedule(worker, date, :a => 1)
64
+ end
65
+
66
+ it "schedules job" do
67
+ ::Backburner::Worker
68
+ .should_receive(:enqueue)
69
+ .with(Qe::Beanstalk::Worker, ["SomeWorker", :a => 1], :delay => 3600)
70
+
71
+ Qe::Beanstalk.schedule(worker, date, :a => 1)
72
+ end
73
+ end
45
74
  end
@@ -56,4 +56,43 @@ describe Qe::DelayedJob do
56
56
  Qe::DelayedJob.enqueue(worker, :a => 1)
57
57
  end
58
58
  end
59
+
60
+ context "scheduling" do
61
+ let(:worker) {
62
+ mock("worker", :queue => "some_queue", :name => "SomeWorker")
63
+ }
64
+
65
+ let(:date) { Time.now }
66
+
67
+ before do
68
+ Delayed::Job.stub :enqueue
69
+ end
70
+
71
+ it "sets queue name" do
72
+ Delayed::Job
73
+ .should_receive(:enqueue)
74
+ .with(anything, hash_including(:queue => "some_queue"))
75
+
76
+ Qe::DelayedJob.schedule(worker, date, :a => 1)
77
+ end
78
+
79
+ it "instantiates worker" do
80
+ Qe::DelayedJob::Worker
81
+ .should_receive(:new)
82
+ .with("SomeWorker", :a => 1)
83
+
84
+ Qe::DelayedJob.schedule(worker, date, :a => 1)
85
+ end
86
+
87
+ it "schedules job" do
88
+ job = mock("job")
89
+ Qe::DelayedJob::Worker.stub :new => job
90
+
91
+ Delayed::Job
92
+ .should_receive(:enqueue)
93
+ .with(job, hash_including(:run_at => date))
94
+
95
+ Qe::DelayedJob.schedule(worker, date, :a => 1)
96
+ end
97
+ end
59
98
  end
@@ -1,8 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Qe::EnqueueMatcher do
4
- HelloWorker = Class.new { include Qe::Worker }
5
-
6
4
  it "sets adapter" do
7
5
  expect(Qe.adapter).to eql(Qe::Testing)
8
6
  end
@@ -1,11 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Qe::Immediate do
4
- HelloWorker = Class.new do
5
- include Qe::Worker
6
- def perform; end
7
- end
8
-
9
4
  let(:job) { mock("job").as_null_object }
10
5
 
11
6
  it "sets options" do
@@ -0,0 +1,58 @@
1
+ require "spec_helper"
2
+
3
+ describe Qe::Locale do
4
+ let(:i18n) { mock("I18n", :locale => :en) }
5
+
6
+ before do
7
+ stub_const("I18n", i18n)
8
+ end
9
+
10
+ context "when including extension" do
11
+ context "before Qe::Locale" do
12
+ it "raises exception" do
13
+ expect {
14
+ mod = Module.new do
15
+ include Qe::Locale
16
+ end
17
+ }.to raise_error(Qe::OutOfOrderError)
18
+ end
19
+ end
20
+
21
+ context "after Qe::Locale" do
22
+ it "does nothing" do
23
+ expect {
24
+ mod = Module.new do
25
+ include Qe::Worker
26
+ include Qe::Locale
27
+ end
28
+ }.not_to raise_error
29
+ end
30
+ end
31
+ end
32
+
33
+ context "when enqueuing" do
34
+ before do
35
+ Qe.adapter = Qe::Testing
36
+ end
37
+
38
+ it "sets locale" do
39
+ expect {
40
+ LocalizedWorker.enqueue
41
+ }.to enqueue(LocalizedWorker).with(:locale => :en)
42
+ end
43
+ end
44
+
45
+ context "when performing" do
46
+ before do
47
+ Qe.adapter = Qe::Immediate
48
+ end
49
+
50
+ it "sets locale" do
51
+ i18n
52
+ .should_receive(:locale=)
53
+ .with(:en)
54
+
55
+ LocalizedWorker.enqueue
56
+ end
57
+ end
58
+ end
@@ -39,4 +39,12 @@ describe Qe::Qu do
39
39
  Qe::Qu.enqueue(worker, :a => 1)
40
40
  end
41
41
  end
42
+
43
+ context "scheduling" do
44
+ it "raises exception" do
45
+ expect {
46
+ Qe::Qu.schedule(stub, Time.now, :a => 1)
47
+ }.to raise_error(Qe::UnsupportedFeatureError)
48
+ end
49
+ end
42
50
  end
@@ -39,4 +39,29 @@ describe Qe::Resque do
39
39
  Qe::Resque.enqueue(worker, :a => 1)
40
40
  end
41
41
  end
42
+
43
+ context "scheduling" do
44
+ let(:date) { Time.now }
45
+
46
+ let(:worker) {
47
+ mock("worker", :queue => "some_queue", :name => "SomeWorker")
48
+ }
49
+
50
+ before do
51
+ Resque.stub :enqueue_at => nil, :remove_delayed => nil
52
+ end
53
+
54
+ it "sets queue name" do
55
+ Qe::Resque.schedule(worker, date)
56
+ expect(Qe::Resque::Worker.instance_variable_get("@queue")).to eql("some_queue")
57
+ end
58
+
59
+ it "schedules job" do
60
+ ::Resque
61
+ .should_receive(:enqueue_at)
62
+ .with(date, Qe::Resque::Worker, "SomeWorker", :a => 1)
63
+
64
+ Qe::Resque.schedule(worker, date, :a => 1)
65
+ end
66
+ end
42
67
  end
@@ -46,4 +46,32 @@ describe Qe::Sidekiq do
46
46
  Qe::Sidekiq.enqueue(worker, :a => 1)
47
47
  end
48
48
  end
49
+
50
+ context "scheduling" do
51
+ let(:worker) {
52
+ mock("worker", :queue => "some_queue", :name => "SomeWorker")
53
+ }
54
+
55
+ before do
56
+ Qe::Sidekiq::Worker.stub :perform_at
57
+ end
58
+
59
+ it "sets queue name" do
60
+ Qe::Sidekiq::Worker
61
+ .should_receive(:sidekiq_options)
62
+ .with(:queue => "some_queue")
63
+
64
+ Qe::Sidekiq.enqueue(worker)
65
+ end
66
+
67
+ it "schedules job" do
68
+ date = Time.now
69
+
70
+ Qe::Sidekiq::Worker
71
+ .should_receive(:perform_at)
72
+ .with(date, "SomeWorker", :a => 1)
73
+
74
+ Qe::Sidekiq.schedule(worker, date, :a => 1)
75
+ end
76
+ end
49
77
  end
@@ -1,12 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Qe::Worker do
4
- HelloWorker = Class.new do
5
- include Qe::Worker
6
-
7
- def perform; end
8
- end
9
-
10
4
  it "sets queue name" do
11
5
  HelloWorker.queue "hello"
12
6
  expect(HelloWorker.queue).to eql("hello")
@@ -28,6 +22,18 @@ describe Qe::Worker do
28
22
  HelloWorker.enqueue(:a => 1)
29
23
  end
30
24
 
25
+ it "delegates scheduling to adapter" do
26
+ adapter = mock("adapter")
27
+ date = Time.now
28
+ adapter
29
+ .should_receive(:schedule)
30
+ .with(HelloWorker, date, :a => 1)
31
+
32
+ Qe.adapter = adapter
33
+
34
+ HelloWorker.enqueue(:a => 1, :run_at => date)
35
+ end
36
+
31
37
  it "finds worker by its name" do
32
38
  worker = mock("worker")
33
39
  stub_const "Some::Weird::Worker", worker
@@ -73,8 +79,13 @@ describe Qe::Worker do
73
79
  end
74
80
 
75
81
  it "passes error object to error handler" do
76
- HelloWorker.any_instance.should_receive(:error).with(kind_of(StandardError))
77
- HelloWorker.any_instance.stub(:perform).and_raise("ZOMG!")
82
+ HelloWorker.any_instance
83
+ .should_receive(:error)
84
+ .with(kind_of(StandardError))
85
+
86
+ HelloWorker.any_instance
87
+ .stub(:perform)
88
+ .and_raise("ZOMG!")
78
89
 
79
90
  Qe::Worker.perform("HelloWorker", {})
80
91
  end
@@ -10,3 +10,6 @@ require "qe/sidekiq"
10
10
  require "qe/qu"
11
11
  require "qe/delayed_job"
12
12
  require "delayed_job_active_record"
13
+
14
+ require "support/hello_worker"
15
+ require "support/localized_worker"
@@ -0,0 +1,4 @@
1
+ class HelloWorker
2
+ include Qe::Worker
3
+ def perform; end
4
+ end
@@ -0,0 +1,5 @@
1
+ class LocalizedWorker
2
+ include Qe::Worker
3
+ include Qe::Locale
4
+ def perform; end
5
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-17 00:00:00.000000000 Z
12
+ date: 2013-02-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sidekiq
@@ -91,6 +91,22 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: resque-scheduler
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
94
110
  - !ruby/object:Gem::Dependency
95
111
  name: activerecord
96
112
  requirement: !ruby/object:Gem::Requirement
@@ -191,11 +207,12 @@ files:
191
207
  - examples/Procfile
192
208
  - examples/README.md
193
209
  - examples/Rakefile
210
+ - examples/add_jobs.rb
194
211
  - examples/beanstalkd.ru
212
+ - examples/delayed_job.ru
195
213
  - examples/migrate.rb
196
214
  - examples/redis.conf
197
215
  - examples/resque.ru
198
- - examples/sample.rb
199
216
  - examples/sidekiq.ru
200
217
  - examples/workers.rb
201
218
  - lib/qe.rb
@@ -203,6 +220,7 @@ files:
203
220
  - lib/qe/beanstalk.rb
204
221
  - lib/qe/delayed_job.rb
205
222
  - lib/qe/immediate.rb
223
+ - lib/qe/locale.rb
206
224
  - lib/qe/qu.rb
207
225
  - lib/qe/resque.rb
208
226
  - lib/qe/sidekiq.rb
@@ -210,17 +228,22 @@ files:
210
228
  - lib/qe/testing/rspec.rb
211
229
  - lib/qe/version.rb
212
230
  - lib/qe/worker.rb
231
+ - lib/qe/worker/class_methods.rb
232
+ - lib/qe/worker/instance_methods.rb
213
233
  - qe.gemspec
214
234
  - spec/qe/action_spec.rb
215
235
  - spec/qe/beanstalk_spec.rb
216
236
  - spec/qe/delayed_job_spec.rb
217
237
  - spec/qe/enqueue_matcher_spec.rb
218
238
  - spec/qe/immediate_spec.rb
239
+ - spec/qe/locale_spec.rb
219
240
  - spec/qe/qu_spec.rb
220
241
  - spec/qe/resque_spec.rb
221
242
  - spec/qe/sidekiq_spec.rb
222
243
  - spec/qe/worker_spec.rb
223
244
  - spec/spec_helper.rb
245
+ - spec/support/hello_worker.rb
246
+ - spec/support/localized_worker.rb
224
247
  homepage: http://rubygems.org/gems/qe
225
248
  licenses: []
226
249
  post_install_message:
@@ -241,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
241
264
  version: '0'
242
265
  requirements: []
243
266
  rubyforge_project:
244
- rubygems_version: 1.8.24
267
+ rubygems_version: 1.8.25
245
268
  signing_key:
246
269
  specification_version: 3
247
270
  summary: A simple interface over several background job libraries like Resque, Sidekiq