resque-pause 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ coverage/*
5
+ .rvmrc
6
+ .project
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in resque-pause.gemspec
4
+ gemspec
5
+
6
+ group :test, :development do
7
+ platforms :mri_18 do
8
+ gem "ruby-debug"
9
+ end
10
+
11
+ platforms :mri_19 do
12
+ gem "ruby-debug19", :require => 'ruby-debug' if RUBY_VERSION < "1.9.3"
13
+ end
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,73 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ resque-pause (0.0.2)
5
+ resque (>= 1.9.10)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ archive-tar-minitar (0.5.2)
11
+ columnize (0.3.3)
12
+ diff-lcs (1.1.2)
13
+ json_pure (1.4.6)
14
+ linecache (0.46)
15
+ rbx-require-relative (> 0.0.4)
16
+ linecache19 (0.5.12)
17
+ ruby_core_source (>= 0.1.4)
18
+ rack (1.3.0)
19
+ rack-test (0.6.0)
20
+ rack (>= 1.0)
21
+ rbx-require-relative (0.0.5)
22
+ redis (2.2.1)
23
+ redis-namespace (0.8.0)
24
+ redis (< 3.0.0)
25
+ resque (1.9.10)
26
+ json_pure (~> 1.4.0)
27
+ redis-namespace (~> 0.8.0)
28
+ sinatra (>= 0.9.2)
29
+ vegas (~> 0.1.2)
30
+ rspec (2.6.0)
31
+ rspec-core (~> 2.6.0)
32
+ rspec-expectations (~> 2.6.0)
33
+ rspec-mocks (~> 2.6.0)
34
+ rspec-core (2.6.4)
35
+ rspec-expectations (2.6.0)
36
+ diff-lcs (~> 1.1.2)
37
+ rspec-mocks (2.6.0)
38
+ ruby-debug (0.10.4)
39
+ columnize (>= 0.1)
40
+ ruby-debug-base (~> 0.10.4.0)
41
+ ruby-debug-base (0.10.4)
42
+ linecache (>= 0.3)
43
+ ruby-debug-base19 (0.11.25)
44
+ columnize (>= 0.3.1)
45
+ linecache19 (>= 0.5.11)
46
+ ruby_core_source (>= 0.1.4)
47
+ ruby-debug19 (0.11.6)
48
+ columnize (>= 0.3.1)
49
+ linecache19 (>= 0.5.11)
50
+ ruby-debug-base19 (>= 0.11.19)
51
+ ruby_core_source (0.1.5)
52
+ archive-tar-minitar (>= 0.5.2)
53
+ simplecov (0.4.2)
54
+ simplecov-html (~> 0.4.4)
55
+ simplecov-html (0.4.5)
56
+ sinatra (1.2.6)
57
+ rack (~> 1.1)
58
+ tilt (>= 1.2.2, < 2.0)
59
+ tilt (1.3.2)
60
+ vegas (0.1.8)
61
+ rack (>= 1.0.0)
62
+
63
+ PLATFORMS
64
+ ruby
65
+
66
+ DEPENDENCIES
67
+ rack-test
68
+ resque (>= 1.9.10)
69
+ resque-pause!
70
+ rspec (>= 2.3.0)
71
+ ruby-debug
72
+ ruby-debug19
73
+ simplecov (>= 0.4.2)
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ Resque Pause
2
+ ============
3
+
4
+ A [Resque][rq] plugin. Requires Resque 1.9.10.
5
+
6
+ resque-pause adds functionality to pause resque jobs through the web interface.
7
+
8
+ Using a `pause` allows you to stop the job for a slice of time.
9
+ The job finish the process it are doing and don't get a new task to do,
10
+ until the queue is released.
11
+ You can use this functionality to do some maintenance whithout kill workers, for example.
12
+
13
+ Usage / Examples
14
+ ----------------
15
+
16
+ ### Single Job Instance
17
+
18
+ require 'resque-pause'
19
+
20
+ class UpdateNetworkGraph
21
+ extend Resque::Plugins::Pause
22
+ @queue = :network_graph
23
+
24
+ def self.perform(repo_id)
25
+ heavy_lifting
26
+ end
27
+ end
28
+
29
+ Pause is achieved by storing a pause/queue key in Redis.
30
+
31
+ Default behaviour...
32
+
33
+ * When the job instance try to execute and the queue is paused, the job is paused for a slice of time.
34
+ * If the queue still paused after this time the job will abort and will be enqueued again with the same arguments.
35
+
36
+
37
+ Resque-Web integration
38
+ ----------------------
39
+
40
+ You have to load ResquePause to enable the Pause tab.
41
+
42
+ ```ruby
43
+ require 'resque_pause'
44
+ ```
45
+
46
+ Customise & Extend
47
+ ==================
48
+
49
+ ### Job pause check interval
50
+
51
+ The slice of time the job will wait for queue be unpaused before abort the job
52
+ could be changed with attribute @pause_check_interval.
53
+
54
+ By default the time is 10 seconds.
55
+
56
+ You can define the attribute in your job class in seconds.
57
+
58
+ class UpdateNetworkGraph
59
+ extend Resque::Plugins::Pause
60
+ @queue = :network_graph
61
+ @pause_check_interval = 30
62
+
63
+ def self.perform(repo_id)
64
+ heavy_lifting
65
+ end
66
+ end
67
+
68
+ The above modification will ensure the job will wait for 30 seconds before abort.
69
+
70
+
71
+ Install
72
+ =======
73
+
74
+ $ gem install resque-pause
75
+
76
+ [rq]: http://github.com/defunkt/resque
77
+ [resque-pause]: https://github.com/wandenberg/resque-pause
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rspec/core/rake_task"
5
+
6
+ desc "Run all examples"
7
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,3 @@
1
+ require 'resque'
2
+ require File.expand_path(File.join('resque_pause_helper'), File.dirname(__FILE__))
3
+ require File.expand_path(File.join('resque', 'plugins', 'pause'), File.dirname(__FILE__))
@@ -0,0 +1,15 @@
1
+ module Resque
2
+ module Plugins
3
+ module Pause
4
+ include Resque::Helpers
5
+ PAUSE_CHECK_INTERVAL = 10 #seconds to wait when queue is paused
6
+
7
+ def before_perform_pause(*args)
8
+ if ResquePauseHelper.paused?(@queue)
9
+ Kernel.sleep(@pause_check_interval || Resque::Plugins::Pause::PAUSE_CHECK_INTERVAL)
10
+ ResquePauseHelper.check_paused(:queue => @queue, :class => self, :args => args)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ require 'resque'
2
+ require 'resque/server'
3
+ require File.expand_path(File.join('resque_pause_helper'), File.dirname(__FILE__))
4
+ require File.expand_path(File.join('resque_pause', 'server'), File.dirname(__FILE__))
@@ -0,0 +1,56 @@
1
+ # Extends Resque Web Based UI.
2
+ # Structure has been borrowed from ResqueScheduler.
3
+ module ResquePause
4
+ module Server
5
+ include Resque::Helpers
6
+
7
+ def self.erb_path(filename)
8
+ File.join(File.dirname(__FILE__), 'server', 'views', filename)
9
+ end
10
+
11
+ def self.public_path(filename)
12
+ File.join(File.dirname(__FILE__), 'server', 'public', filename)
13
+ end
14
+
15
+ def self.included(base)
16
+
17
+ base.class_eval do
18
+
19
+ helpers do
20
+ def paused?(queue)
21
+ ResquePauseHelper.paused?(queue)
22
+ end
23
+ end
24
+
25
+ mime_type :json, 'application/json'
26
+
27
+ get '/pause' do
28
+ erb File.read(ResquePause::Server.erb_path('pause.erb'))
29
+ end
30
+
31
+ post '/pause' do
32
+ ResquePauseHelper.pause(params['queue_name']) unless params['queue_name'].empty?
33
+ content_type :json
34
+ encode(:queue_name => params['queue_name'], :paused => true)
35
+ end
36
+
37
+ post '/unpause' do
38
+ ResquePauseHelper.unpause(params['queue_name']) unless params['queue_name'].empty?
39
+ content_type :json
40
+ encode(:queue_name => params['queue_name'], :paused => false)
41
+ end
42
+
43
+ get /pause\/public\/([a-z]+\.[a-z]+)/ do
44
+ send_file ResquePause::Server.public_path(params[:captures].first)
45
+ end
46
+ end
47
+ end
48
+
49
+ Resque::Server.tabs << 'Pause'
50
+ end
51
+ end
52
+
53
+ Resque.extend ResquePause
54
+ Resque::Server.class_eval do
55
+ include ResquePause::Server
56
+ end
@@ -0,0 +1,18 @@
1
+ jQuery(document).ready(function($) {
2
+ $('input:checkbox.pause').click( function(){
3
+ var queue = $(this);
4
+ var data = {'queue_name': queue.val()};
5
+ var url = queue.is(':checked') ? '/pause' : '/unpause';
6
+ $.ajax({
7
+ type: 'POST',
8
+ url: url,
9
+ data: data,
10
+ async: false,
11
+ cache: false,
12
+ success: function() { return true; },
13
+ error: function() { return false; },
14
+ dataType: 'json'
15
+ });
16
+
17
+ });
18
+ });
@@ -0,0 +1,18 @@
1
+ <script src="<%=u '/pause/public/pause.js' %>" type="text/javascript"></script>
2
+
3
+ <h1 class='wi'>Queues</h1>
4
+ <p class='intro'>The list below contains all the registered queues with the status if is paused or not. Select a queue from above to pause processing jobs.</p>
5
+ <table class='queues1'>
6
+ <tr>
7
+ <th>Name</th>
8
+ <th>Paused</th>
9
+ <th>Jobs</th>
10
+ </tr>
11
+ <% for queue in resque.queues.sort_by { |q| q.to_s } %>
12
+ <tr>
13
+ <td class='queue'><%= queue %></td>
14
+ <td class='status'><input class="pause" type="checkbox" value="<%= queue%>" <%= "checked" if paused?(queue) %>></input></td>
15
+ <td class='size'><%= resque.size queue %></td>
16
+ </tr>
17
+ <% end %>
18
+ </table>
@@ -0,0 +1,30 @@
1
+ module ResquePauseHelper
2
+ class << self
3
+ def paused?(queue)
4
+ !Resque.redis.get("pause:queue:#{queue}").nil?
5
+ end
6
+
7
+ def pause(queue)
8
+ Resque.redis.set "pause:queue:#{queue}", true
9
+ end
10
+
11
+ def unpause(queue)
12
+ Resque.redis.del "pause:queue:#{queue}"
13
+ end
14
+
15
+ def enqueue_job(args)
16
+ Resque.redis.lpush("queue:#{args[:queue]}", Resque.encode(:class => args[:class], :args => args[:args]))
17
+ end
18
+
19
+ def dequeue_job(args)
20
+ Resque.redis.lpop("queue:#{args[:queue]}")
21
+ end
22
+
23
+ def check_paused(args)
24
+ if ResquePauseHelper.paused?(args[:queue])
25
+ enqueue_job(args)
26
+ raise Resque::Job::DontPerform.new "Queue #{args[:queue]} is paused!"
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Resque
2
+ module Plugins
3
+ module Pause
4
+ VERSION = "0.0.2"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "resque-pause"
7
+ s.version = Resque::Plugins::Pause::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Wandenberg Peixoto"]
10
+ s.email = ["wandenberg@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{A Resque plugin to add functionality to pause resque jobs through the web interface.}
13
+ s.description = %q{A Resque plugin to add functionality to pause resque jobs through the web interface.
14
+
15
+ Using a `pause` allows you to stop the job for a slice of time.
16
+ The job finish the process it are doing and don't get a new task to do,
17
+ until the queue is released.
18
+ You can use this functionality to do some maintenance whithout kill workers, for example.}
19
+
20
+ s.rubyforge_project = "resque-pause"
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ s.has_rdoc = false
27
+
28
+ s.add_dependency('resque', '>= 1.9.10')
29
+
30
+ s.add_development_dependency('rspec', '>= 2.3.0')
31
+ s.add_development_dependency('rack-test')
32
+ s.add_development_dependency('simplecov', '>= 0.4.2')
33
+
34
+ end
@@ -0,0 +1,115 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile ./spec/redis-test.pid
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port 9736
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Save the DB on disk:
23
+ #
24
+ # save <seconds> <changes>
25
+ #
26
+ # Will save the DB if both the given number of seconds and the given
27
+ # number of write operations against the DB occurred.
28
+ #
29
+ # In the example below the behaviour will be to save:
30
+ # after 900 sec (15 min) if at least 1 key changed
31
+ # after 300 sec (5 min) if at least 10 keys changed
32
+ # after 60 sec if at least 10000 keys changed
33
+ save 900 1
34
+ save 300 10
35
+ save 60 10000
36
+
37
+ # The filename where to dump the DB
38
+ dbfilename dump.rdb
39
+
40
+ # For default save/load DB in/from the working directory
41
+ # Note that you must specify a directory not a file name.
42
+ dir ./spec/
43
+
44
+ # Set server verbosity to 'debug'
45
+ # it can be one of:
46
+ # debug (a lot of information, useful for development/testing)
47
+ # notice (moderately verbose, what you want in production probably)
48
+ # warning (only very important / critical messages are logged)
49
+ loglevel debug
50
+
51
+ # Specify the log file name. Also 'stdout' can be used to force
52
+ # the demon to log on the standard output. Note that if you use standard
53
+ # output for logging but daemonize, logs will be sent to /dev/null
54
+ logfile stdout
55
+
56
+ # Set the number of databases. The default database is DB 0, you can select
57
+ # a different one on a per-connection basis using SELECT <dbid> where
58
+ # dbid is a number between 0 and 'databases'-1
59
+ databases 16
60
+
61
+ ################################# REPLICATION #################################
62
+
63
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
64
+ # another Redis server. Note that the configuration is local to the slave
65
+ # so for example it is possible to configure the slave to save the DB with a
66
+ # different interval, or to listen to another port, and so on.
67
+
68
+ # slaveof <masterip> <masterport>
69
+
70
+ ################################## SECURITY ###################################
71
+
72
+ # Require clients to issue AUTH <PASSWORD> before processing any other
73
+ # commands. This might be useful in environments in which you do not trust
74
+ # others with access to the host running redis-server.
75
+ #
76
+ # This should stay commented out for backward compatibility and because most
77
+ # people do not need auth (e.g. they run their own servers).
78
+
79
+ # requirepass foobared
80
+
81
+ ################################### LIMITS ####################################
82
+
83
+ # Set the max number of connected clients at the same time. By default there
84
+ # is no limit, and it's up to the number of file descriptors the Redis process
85
+ # is able to open. The special value '0' means no limts.
86
+ # Once the limit is reached Redis will close all the new connections sending
87
+ # an error 'max number of clients reached'.
88
+
89
+ # maxclients 128
90
+
91
+ # Don't use more memory than the specified amount of bytes.
92
+ # When the memory limit is reached Redis will try to remove keys with an
93
+ # EXPIRE set. It will try to start freeing keys that are going to expire
94
+ # in little time and preserve keys with a longer time to live.
95
+ # Redis will also try to remove objects from free lists if possible.
96
+ #
97
+ # If all this fails, Redis will start to reply with errors to commands
98
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
99
+ # to reply to most read-only commands like GET.
100
+ #
101
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
102
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
103
+ # database the memory usage will grow over the weeks, it will be obvious if
104
+ # it is going to use too much memory in the long run, and you'll have the time
105
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
106
+ # errors for write operations, and this may even lead to DB inconsistency.
107
+
108
+ # maxmemory <bytes>
109
+
110
+ ############################### ADVANCED CONFIG ###############################
111
+
112
+ # Glue small output buffers together in order to send small replies in a
113
+ # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
+ # in terms of number of queries per second. Use 'yes' if unsure.
115
+ glueoutputbuf yes
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe ResquePause::Server do
4
+ include Rack::Test::Methods
5
+ def app
6
+ @app ||= Resque::Server.new
7
+ end
8
+
9
+ let :queues do
10
+ Resque.redis.sadd(:queues, "queue1")
11
+ Resque.redis.sadd(:queues, "queue2")
12
+ Resque.redis.sadd(:queues, "queue3")
13
+ end
14
+
15
+ before do
16
+ queues
17
+ end
18
+
19
+ it "should respond to /pause" do
20
+ get '/pause'
21
+ last_response.should be_ok
22
+ end
23
+
24
+ it "should list all registered queues" do
25
+ get '/pause'
26
+ last_response.body.should include("queue1")
27
+ last_response.body.should include("queue2")
28
+ last_response.body.should include("queue3")
29
+ end
30
+
31
+ it "should check paused queues" do
32
+ ResquePauseHelper.pause("queue2")
33
+
34
+ get '/pause'
35
+ last_response.body.should include(%q{<input class="pause" type="checkbox" value="queue1" ></input>})
36
+ last_response.body.should include(%q{<input class="pause" type="checkbox" value="queue2" checked></input>})
37
+ last_response.body.should include(%q{<input class="pause" type="checkbox" value="queue3" ></input>})
38
+ end
39
+
40
+
41
+ it "should pause a queue" do
42
+ post "/pause", :queue_name => "queue3"
43
+
44
+ ResquePauseHelper.paused?("queue3").should be_true
45
+ end
46
+
47
+ it "should return a json when pause a queue" do
48
+ post "/pause", :queue_name => "queue3"
49
+
50
+ last_response.headers["Content-Type"].should == "application/json"
51
+ last_response.body.should == { :queue_name => "queue3", :paused => true }.to_json
52
+ end
53
+
54
+ it "should unpause a queue" do
55
+ ResquePauseHelper.pause("queue2")
56
+ post "/unpause", :queue_name => "queue2"
57
+
58
+ ResquePauseHelper.paused?("queue2").should be_false
59
+ end
60
+
61
+ it "should return a json when unpause a queue" do
62
+ post "/unpause", :queue_name => "queue2"
63
+
64
+ last_response.headers["Content-Type"].should == "application/json"
65
+ last_response.body.should == { :queue_name => "queue2", :paused => false }.to_json
66
+ end
67
+
68
+ it "should return static files" do
69
+ get "/pause/public/pause.js"
70
+ last_response.body.should == File.read(File.expand_path('../lib/resque_pause/server/public/pause.js', File.dirname(__FILE__)))
71
+ end
72
+
73
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ class PauseJob
4
+ extend Resque::Plugins::Pause
5
+ @queue = :test
6
+
7
+ def self.perform(*args)
8
+ end
9
+ end
10
+
11
+ describe Resque::Plugins::Pause do
12
+ it "should be compliance with Resqu::Plugin document" do
13
+ expect { Resque::Plugin.lint(Resque::Plugins::Pause) }.to_not raise_error
14
+ end
15
+
16
+ it "should use at least resque version 1.8.0" do
17
+ major, minor, patch = Resque::Version.split('.')
18
+ major.to_i.should == 1
19
+ minor.to_i.should >= 8
20
+ end
21
+
22
+ it "should execute the job when queue is not paused" do
23
+ Resque.enqueue(PauseJob)
24
+ PauseJob.should_receive(:perform)
25
+
26
+ Resque.reserve('test').perform
27
+ end
28
+
29
+ it "should not execute the job when queue is paused" do
30
+ ResquePauseHelper.pause('test')
31
+ Resque.enqueue(PauseJob)
32
+ PauseJob.should_not_receive(:perform)
33
+
34
+ Resque.reserve('test').perform
35
+ end
36
+
37
+ it "should not change queued jobs when queue is paused" do
38
+ ResquePauseHelper.pause('test')
39
+ Resque.enqueue(PauseJob, 1)
40
+ Resque.enqueue(PauseJob, 2)
41
+ Resque.enqueue(PauseJob, 3)
42
+ jobs = Resque.redis.lrange('queue:test', 0, 2)
43
+
44
+ Resque.reserve('test').perform
45
+
46
+ remaining_jobs = Resque.redis.lrange('queue:test', 0, 2)
47
+ jobs.should == remaining_jobs
48
+ end
49
+
50
+ it "should back to execute the job when queue is unpaused" do
51
+ Resque.enqueue(PauseJob)
52
+
53
+ ResquePauseHelper.pause('test')
54
+ Resque.reserve('test').perform
55
+ Resque.size('test').should == 1
56
+
57
+ ResquePauseHelper.unpause('test')
58
+ Resque.reserve('test').perform
59
+ Resque.size('test').should == 0
60
+ end
61
+
62
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ class PauseJob
4
+ @queue = :test
5
+
6
+ def self.perform(*args)
7
+ end
8
+ end
9
+
10
+ describe ResquePauseHelper do
11
+
12
+ context "when check queue status" do
13
+ it "should return return false if don't have register on redis" do
14
+ Resque.redis.del "pause:queue:queue1"
15
+
16
+ subject.paused?("queue1").should be_false
17
+ end
18
+
19
+ it "should return return true if have register on redis" do
20
+ Resque.redis.set "pause:queue:queue1", "AnyValue"
21
+
22
+ subject.paused?("queue1").should be_true
23
+ end
24
+ end
25
+
26
+ context "when pause a queue" do
27
+ it "should register a unregistred queue" do
28
+ Resque.redis.del "pause:queue:queue1"
29
+ subject.pause("queue1")
30
+
31
+ subject.paused?("queue1").should be_true
32
+ end
33
+
34
+ it "should register again a registred queue" do
35
+ Resque.redis.set "pause:queue:queue1", "AnyValue"
36
+ expect { subject.pause("queue1") }.to_not raise_error
37
+
38
+ Resque.redis.get("pause:queue:queue1").should_not be_nil
39
+ Resque.redis.get("pause:queue:queue1").should be_true
40
+ end
41
+ end
42
+
43
+ context "when unpause a queue" do
44
+ it "should unregister a unregistred queue" do
45
+ Resque.redis.del "pause:queue:queue1"
46
+ subject.unpause("queue1")
47
+
48
+ subject.paused?("queue1").should be_false
49
+ end
50
+
51
+ it "should unregister a registred queue" do
52
+ Resque.redis.set "pause:queue:queue1", "AnyValue"
53
+ expect { subject.unpause("queue1") }.to_not raise_error
54
+
55
+ Resque.redis.get("pause:queue:queue1").should be_nil
56
+ end
57
+ end
58
+
59
+ context "when enqueue a job" do
60
+ it "should enqueue on a empty queue" do
61
+ Resque.redis.del "queue:queue1"
62
+
63
+ subject.enqueue_job(:queue => "queue1", :class => PauseJob, :args => nil)
64
+
65
+ Resque.redis.llen("queue:queue1").to_i.should == 1
66
+ end
67
+
68
+ it "should enqueue on beginning of a queue" do
69
+ Resque.redis.lpush "queue:queue1", {:class => PauseJob, :args => [1, 2]}.to_json
70
+
71
+ subject.enqueue_job(:queue => "queue1", :class => PauseJob, :args => [1])
72
+
73
+ jobs = Resque.redis.lrange('queue:queue1', 0, 10)
74
+
75
+ jobs.count.should == 2
76
+ jobs[0].should == {:class => PauseJob, :args => [1]}.to_json
77
+ jobs[1].should == {:class => PauseJob, :args => [1, 2]}.to_json
78
+ end
79
+ end
80
+
81
+ context "when dequeue a job" do
82
+ it "should not get error when queue is empty" do
83
+ Resque.redis.del "queue:queue1"
84
+
85
+ expect { subject.dequeue_job(:queue => "queue1") }.to_not raise_error
86
+
87
+ subject.dequeue_job(:queue => "queue1").should be_nil
88
+ end
89
+
90
+ it "should get the job on beginning of a queue" do
91
+ Resque.redis.lpush "queue:queue1", {:class => PauseJob, :args => [1, 2]}.to_json
92
+ Resque.redis.lpush "queue:queue1", {:class => PauseJob, :args => [1]}.to_json
93
+
94
+ job = subject.dequeue_job(:queue => "queue1")
95
+ job.should == {:class => PauseJob, :args => [1]}.to_json
96
+ end
97
+ end
98
+
99
+ context "when checking if queue is paused" do
100
+ it "should check if queue is paused" do
101
+ subject.should_receive(:paused?).with("queue1")
102
+
103
+ subject.check_paused(:queue => "queue1")
104
+ end
105
+
106
+ it "should not raise error when queue is not paused" do
107
+ subject.should_receive(:paused?).with("queue1").and_return(false)
108
+
109
+ expect { subject.check_paused(:queue => "queue1") }.to_not raise_error
110
+ end
111
+
112
+ it "should raise error when queue is paused" do
113
+ subject.stub!(:enqueue_job)
114
+ subject.stub!(:paused?).with("queue1").and_return(true)
115
+
116
+ expect { subject.check_paused(:queue => "queue1") }.to raise_error(Resque::Job::DontPerform)
117
+ end
118
+
119
+ it "should enqueue the job again when queue is paused" do
120
+ subject.stub!(:paused?).with("queue1").and_return(true)
121
+
122
+ args = {:queue => "queue1", :class => PauseJob, :args => [1, 2]}
123
+ subject.should_receive(:enqueue_job).with(args)
124
+
125
+ subject.check_paused(args) rescue nil
126
+ end
127
+ end
128
+
129
+ end
@@ -0,0 +1,65 @@
1
+ require 'rack/test'
2
+
3
+ if !system("which redis-server")
4
+ puts '', "** can't find `redis-server` in your path"
5
+ abort ''
6
+ end
7
+
8
+ begin
9
+ require 'simplecov'
10
+ SimpleCov.start do
11
+ add_filter '/spec/'
12
+ end
13
+ SimpleCov.coverage_dir 'coverage'
14
+ rescue LoadError
15
+ # ignore simplecov in ruby < 1.9
16
+ end
17
+
18
+ begin
19
+ require 'bundler'
20
+ Bundler.setup
21
+ Bundler.require(:default, :development)
22
+ rescue LoadError
23
+ puts 'Bundler is not installed, you need to gem install it in order to run the specs.'
24
+ exit 1
25
+ end
26
+
27
+ # Requires supporting files with custom matchers and macros, etc,
28
+ # in ./support/ and its subdirectories.
29
+ Dir[File.expand_path('support/**/*.rb', File.dirname(__FILE__))].each { |f| require f }
30
+
31
+ # Requires lib.
32
+ Dir[File.expand_path('../lib/**/*.rb', File.dirname(__FILE__))].each { |f| require f }
33
+
34
+ RSpec.configure do |config|
35
+ # == Mock Framework
36
+ #
37
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
38
+ #
39
+ # config.mock_with :mocha
40
+ # config.mock_with :flexmock
41
+ # config.mock_with :rr
42
+ config.mock_with :rspec
43
+
44
+ config.before(:suite) do
45
+ puts "Starting redis for testing at localhost:9736..."
46
+ `redis-server #{File.dirname(File.expand_path(__FILE__))}/redis-test.conf`
47
+ pid = ''
48
+ while pid.empty? do
49
+ pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
50
+ end
51
+ Resque.redis = '127.0.0.1:9736'
52
+ end
53
+
54
+ config.before(:each) do
55
+ Resque.redis.flushall
56
+ Kernel.stub!(:sleep)
57
+ end
58
+
59
+ config.after(:suite) do
60
+ pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
61
+ puts '', "Killing test redis server..."
62
+ Process.kill("KILL", pid.to_i)
63
+ `rm -f #{File.dirname(File.expand_path(__FILE__))}/dump.rdb`
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque-pause
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Wandenberg Peixoto
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-06-27 00:00:00 -03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: resque
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 9
31
+ - 10
32
+ version: 1.9.10
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 2
45
+ - 3
46
+ - 0
47
+ version: 2.3.0
48
+ type: :development
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rack-test
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: simplecov
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ - 4
74
+ - 2
75
+ version: 0.4.2
76
+ type: :development
77
+ version_requirements: *id004
78
+ description: |-
79
+ A Resque plugin to add functionality to pause resque jobs through the web interface.
80
+
81
+ Using a `pause` allows you to stop the job for a slice of time.
82
+ The job finish the process it are doing and don't get a new task to do,
83
+ until the queue is released.
84
+ You can use this functionality to do some maintenance whithout kill workers, for example.
85
+ email:
86
+ - wandenberg@gmail.com
87
+ executables: []
88
+
89
+ extensions: []
90
+
91
+ extra_rdoc_files: []
92
+
93
+ files:
94
+ - .gitignore
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - README.md
98
+ - Rakefile
99
+ - lib/resque-pause.rb
100
+ - lib/resque/plugins/pause.rb
101
+ - lib/resque_pause.rb
102
+ - lib/resque_pause/server.rb
103
+ - lib/resque_pause/server/public/pause.js
104
+ - lib/resque_pause/server/views/pause.erb
105
+ - lib/resque_pause_helper.rb
106
+ - lib/version.rb
107
+ - resque-pause.gemspec
108
+ - spec/redis-test.conf
109
+ - spec/resque-web_spec.rb
110
+ - spec/resque/plugins/pause_spec.rb
111
+ - spec/resque_pause_helper_spec.rb
112
+ - spec/spec_helper.rb
113
+ has_rdoc: true
114
+ homepage: ""
115
+ licenses: []
116
+
117
+ post_install_message:
118
+ rdoc_options: []
119
+
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ requirements: []
139
+
140
+ rubyforge_project: resque-pause
141
+ rubygems_version: 1.3.7
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: A Resque plugin to add functionality to pause resque jobs through the web interface.
145
+ test_files: []
146
+