resque-dynamic-queues 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 0.7.0
2
+ -----
3
+
4
+ api breaking refactor, web ui improvements <51948a0> [Matt Conway]
5
+ add rackup config for testing web ui <009ccda> [Matt Conway]
6
+
1
7
  0.6.1
2
8
  -----
3
9
 
data/config.ru ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'logger'
3
+
4
+ $LOAD_PATH.unshift ::File.expand_path(::File.dirname(__FILE__) + '/lib')
5
+ require 'resque/server'
6
+ require 'resque-dynamic-queues-server'
7
+
8
+ use Rack::ShowExceptions
9
+ run Resque::Server.new
@@ -1,2 +1,4 @@
1
1
  require 'resque-dynamic-queues'
2
- require 'resque/plugins/dynamic_queues/server'
2
+ require 'resque/plugins/dynamic_queues/server'
3
+
4
+ Resque::Server.register Resque::Plugins::DynamicQueues::Server
@@ -2,40 +2,50 @@ module Resque
2
2
  module Plugins
3
3
  module DynamicQueues
4
4
 
5
- KEY_PREFIX = "dynamic_queue"
5
+ DYNAMIC_QUEUE_KEY = "dynamic_queue"
6
6
  FALLBACK_KEY = "default"
7
7
 
8
8
  module Attributes
9
9
 
10
- def get_dynamic_queue(key)
11
- queue_names = redis.lrange("#{KEY_PREFIX}:#{key}", 0, -1)
10
+ def get_dynamic_queue(key, fallback=['*'])
11
+ data = redis.hget(DYNAMIC_QUEUE_KEY, key)
12
+ queue_names = Resque.decode(data)
12
13
 
13
14
  if queue_names.nil? || queue_names.size == 0
14
- queue_names = redis.lrange("#{KEY_PREFIX}:#{FALLBACK_KEY}", 0, -1)
15
+ data = redis.hget(DYNAMIC_QUEUE_KEY, FALLBACK_KEY)
16
+ queue_names = Resque.decode(data)
15
17
  end
16
18
 
17
19
  if queue_names.nil? || queue_names.size == 0
18
- queue_names = Resque.queues
20
+ queue_names = fallback
19
21
  end
20
22
 
21
23
  return queue_names
22
24
  end
23
25
 
24
26
  def set_dynamic_queue(key, values)
25
- k = "#{KEY_PREFIX}:#{key}"
27
+ if values.nil? or values.size == 0
28
+ redis.hdel(DYNAMIC_QUEUE_KEY, key)
29
+ else
30
+ redis.hset(DYNAMIC_QUEUE_KEY, key, Resque.encode(values))
31
+ end
32
+ end
33
+
34
+ def set_dynamic_queues(dynamic_queues)
26
35
  redis.multi do
27
- redis.del(k)
28
- Array(values).each do |v|
29
- redis.rpush(k, v)
36
+ redis.del(DYNAMIC_QUEUE_KEY)
37
+ dynamic_queues.each do |k, v|
38
+ set_dynamic_queue(k, v)
30
39
  end
31
40
  end
32
41
  end
33
42
 
34
43
  def get_dynamic_queues
35
- dqueues = redis.keys("#{KEY_PREFIX}:*") || []
36
- dqueues = dqueues.collect{|q| q.gsub('dynamic_queue:', '')}
37
- dqueues << FALLBACK_KEY unless dqueues.include?(FALLBACK_KEY)
38
- return dqueues
44
+ result = {}
45
+ queues = redis.hgetall(DYNAMIC_QUEUE_KEY)
46
+ queues.each {|k, v| result[k] = Resque.decode(v) }
47
+ result[FALLBACK_KEY] ||= ['*']
48
+ return result
39
49
  end
40
50
 
41
51
  end
@@ -9,25 +9,46 @@ module Resque
9
9
 
10
10
  def self.registered(app)
11
11
  app.get "/dynamicqueues" do
12
- @queues = Resque.get_dynamic_queues
13
- dq_view :queues
12
+ @queues = []
13
+ dqueues = Resque.get_dynamic_queues
14
+ dqueues.each do |k, v|
15
+ view_data = {
16
+ 'name' => k,
17
+ 'value' => Array(v).join(", "),
18
+ 'expanded' => Resque::Worker.new("@#{k}").queues.join(", ")
19
+ }
20
+ @queues << view_data
21
+ end
22
+
23
+ @queues.sort! do |a, b|
24
+ an = a['name']
25
+ bn = b['name']
26
+ if an == 'default'
27
+ 1
28
+ elsif bn == 'default'
29
+ -1
30
+ else
31
+ an <=> bn
32
+ end
33
+ end
34
+
35
+ plugin_view :queues
14
36
  end
15
37
 
16
38
  app.post "/dynamicqueues" do
17
- key = params['name']
18
- values = params['queues'].to_s.split.collect{|q| q.gsub(/\s/, '')}
19
- Resque.set_dynamic_queue(key, values)
20
- redirect url(:dynamicqueues)
21
- end
22
-
23
- app.post "/dynamicqueues/:key/remove" do
24
- key = params['key']
25
- Resque.set_dynamic_queue(key, [])
39
+ dynamic_queues = Array(params['queues'])
40
+ queues = {}
41
+ dynamic_queues.each do |queue|
42
+ key = queue['name']
43
+ values = queue['value'].to_s.split(',').collect{|q| q.gsub(/\s/, '') }
44
+ queues[key] = values
45
+ end
46
+ Resque.set_dynamic_queues(queues)
26
47
  redirect url(:dynamicqueues)
27
48
  end
28
49
 
29
50
  app.helpers do
30
- def dq_view(filename, options = {}, locals = {})
51
+ def plugin_view(filename, options = {}, locals = {})
31
52
  erb(File.read(File.join(::Resque::Plugins::DynamicQueues::Server::VIEW_PATH, "#{filename}.erb")), options, locals)
32
53
  end
33
54
  end
@@ -38,5 +59,3 @@ module Resque
38
59
  end
39
60
  end
40
61
  end
41
-
42
- Resque::Server.register Resque::Plugins::DynamicQueues::Server
@@ -1,58 +1,61 @@
1
1
  <h1>Dynamic Queues</h1>
2
- <table class='workers'>
3
- <tr>
4
- <th>Name</th>
5
- <th>Value</th>
6
- <th>Result</th>
7
- <th>Workers</th>
8
- <th></th>
9
- </tr>
10
- <% @queues.each do |queue| %>
2
+ <p class="intro">
3
+ The list below shows the dynamic queues currently defined. When you start a worker with a dynamic queue key (@key_name), that key is looked up from the list below to determine the actual queues the worker should pull from. Wildcards (*) and negation (leading !) can be used to select the queues the worker should process. There is always a fallback key - @default, which workers will use if the key for that worker is empty. If both the key and the fallback are empty, the worker defaults to processing '*'
4
+ </p>
5
+
6
+ <form action="<%= url(:dynamicqueues) %>" method="POST" style="float:none; margin-top:10px">
7
+
8
+ <table class='queues'>
11
9
  <tr>
12
- <td><%= queue %></td>
13
- <td><%= Resque.get_dynamic_queue(queue).join(", ") %></td>
14
- <td><%= Resque::Worker.new("@#{queue}").queues.join(", ") %></td>
15
- <td></td>
16
- <td>
17
- <a href="<%= url(:dynamicqueues) %>/<%= queue %>/remove" class="remove">Remove</a>
18
- </td>
10
+ <th>Name</th>
11
+ <th>Value</th>
12
+ <th>Expanded</th>
13
+ <th></th>
19
14
  </tr>
20
- <% end %>
21
- </table>
22
-
23
-
24
- <h1>Make a new queue</h1>
25
- <form action="<%= url(:dynamicqueues) %>" method="post" accept-charset="utf-8">
26
- <p><input type="text" name="name"></p>
27
- <p>
28
- <textarea name="queues"></textarea>
29
- Separate new queues by lines
30
- </p>
31
- <p><input type="submit" value="Create or Update"></p>
32
- </form>
15
+ <% @queues.each_with_index do |data, i| %>
16
+ <tr class="line">
17
+ <td><input type="text" id="input-<%= i %>-name" name="queues[][name]" value="<%= data['name'] %>" /></td>
18
+ <td><input type="text" id="input-<%= i %>-value" name="queues[][value]" value="<%= data['value'] %>" /></td>
19
+ <td class="expanded"><%= data['expanded'] %></td>
20
+ <td>
21
+ <a href="#remove" class="remove">Remove</a>
22
+ </td>
23
+ </tr>
24
+ <% end %>
25
+ </table>
26
+
27
+ <a href="#add" class="add">Add</a>
28
+ <input type="submit" value="Save"/>
33
29
 
30
+ </form>
34
31
 
35
32
  <script type="text/javascript" charset="utf-8">
33
+ function markDirty()
34
+ {
35
+ $("input[type=submit]").css({border:"3px orange solid"});
36
+ }
37
+
36
38
  jQuery(function($) {
37
39
 
38
- $('a.remove').click(function(e) {
40
+ $("input").live("keypress", markDirty);
41
+
42
+ $("a.add").live("click", function(e) {
43
+ e.preventDefault();
44
+ var $table = $("table.queues");
45
+ var $newRow = $table.find("tr.line:first").clone();
46
+ $newRow.find("input[type=text]").attr("value", "");
47
+ $newRow.find("td.expanded").html("")
48
+ $newRow.appendTo($table);
49
+ markDirty();
50
+ });
51
+
52
+ $("a.remove").live("click", function(e) {
39
53
  e.preventDefault();
40
- var $link = $(this),
41
- url = $link.attr('href'),
42
- confirmed = confirm("Are you sure you want to remove this dynamic queue? There is no undo.");
43
- if (confirmed) {
44
- $link.animate({opacity: 0.5});
45
- $.ajax({
46
- url: url,
47
- type: 'post',
48
- success: function() {
49
- $link.parents('tr').remove();
50
- }
51
- });
52
- } else {
53
- return false
54
- }
54
+ var $link = $(this);
55
+ $link.parents("tr").remove();
56
+ markDirty();
55
57
  });
56
58
 
59
+
57
60
  });
58
61
  </script>
@@ -1,7 +1,7 @@
1
1
  module Resque
2
2
  module Plugins
3
3
  module DynamicQueues
4
- VERSION = "0.6.1"
4
+ VERSION = "0.7.0"
5
5
  end
6
6
  end
7
7
  end
data/spec/queues_spec.rb CHANGED
@@ -55,6 +55,42 @@ describe "Dynamic Queues" do
55
55
 
56
56
  end
57
57
 
58
+ context "attributes" do
59
+ it "should always have a fallback pattern" do
60
+ Resque.get_dynamic_queues.should == {'default' => ['*']}
61
+ end
62
+
63
+ it "should allow setting single patterns" do
64
+ Resque.get_dynamic_queue('foo').should == ['*']
65
+ Resque.set_dynamic_queue('foo', ['bar'])
66
+ Resque.get_dynamic_queue('foo').should == ['bar']
67
+ end
68
+
69
+ it "should allow setting multiple patterns" do
70
+ Resque.set_dynamic_queues({'foo' => ['bar'], 'baz' => ['boo']})
71
+ Resque.get_dynamic_queues.should == {'foo' => ['bar'], 'baz' => ['boo'], 'default' => ['*']}
72
+ end
73
+
74
+ it "should remove mapping when setting empty value" do
75
+ Resque.get_dynamic_queues
76
+ Resque.set_dynamic_queues({'foo' => ['bar'], 'baz' => ['boo']})
77
+ Resque.get_dynamic_queues.should == {'foo' => ['bar'], 'baz' => ['boo'], 'default' => ['*']}
78
+
79
+ Resque.set_dynamic_queues({'foo' => [], 'baz' => ['boo']})
80
+ Resque.get_dynamic_queues.should == {'baz' => ['boo'], 'default' => ['*']}
81
+ Resque.set_dynamic_queues({'baz' => nil})
82
+ Resque.get_dynamic_queues.should == {'default' => ['*']}
83
+
84
+ Resque.set_dynamic_queues({'foo' => ['bar'], 'baz' => ['boo']})
85
+ Resque.set_dynamic_queue('foo', [])
86
+ Resque.get_dynamic_queues.should == {'baz' => ['boo'], 'default' => ['*']}
87
+ Resque.set_dynamic_queue('baz', nil)
88
+ Resque.get_dynamic_queues.should == {'default' => ['*']}
89
+ end
90
+
91
+
92
+ end
93
+
58
94
  context "basic queue patterns" do
59
95
 
60
96
  before(:each) do
data/spec/server_spec.rb CHANGED
@@ -37,6 +37,12 @@ describe "Dynamic Queues pages" do
37
37
 
38
38
  context "show dynamic queues table" do
39
39
 
40
+ it "should shows default queue when nothing set" do
41
+ get "/dynamicqueues"
42
+
43
+ last_response.body.should include 'default'
44
+ end
45
+
40
46
  it "should shows names of queues" do
41
47
  Resque.set_dynamic_queue("key_one", ["foo"])
42
48
  Resque.set_dynamic_queue("key_two", ["bar"])
@@ -61,23 +67,18 @@ describe "Dynamic Queues pages" do
61
67
 
62
68
  context "remove queue link" do
63
69
 
64
-
65
- it "should shows remove link for queue" do
70
+ it "should show remove link for queue" do
66
71
  Resque.set_dynamic_queue("key_one", ["foo"])
67
72
 
68
73
  get "/dynamicqueues"
69
74
 
70
- last_response.body.should match /<a .*href=['"]http:\/\/example.org\/dynamicqueues\/key_one\/remove['"].*>/
75
+ last_response.body.should match /<a .*href=['"]#remove['"].*>/
71
76
  end
72
77
 
73
- it "should remove queue when remove link clicked" do # JS will do the post
74
- Resque.set_dynamic_queue("key_one", ["foo"])
75
-
76
- post "/dynamicqueues/key_one/remove"
78
+ it "should show add link" do
79
+ get "/dynamicqueues"
77
80
 
78
- last_response.should be_redirect
79
- last_response['Location'].should match /dynamicqueues/
80
- Resque.get_dynamic_queue("key_two").should be_empty
81
+ last_response.body.should match /<a .*href=['"]#add['"].*>/
81
82
  end
82
83
 
83
84
  end
@@ -87,22 +88,31 @@ describe "Dynamic Queues pages" do
87
88
  it "should have form to edit queues" do
88
89
  get "/dynamicqueues"
89
90
 
90
- last_response.body.should match /<form .*action=['"]http:\/\/example.org\/dynamicqueues['"].*>/
91
- last_response.body.should match /<input .*name=['"]name['"].*>/
92
- last_response.body.should match /<textarea .*name=['"]queues['"].*>/
91
+ last_response.body.should match /<form action="http:\/\/example.org\/dynamicqueues"/
92
+ end
93
+
94
+ it "should show input fields" do
95
+ Resque.set_dynamic_queue("key_one", ["foo"])
96
+ Resque.set_dynamic_queue("key_two", ["bar", "baz"])
97
+ get "/dynamicqueues"
98
+
99
+ last_response.body.should match /<input type="text" id="input-0-name" name="queues\[\]\[name\]" value="key_one"/
100
+ last_response.body.should match /<input type="text" id="input-0-value" name="queues\[\]\[value\]" value="foo"/
101
+ last_response.body.should match /<input type="text" id="input-1-name" name="queues\[\]\[name\]" value="key_two"/
102
+ last_response.body.should match /<input type="text" id="input-1-value" name="queues\[\]\[value\]" value="bar, baz"/
93
103
  end
94
104
 
95
105
  it "should delete queues on empty queue submit" do
96
106
  Resque.set_dynamic_queue("key_two", ["bar", "baz"])
97
- post "/dynamicqueues", {'name' => "key_two", "queues" => ""}
107
+ post "/dynamicqueues", {'queues' => [{'name' => "key_two", "value" => ""}]}
98
108
 
99
109
  last_response.should be_redirect
100
110
  last_response['Location'].should match /dynamicqueues/
101
- Resque.get_dynamic_queue("key_two").should be_empty
111
+ Resque.get_dynamic_queue("key_two", []).should be_empty
102
112
  end
103
113
 
104
114
  it "should create queues" do
105
- post "/dynamicqueues", {'name' => "key_two", "queues" => "foo\n\rbar\n\rbaz"}
115
+ post "/dynamicqueues", {'queues' => [{'name' => "key_two", "value" => " foo, bar ,baz "}]}
106
116
 
107
117
  last_response.should be_redirect
108
118
  last_response['Location'].should match /dynamicqueues/
@@ -111,7 +121,7 @@ describe "Dynamic Queues pages" do
111
121
 
112
122
  it "should update queues" do
113
123
  Resque.set_dynamic_queue("key_two", ["bar", "baz"])
114
- post "/dynamicqueues", {'name' => "key_two", "queues" => "foo\n\rbar\n\rbaz"}
124
+ post "/dynamicqueues", {'queues' => [{'name' => "key_two", "value" => "foo,bar,baz"}]}
115
125
 
116
126
  last_response.should be_redirect
117
127
  last_response['Location'].should match /dynamicqueues/
@@ -120,4 +130,4 @@ describe "Dynamic Queues pages" do
120
130
 
121
131
  end
122
132
 
123
- end
133
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-dynamic-queues
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-07 00:00:00.000000000Z
12
+ date: 2011-12-13 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: resque
16
- requirement: &2176833480 !ruby/object:Gem::Requirement
16
+ requirement: &2236617460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '1.10'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2176833480
24
+ version_requirements: *2236617460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2176808620 !ruby/object:Gem::Requirement
27
+ requirement: &2236616960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '2.5'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2176808620
35
+ version_requirements: *2236616960
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rack-test
38
- requirement: &2176798820 !ruby/object:Gem::Requirement
38
+ requirement: &2236616500 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 0.5.4
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2176798820
46
+ version_requirements: *2236616500
47
47
  description: A resque plugin for specifying the queues a worker pulls from with wildcards,
48
48
  negations, or dynamic look up from redis
49
49
  email:
@@ -57,6 +57,7 @@ files:
57
57
  - Gemfile
58
58
  - README.md
59
59
  - Rakefile
60
+ - config.ru
60
61
  - init.rb
61
62
  - lib/resque-dynamic-queues-server.rb
62
63
  - lib/resque-dynamic-queues.rb