matthewrudy-rudeq 2.0 → 2.1.0

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.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [Matthew Rudy Jacobs]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,24 @@
1
+ Description:
2
+ The rude_q generator creates a fully functioning RudeQ.
3
+
4
+ The generator takes a model name as its argument. The model name may be
5
+ given in CamelCase or under_score and should not be suffixed with 'Model'.
6
+
7
+ The generator creates a model class in app/models, an RSpec spec in
8
+ spec/models, database fixtures in spec/fixtures/plural_name.yml, and a migration
9
+ in db/migrate.
10
+
11
+ All the generated files are fully functioning, and no extra work should be necessary.
12
+
13
+ Example:
14
+ ./script/generate rude_q ProcessQueue
15
+
16
+ This will create a ProcessQueue model:
17
+ Model: app/models/process_queue.rb
18
+ Spec: spec/models/process_queue_spec.rb
19
+ Fixtures: spec/fixtures/process_queues.yml
20
+ Migration: db/migrate/XXX_add_process_queues.rb
21
+
22
+ Run migrations, and you can use it immediately;
23
+ ProcessQueue.set(queue_name, value)
24
+ ProcessQueue.get(queue_name)
@@ -0,0 +1,27 @@
1
+ class RudeQGenerator < Rails::Generator::NamedBase
2
+ def manifest
3
+
4
+ record do |m|
5
+ # Check for class naming collisions.
6
+ m.class_collisions class_path, class_name
7
+
8
+ # Model, spec, and fixture directories.
9
+ m.directory File.join('app/models', class_path)
10
+ m.directory File.join('spec/fixtures', class_path)
11
+ m.directory File.join('spec/models', class_path)
12
+
13
+ # Model class, spec and fixtures.
14
+ m.template 'rude_q_model.rb', File.join('app/models', class_path, "#{file_name}.rb")
15
+ m.template 'model:fixtures.yml', File.join('spec/fixtures', class_path, "#{table_name}.yml")
16
+ m.template 'rude_q_model_spec.rb', File.join('spec/models', class_path, "#{file_name}_spec.rb")
17
+
18
+ unless options[:skip_migration]
19
+ m.migration_template 'rude_q_migration.rb', 'db/migrate', :assigns => {
20
+ :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
21
+ }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
22
+ end
23
+
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,18 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= table_name %> do |t|
4
+ t.string :queue_name
5
+ t.text :data
6
+ t.boolean :processed, :default => false, :null => false
7
+ <% unless options[:skip_timestamps] %>
8
+ t.timestamps
9
+ <% end -%>
10
+ end
11
+ add_index :<%= table_name %>, :processed
12
+ add_index :<%= table_name %>, [:queue_name, :processed]
13
+ end
14
+
15
+ def self.down
16
+ drop_table :<%= table_name %>
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ class <%= class_name %> < ActiveRecord::Base
2
+ include RudeQ
3
+ end
@@ -0,0 +1,71 @@
1
+ require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper'
2
+
3
+ describe <%= class_name %> do
4
+ before(:each) do
5
+ @<%= file_name %> = <%= class_name %>.new
6
+ end
7
+
8
+ it "should be valid" do
9
+ @<%= file_name %>.should be_valid
10
+ end
11
+
12
+ describe "get and set" do
13
+ it "should work with strings" do
14
+ <%= class_name %>.set('abcde', "Something to set")
15
+ <%= class_name %>.get('abcde').should == "Something to set"
16
+ end
17
+ it "should work with symbols" do
18
+ <%= class_name %>.set('abcde', :a_symbol)
19
+ <%= class_name %>.get('abcde').should == :a_symbol
20
+ end
21
+ it "should work with arrays" do
22
+ array = [1, :b, "C"]
23
+ <%= class_name %>.set('abcde', array)
24
+ <%= class_name %>.get('abcde').should == array
25
+ end
26
+ it "should work with hashes" do
27
+ hash = {:symbol => "A string", "stringy" => 23, 74 => :cheese}
28
+ <%= class_name %>.set('abcde', hash)
29
+ <%= class_name %>.get('abcde').should == hash
30
+ end
31
+
32
+ it "should :get in the same order they are :set" do
33
+ <%= class_name %>.set('abcde', :first)
34
+ <%= class_name %>.set('abcde', "second")
35
+
36
+ <%= class_name %>.get('abcde').should == :first
37
+
38
+ <%= class_name %>.set('abcde', 33.3333)
39
+
40
+ <%= class_name %>.get('abcde').should == "second"
41
+ <%= class_name %>.get('abcde').should == 33.3333
42
+ <%= class_name %>.get('abcde').should be(nil)
43
+ end
44
+
45
+ it "should keep queues seperated" do
46
+ <%= class_name %>.set('queue_1', :data_1)
47
+ <%= class_name %>.set('queue_2', "DATA2")
48
+
49
+ <%= class_name %>.get('queue_2').should == "DATA2"
50
+ <%= class_name %>.get('queue_2').should be(nil)
51
+ <%= class_name %>.get('queue_1').should == :data_1
52
+ <%= class_name %>.get('queue_1').should be(nil)
53
+ end
54
+
55
+ it "should work with queue name as strings or symbols" do
56
+ <%= class_name %>.set(:bah, "something about bah")
57
+ <%= class_name %>.get("bah").should == "something about bah"
58
+
59
+ <%= class_name %>.set("girah", {:craziness => "embodied"})
60
+ <%= class_name %>.get(:girah).should == {:craziness => "embodied"}
61
+ end
62
+
63
+ it "should work with queue name as strings or integers" do
64
+ <%= class_name %>.set(23, "something about bah")
65
+ <%= class_name %>.get("23").should == "something about bah"
66
+
67
+ <%= class_name %>.set("34", {:craziness => "embodied"})
68
+ <%= class_name %>.get(34).should == {:craziness => "embodied"}
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,4 @@
1
1
  # RudeQ
2
- require 'digest/sha1'
3
2
 
4
3
  # simply doing;
5
4
  # class RudeQueue < ActiveRecord::Base
@@ -12,9 +11,18 @@ module RudeQ
12
11
 
13
12
  def self.included(mod) # :nodoc:
14
13
  mod.extend(ClassMethods)
15
- mod.serialize(:data)
14
+ mod.send(:include, InstanceMethods)
16
15
  end
17
-
16
+
17
+ module InstanceMethods
18
+ def data # :nodoc:
19
+ YAML.load(self[:data])
20
+ end
21
+ def data=(value) # :nodoc:
22
+ self[:data] = YAML.dump(value)
23
+ end
24
+ end
25
+
18
26
  module ClassMethods
19
27
  # Cleanup old processed items
20
28
  #
@@ -25,7 +33,6 @@ module RudeQ
25
33
  end
26
34
 
27
35
  # Add any serialize-able +data+ to the queue +queue_name+ (strings and symbols are treated the same)
28
- #
29
36
  # RudeQueue.set(:sausage_queue, Sausage.new(:sauce => "yummy"))
30
37
  # RudeQueue.set("sausage_queue", Sausage.new(:other => true))
31
38
  #
@@ -37,6 +44,7 @@ module RudeQ
37
44
  # -> nil
38
45
  def set(queue_name, data)
39
46
  queue_name = sanitize_queue_name(queue_name)
47
+
40
48
  self.create!(:queue_name => queue_name, :data => data)
41
49
  return nil # in line with Starling
42
50
  end
@@ -86,9 +94,20 @@ module RudeQ
86
94
  end
87
95
 
88
96
  # A snapshot count of unprocessed items for the given +queue_name+
89
- def backlog(queue_name)
90
- qname = sanitize_queue_name(queue_name)
91
- self.count(:conditions => {:queue_name => qname, :processed => false})
97
+ #
98
+ # >> RudeQueue.backlog
99
+ # -> 265
100
+ # >> RudeQueue.backlog(:one_queue)
101
+ # -> 212
102
+ # >> RudeQueue.backlog(:another_queue)
103
+ # -> 53
104
+ #
105
+ def backlog(queue_name=nil)
106
+ conditions = {:processed => false}
107
+ if queue_name
108
+ conditions[:queue_name] = sanitize_queue_name(queue_name)
109
+ end
110
+ self.count(:conditions => conditions)
92
111
  end
93
112
 
94
113
  def fetch_with_lock(qname, &block) # :nodoc:
@@ -126,6 +145,12 @@ module RudeQ
126
145
  @queue_options ||= {:processed => :set_flag, :lock => :pessimistic}
127
146
  end
128
147
 
148
+ def data # :nodoc:
149
+ YAML.load(self[:data])
150
+ end
151
+ def data=(value) # :nodoc:
152
+ self[:data] = YAML.dump(value)
153
+ end
129
154
  private
130
155
 
131
156
  def sanitize_queue_name(queue_name) # :nodoc:
@@ -161,9 +186,12 @@ module RudeQ
161
186
  # which misses the point
162
187
  #
163
188
  # also, it doesn't work on SQLite as it requires "UPDATE ... LIMIT 1 ORDER id ASC"
189
+ # and as of RudeQueue2, you'll need to manually add the "token" column
164
190
  module TokenLock
165
191
  class << self
166
192
 
193
+ require 'digest/sha1'
194
+
167
195
  def fetch_with_lock(klass, qname) # :nodoc:
168
196
  token = get_unique_token
169
197
  klass.update_all(["token = ?", token], ["queue_name = ? AND processed = ? AND token IS NULL", qname, false], :limit => 1, :order => "id ASC")
@@ -188,5 +216,5 @@ module RudeQ
188
216
  end
189
217
  end
190
218
  end
191
-
192
219
  end
220
+
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/../rude_q"
2
+
3
+ module RudeQ
4
+ class Scope
5
+
6
+ def initialize(queue_name)
7
+ @queue_name = queue_name
8
+ end
9
+ attr_reader :queue_name
10
+
11
+ def set(data)
12
+ RudeQueue.set(self.queue_name, data)
13
+ end
14
+
15
+ def get()
16
+ RudeQueue.get(self.queue_name)
17
+ end
18
+
19
+ def backlog()
20
+ RudeQueue.backlog(self.queue_name)
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,66 @@
1
+ # example worker class: lib/my_worker.rb
2
+ # class MyWorker < RudeQ::Worker
3
+ # def queue_name
4
+ # :my_queue
5
+ # end
6
+ #
7
+ # def do_work(data)
8
+ # MyMailer.send(data)
9
+ # end
10
+ # end
11
+ #
12
+ # example rake file: lib/tasks/worker.rake
13
+ # namespace :worker do
14
+ # desc "fire off a worker"
15
+ # task :do => :environment do
16
+ # worker = MyWorker.new
17
+ # worker.do!
18
+ # end
19
+ # end
20
+ #
21
+ # then add a cron job to run "cd /path/to/wherever && rake worker:do RAILS_ENV=production"
22
+ module RudeQ
23
+ class Worker
24
+
25
+ def queue_name
26
+ raise NotImplementedError
27
+ end
28
+
29
+ def do_work(data)
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def do!
34
+ logger.info("starting up")
35
+ if work = self.queue.get
36
+ logger.info("found some work")
37
+ do_work(work)
38
+ else
39
+ logger.info("couldn't find any work")
40
+ end
41
+ logger.info("finished for now")
42
+ end
43
+
44
+ def logger
45
+ unless @logger
46
+ @logger = Logger.new(RAILS_ROOT + "/log/#{self.class.to_s.underscore}_#{RAILS_ENV}.log")
47
+ class << @logger
48
+ def format_message(severity, timestamp, progname, msg)
49
+ "#{timestamp.strftime('%Y%m%d-%H:%M:%S')} (#{$$}) #{msg}\n"
50
+ end
51
+ end
52
+ end
53
+ return @logger
54
+ end
55
+
56
+ class << self
57
+ def queue
58
+ RudeQ::Scope.new(self.new.queue_name)
59
+ end
60
+ end
61
+
62
+ def queue
63
+ @queue ||= self.class.queue
64
+ end
65
+ end
66
+ end
@@ -1,4 +1,4 @@
1
- class ProcessQueue < ActiveRecord::Base
1
+ class RudeQueue < ActiveRecord::Base
2
2
  include RudeQ
3
3
 
4
4
  class << self
@@ -10,4 +10,5 @@ class ProcessQueue < ActiveRecord::Base
10
10
  attr_accessor :raise_on_processed
11
11
  end
12
12
 
13
- end
13
+ end
14
+
@@ -0,0 +1,3 @@
1
+ class Something < ActiveRecord::Base
2
+ end
3
+
@@ -1,111 +1,117 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
- describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
3
+ describe RudeQ::ClassMethods do # RudeQueue extends ClassMethods
4
4
  before(:each) do
5
- ProcessQueue.delete_all
6
- ProcessQueue.raise_on_processed = false
5
+ RudeQueue.delete_all
6
+ RudeQueue.raise_on_processed = false
7
7
  create_some_noise
8
8
  end
9
9
 
10
10
  def create_some_noise
11
- ProcessQueue.create!(:queue_name => "doNT use this in Specs", :data => {:not => "to be messed with"})
12
- ProcessQueue.create!(:queue_name => "abcde", :data => {:same_as => "the specs but already processed"}, :processed => true)
11
+ RudeQueue.create!(:queue_name => "doNT use this in Specs", :data => {:not => "to be messed with"})
12
+ RudeQueue.create!(:queue_name => "abcde", :data => {:same_as => "the specs but already processed"}, :processed => true)
13
13
  end
14
14
 
15
15
  describe "get and set" do
16
16
  it "should work with strings" do
17
- ProcessQueue.set('abcde', "Something to set")
18
- ProcessQueue.get('abcde').should == "Something to set"
17
+ RudeQueue.set('abcde', "Something to set")
18
+ RudeQueue.get('abcde').should == "Something to set"
19
19
  end
20
20
  it "should work with symbols" do
21
- ProcessQueue.set('abcde', :a_symbol)
22
- ProcessQueue.get('abcde').should == :a_symbol
21
+ RudeQueue.set('abcde', :a_symbol)
22
+ RudeQueue.get('abcde').should == :a_symbol
23
23
  end
24
24
  it "should work with arrays" do
25
25
  array = [1, :b, "C"]
26
- ProcessQueue.set('abcde', array)
27
- ProcessQueue.get('abcde').should == array
26
+ RudeQueue.set('abcde', array)
27
+ RudeQueue.get('abcde').should == array
28
28
  end
29
29
  it "should work with hashes" do
30
30
  hash = {:symbol => "A string", "stringy" => 23, 74 => :cheese}
31
- ProcessQueue.set('abcde', hash)
32
- ProcessQueue.get('abcde').should == hash
31
+ RudeQueue.set('abcde', hash)
32
+ RudeQueue.get('abcde').should == hash
33
33
  end
34
34
  it "should work with integers" do
35
- ProcessQueue.set('abcde', 7816327370)
36
- ProcessQueue.get('abcde').should == 7816327370
35
+ RudeQueue.set('abcde', 7816327370)
36
+ RudeQueue.get('abcde').should == 7816327370
37
37
  end
38
- it "unfortunately doesnt resolve booleans correctly" do
39
- ProcessQueue.set('abcde', true)
40
- ProcessQueue.get('abcde').should == 1
38
+ it "should work with ActiveRecords" do
39
+ record = Something.create!(:name => "MatthewRudy")
40
+
41
+ RudeQueue.set('abcde', record)
42
+ RudeQueue.get('abcde').should == record
43
+ end
44
+ it "should resolve booleans correctly" do
45
+ RudeQueue.set('abcde', true)
46
+ RudeQueue.get('abcde').should == true
41
47
 
42
- ProcessQueue.set('abcde', false)
43
- ProcessQueue.get('abcde').should == 0
48
+ RudeQueue.set('abcde', false)
49
+ RudeQueue.get('abcde').should == false
44
50
  end
45
51
 
46
52
  it "should :get in the same order they are :set" do
47
- ProcessQueue.set('abcde', :first)
48
- ProcessQueue.set('abcde', "second")
53
+ RudeQueue.set('abcde', :first)
54
+ RudeQueue.set('abcde', "second")
49
55
 
50
- ProcessQueue.get('abcde').should == :first
56
+ RudeQueue.get('abcde').should == :first
51
57
 
52
- ProcessQueue.set('abcde', 33.3333)
58
+ RudeQueue.set('abcde', 33.3333)
53
59
 
54
- ProcessQueue.get('abcde').should == "second"
55
- ProcessQueue.get('abcde').should == 33.3333
56
- ProcessQueue.get('abcde').should be(nil)
60
+ RudeQueue.get('abcde').should == "second"
61
+ RudeQueue.get('abcde').should == 33.3333
62
+ RudeQueue.get('abcde').should be(nil)
57
63
  end
58
64
 
59
65
  it "should keep queues seperated" do
60
- ProcessQueue.set('queue_1', :data_1)
61
- ProcessQueue.set('queue_2', "DATA2")
66
+ RudeQueue.set('queue_1', :data_1)
67
+ RudeQueue.set('queue_2', "DATA2")
62
68
 
63
- ProcessQueue.get('queue_2').should == "DATA2"
64
- ProcessQueue.get('queue_2').should be(nil)
65
- ProcessQueue.get('queue_1').should == :data_1
66
- ProcessQueue.get('queue_1').should be(nil)
69
+ RudeQueue.get('queue_2').should == "DATA2"
70
+ RudeQueue.get('queue_2').should be(nil)
71
+ RudeQueue.get('queue_1').should == :data_1
72
+ RudeQueue.get('queue_1').should be(nil)
67
73
  end
68
74
 
69
75
  it "should call to_s on inputs" do
70
76
  qname = stub("fake input")
71
77
  qname.should_receive(:to_s).exactly(:twice).and_return("fake queue name")
72
78
 
73
- ProcessQueue.set(qname, ["Data"])
74
- ProcessQueue.get(qname).should == ["Data"]
79
+ RudeQueue.set(qname, ["Data"])
80
+ RudeQueue.get(qname).should == ["Data"]
75
81
  end
76
82
 
77
83
  it "should work with queue name as strings or symbols" do
78
- ProcessQueue.set(:bah, "something about bah")
79
- ProcessQueue.get("bah").should == "something about bah"
84
+ RudeQueue.set(:bah, "something about bah")
85
+ RudeQueue.get("bah").should == "something about bah"
80
86
 
81
- ProcessQueue.set("girah", {:craziness => "embodied"})
82
- ProcessQueue.get(:girah).should == {:craziness => "embodied"}
87
+ RudeQueue.set("girah", {:craziness => "embodied"})
88
+ RudeQueue.get(:girah).should == {:craziness => "embodied"}
83
89
  end
84
90
  end
85
91
 
86
92
  describe ".set" do
87
93
  it "should delegate to :create!" do
88
- ProcessQueue.should_receive(:create!).with(:queue_name => 'abcde', :data => :magical_planet)
89
- ProcessQueue.set('abcde', :magical_planet)
94
+ RudeQueue.should_receive(:create!).with(:queue_name => 'abcde', :data => :magical_planet)
95
+ RudeQueue.set('abcde', :magical_planet)
90
96
  end
91
97
  it "should return nil" do
92
- ProcessQueue.set('abcde', "something").should be(nil)
98
+ RudeQueue.set('abcde', "something").should be(nil)
93
99
  end
94
100
  end
95
101
 
96
102
  describe ".get" do
97
103
  it "should revert a record if something goes wrong before it finishes" do
98
- ProcessQueue.raise_on_processed = true
99
- ProcessQueue.set('abcde', :this_will_remain_unprocessed)
104
+ RudeQueue.raise_on_processed = true
105
+ RudeQueue.set('abcde', :this_will_remain_unprocessed)
100
106
 
101
107
  # confirm the object is in the db
102
- record = ProcessQueue.find(:first, :order => "id DESC")
108
+ record = RudeQueue.find(:first, :order => "id DESC")
103
109
  record.queue_name.should == 'abcde'
104
110
  record.data.should == :this_will_remain_unprocessed
105
111
  record.processed?.should == false
106
112
  record.token.should == nil
107
113
 
108
- lambda {ProcessQueue.get('abcde')}.should raise_error(RuntimeError)
114
+ lambda {RudeQueue.get('abcde')}.should raise_error(RuntimeError)
109
115
 
110
116
  record.reload
111
117
  record.queue_name.should == 'abcde'
@@ -119,11 +125,11 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
119
125
  describe "with data" do
120
126
 
121
127
  before(:each) do
122
- ProcessQueue.set(:fetch_queue, "some data")
128
+ RudeQueue.set(:fetch_queue, "some data")
123
129
  end
124
130
 
125
131
  it "should return the value of the block" do
126
- rtn = ProcessQueue.fetch(:fetch_queue) do |data|
132
+ rtn = RudeQueue.fetch(:fetch_queue) do |data|
127
133
  data.should == "some data"
128
134
  :the_return
129
135
  end
@@ -132,7 +138,7 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
132
138
 
133
139
  it "should execute the block with the data" do
134
140
  self.should_receive(:something)
135
- ProcessQueue.fetch(:fetch_queue) do |data|
141
+ RudeQueue.fetch(:fetch_queue) do |data|
136
142
  self.something
137
143
  data.should == "some data"
138
144
  end
@@ -144,13 +150,13 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
144
150
 
145
151
  it "should not execute the block" do
146
152
  self.should_not_receive(:something)
147
- ProcessQueue.fetch(:fetch_queue) do |data|
153
+ RudeQueue.fetch(:fetch_queue) do |data|
148
154
  raise(Exception, "this should never get here")
149
155
  end
150
156
  end
151
157
 
152
158
  it "should return nil" do
153
- rtn = ProcessQueue.fetch(:fetch_queue) do |data|
159
+ rtn = RudeQueue.fetch(:fetch_queue) do |data|
154
160
  raise(Exception, "again this shouldnt happen")
155
161
  end
156
162
  rtn.should be_nil
@@ -163,33 +169,33 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
163
169
  describe :processed do
164
170
  describe "set to :destroy" do
165
171
  before(:each) do
166
- @old_processed = ProcessQueue.queue_options[:processed]
167
- ProcessQueue.queue_options[:processed] = :destroy
172
+ @old_processed = RudeQueue.queue_options[:processed]
173
+ RudeQueue.queue_options[:processed] = :destroy
168
174
  end
169
175
  after(:each) do
170
- ProcessQueue.queue_options[:processed] = @old_processed
176
+ RudeQueue.queue_options[:processed] = @old_processed
171
177
  end
172
178
  it "should delete processed items" do
173
- count = ProcessQueue.count
179
+ count = RudeQueue.count
174
180
 
175
- ProcessQueue.set(:abcde, "some value")
176
- ProcessQueue.count.should == (count + 1)
181
+ RudeQueue.set(:abcde, "some value")
182
+ RudeQueue.count.should == (count + 1)
177
183
 
178
- ProcessQueue.get(:abcde).should == "some value"
179
- ProcessQueue.count.should == count
184
+ RudeQueue.get(:abcde).should == "some value"
185
+ RudeQueue.count.should == count
180
186
  end
181
187
  end
182
188
  describe "set to something crazy" do
183
189
  before(:each) do
184
- @old_processed = ProcessQueue.queue_options[:processed]
185
- ProcessQueue.queue_options[:processed] = :something_crazy
190
+ @old_processed = RudeQueue.queue_options[:processed]
191
+ RudeQueue.queue_options[:processed] = :something_crazy
186
192
  end
187
193
  after(:each) do
188
- ProcessQueue.queue_options[:processed] = @old_processed
194
+ RudeQueue.queue_options[:processed] = @old_processed
189
195
  end
190
196
  it "should raise an exception" do
191
- ProcessQueue.set(:abcde, "some value")
192
- lambda {ProcessQueue.get(:abcde)}.should raise_error(ArgumentError)
197
+ RudeQueue.set(:abcde, "some value")
198
+ lambda {RudeQueue.get(:abcde)}.should raise_error(ArgumentError)
193
199
  end
194
200
  end
195
201
  end
@@ -197,66 +203,72 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
197
203
 
198
204
  describe ".backlog" do
199
205
  it "should count the unprocessed items for the provided queue_name" do
200
- ProcessQueue.backlog(:abcde).should == 0
201
-
202
- ProcessQueue.set(:abcde, "a value")
203
- ProcessQueue.backlog(:abcde).should == 1
204
-
205
- ProcessQueue.set(:something_else, "another value")
206
- 3.times { ProcessQueue.set(:abcde, :add_three_more)}
207
-
208
- ProcessQueue.backlog(:abcde).should == 4
206
+ RudeQueue.delete_all
207
+
208
+ RudeQueue.backlog(:abcde).should == 0
209
+ RudeQueue.backlog().should == 0
210
+
211
+ RudeQueue.set(:abcde, "a value")
212
+ RudeQueue.backlog(:abcde).should == 1
213
+ RudeQueue.backlog().should == 1
214
+
215
+ RudeQueue.set(:something_else, "another value")
216
+ 3.times { RudeQueue.set(:abcde, :add_three_more)}
209
217
 
210
- ProcessQueue.get(:abcde).should == "a value"
211
- ProcessQueue.backlog(:abcde).should == 3
218
+ RudeQueue.backlog(:abcde).should == 4
219
+ RudeQueue.backlog().should == 5
220
+
221
+ RudeQueue.get(:abcde).should == "a value"
222
+ RudeQueue.backlog(:abcde).should == 3
223
+ RudeQueue.backlog().should == 4
212
224
  end
213
225
  end
214
226
 
215
227
  describe ".cleanup!" do
216
228
  it "should use :delete_all" do
217
- ProcessQueue.should_receive(:delete_all) # not :destroy_all
218
- ProcessQueue.cleanup!
229
+ RudeQueue.should_receive(:delete_all) # not :destroy_all
230
+ RudeQueue.cleanup!
219
231
  end
220
232
 
221
233
  it "should allow string inputs" do
222
- ProcessQueue.cleanup!("3600")
234
+ RudeQueue.cleanup!("3600")
223
235
  end
224
236
 
225
237
  it "should allow integer inputs" do
226
- ProcessQueue.cleanup!(3600)
238
+ RudeQueue.cleanup!(3600)
227
239
  end
228
240
 
229
241
  it "should not clear unprocessed items" do
230
- ProcessQueue.set('abcde', :giraffe)
231
- ProcessQueue.set('abcde', :monkey)
232
- ProcessQueue.count.should >= 2
242
+ RudeQueue.set('abcde', :giraffe)
243
+ RudeQueue.set('abcde', :monkey)
244
+ RudeQueue.count.should >= 2
233
245
 
234
- ProcessQueue.cleanup!
246
+ RudeQueue.cleanup!
235
247
 
236
- ProcessQueue.count.should >=2
237
- ProcessQueue.get('abcde').should == :giraffe
248
+ RudeQueue.count.should >=2
249
+ RudeQueue.get('abcde').should == :giraffe
238
250
  end
239
251
 
240
252
  it "should not clear old unprocessed items" do
241
- ProcessQueue.set('abcde', :giraffe)
242
- giraffe = ProcessQueue.find(:first, :conditions => {:data => :giraffe})
253
+ RudeQueue.set('abcde', :giraffe)
254
+ giraffe = RudeQueue.find(:first, :conditions => {:data => :giraffe})
243
255
 
244
256
  time_now = Time.now
245
257
  Time.stub!(:now).and_return(time_now + 1.year)
246
258
 
247
259
  giraffe.updated_at.should < 2.weeks.ago
248
260
 
249
- ProcessQueue.cleanup!
261
+ RudeQueue.cleanup!
250
262
 
251
263
  giraffe.reload
252
- ProcessQueue.get('abcde').should == :giraffe
264
+ RudeQueue.get('abcde').should == :giraffe
253
265
  end
254
266
 
255
267
  it "should not clear processed items newer than the argument" do
256
- ProcessQueue.set('abcde', :giraffe)
257
- ProcessQueue.get('abcde').should == :giraffe
268
+ RudeQueue.set('abcde', :giraffe)
269
+ RudeQueue.get('abcde').should == :giraffe
258
270
 
259
- giraffe = ProcessQueue.find(:first, :conditions => {:data => :giraffe})
271
+ giraffe = RudeQueue.find(:first, :conditions => {:data => :giraffe})
260
272
 
261
273
  time_now = Time.now
262
274
  Time.stub!(:now).and_return(time_now + 1.week - 5.minutes)
@@ -264,16 +276,16 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
264
276
  giraffe.updated_at.should > 1.week.ago
265
277
  giraffe.processed.should be(true)
266
278
 
267
- ProcessQueue.cleanup!(1.week)
279
+ RudeQueue.cleanup!(1.week)
268
280
 
269
281
  giraffe.reload
270
282
  end
271
283
 
272
284
  it "should not clear processed items newer than one hour, by default" do
273
- ProcessQueue.set('abcde', :giraffe)
274
- ProcessQueue.get('abcde').should == :giraffe
285
+ RudeQueue.set('abcde', :giraffe)
286
+ RudeQueue.get('abcde').should == :giraffe
275
287
 
276
- giraffe = ProcessQueue.find(:first, :conditions => {:data => :giraffe})
288
+ giraffe = RudeQueue.find(:first, :conditions => {:data => :giraffe})
277
289
 
278
290
  time_now = Time.now
279
291
  Time.stub!(:now).and_return(time_now + 59.minutes)
@@ -281,16 +293,16 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
281
293
  giraffe.updated_at.should > 1.hour.ago
282
294
  giraffe.processed.should be(true)
283
295
 
284
- ProcessQueue.cleanup!()
296
+ RudeQueue.cleanup!()
285
297
 
286
298
  giraffe.reload
287
299
  end
288
300
 
289
301
  it "should clear processed items older than the argument" do
290
- ProcessQueue.set('abcde', :giraffe)
291
- ProcessQueue.get('abcde').should == :giraffe
302
+ RudeQueue.set('abcde', :giraffe)
303
+ RudeQueue.get('abcde').should == :giraffe
292
304
 
293
- giraffe = ProcessQueue.find(:first, :conditions => {:data => :giraffe})
305
+ giraffe = RudeQueue.find(:first, :conditions => {:data => :giraffe})
294
306
 
295
307
  time_now = Time.now
296
308
  Time.stub!(:now).and_return(time_now + 1.week + 5.minutes)
@@ -298,16 +310,16 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
298
310
  giraffe.updated_at.should < 1.week.ago
299
311
  giraffe.processed.should be(true)
300
312
 
301
- ProcessQueue.cleanup!(1.week)
313
+ RudeQueue.cleanup!(1.week)
302
314
 
303
315
  lambda { giraffe.reload }.should raise_error(ActiveRecord::RecordNotFound)
304
316
  end
305
317
 
306
318
  it "should clear processed items older than one hour, by default" do
307
- ProcessQueue.set('abcde', :giraffe)
308
- ProcessQueue.get('abcde').should == :giraffe
319
+ RudeQueue.set('abcde', :giraffe)
320
+ RudeQueue.get('abcde').should == :giraffe
309
321
 
310
- giraffe = ProcessQueue.find(:first, :conditions => {:data => :giraffe})
322
+ giraffe = RudeQueue.find(:first, :conditions => {:data => :giraffe})
311
323
 
312
324
  time_now = Time.now()
313
325
  Time.stub!(:now).and_return(time_now + 61.minutes)
@@ -315,7 +327,7 @@ describe RudeQ::ClassMethods do # ProcessQueue extends ClassMethods
315
327
  giraffe.updated_at.should < 1.hour.ago
316
328
  giraffe.processed.should be(true)
317
329
 
318
- ProcessQueue.cleanup!
330
+ RudeQueue.cleanup!
319
331
 
320
332
  lambda { giraffe.reload }.should raise_error(ActiveRecord::RecordNotFound)
321
333
  end
@@ -348,13 +360,13 @@ describe RudeQ::TokenLock do
348
360
  # RudeQ::TokenLock.should respond_to(:get_unique_token) # ensure our stub is safe
349
361
  # RudeQ::TokenLock.should_receive(:get_unique_token).exactly(3).times.and_return(@token)
350
362
  #
351
- # @existing = ProcessQueue.create!(:queue_name => 'abcde', :data => :old_data, :token => @token, :processed => true)
363
+ # @existing = RudeQueue.create!(:queue_name => 'abcde', :data => :old_data, :token => @token, :processed => true)
352
364
  #
353
- # ProcessQueue.get('abcde').should be(nil)
365
+ # RudeQueue.get('abcde').should be(nil)
354
366
  #
355
- # ProcessQueue.set('abcde', :new_data)
356
- # ProcessQueue.get('abcde').should == :new_data
357
- # ProcessQueue.get('abcde').should be(nil)
367
+ # RudeQueue.set('abcde', :new_data)
368
+ # RudeQueue.get('abcde').should == :new_data
369
+ # RudeQueue.get('abcde').should be(nil)
358
370
  # end
359
371
 
360
372
  end
@@ -1,5 +1,5 @@
1
1
  ActiveRecord::Schema.define(:version => 1) do
2
- create_table :process_queues, :force => true do |t|
2
+ create_table :rude_queues, :force => true do |t|
3
3
  t.string :queue_name
4
4
  t.text :data
5
5
  t.string :token, :default => nil
@@ -7,6 +7,13 @@ ActiveRecord::Schema.define(:version => 1) do
7
7
 
8
8
  t.timestamps
9
9
  end
10
- add_index :process_queues, :processed
11
- add_index :process_queues, [:queue_name, :processed]
12
- end
10
+ add_index :rude_queues, :processed
11
+ add_index :rude_queues, [:queue_name, :processed]
12
+
13
+ create_table :somethings, :force => true do |t|
14
+ t.string :name
15
+ t.integer :count
16
+
17
+ t.timestamps
18
+ end
19
+ end
@@ -4,9 +4,11 @@ require 'active_record'
4
4
 
5
5
  current_dir = File.dirname(__FILE__)
6
6
  require "#{current_dir}/../lib/rude_q"
7
- require "#{current_dir}/process_queue"
8
-
7
+ require "#{current_dir}/../lib/rude_q/worker"
8
+ require "#{current_dir}/../lib/rude_q/scope"
9
+ require "#{current_dir}/models/rude_queue"
10
+ require "#{current_dir}/models/something"
9
11
  config = YAML::load(IO.read(current_dir + '/database.yml'))
10
12
  ActiveRecord::Base.logger = Logger.new(current_dir + "/debug.log")
11
13
  ActiveRecord::Base.establish_connection(config['rude_q_test'])
12
- load(current_dir + "/schema.rb")
14
+ load(current_dir + "/schema.rb")
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class ExampleWorker < RudeQ::Worker
4
+ def queue_name
5
+ :some_queue
6
+ end
7
+
8
+ # for the test, we'll just append each bit of data to a variable
9
+ attr_accessor :processed_data
10
+
11
+ def do_work(data)
12
+ self.processed_data ||= []
13
+ self.processed_data << data
14
+ end
15
+ end
16
+
17
+ describe RudeQ::Worker do
18
+ before(:each) do
19
+ @it = ExampleWorker.new
20
+ RudeQueue.delete_all
21
+ end
22
+
23
+ describe "queue" do
24
+ it "should expose RudeQueue.get scoped for the worker's queue" do
25
+ RudeQueue.set(:some_queue, ["some data for the worker"])
26
+ @it.queue.get.should == ["some data for the worker"]
27
+ end
28
+
29
+ it "should expose RudeQueue.set scoped for the worker's queue" do
30
+ @it.queue.set(:some_other_data_for_the_worker)
31
+ RudeQueue.get(:some_queue).should == :some_other_data_for_the_worker
32
+ end
33
+
34
+ it "should expose RudeQueue.backlog scoped for the worker's queue" do
35
+ RudeQueue.set(:who_knows, 1)
36
+ RudeQueue.set(:my_mum, 23)
37
+
38
+ RudeQueue.backlog.should == 2
39
+ RudeQueue.backlog(:some_queue).should == 0
40
+ @it.queue.backlog.should == 0
41
+
42
+ RudeQueue.set(:some_queue, "purple")
43
+
44
+ RudeQueue.backlog.should == 3
45
+ RudeQueue.backlog(:some_queue).should == 1
46
+ @it.queue.backlog.should == 1
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,25 @@
1
+ namespace :queue do
2
+ desc "Generates your RudeQueue model"
3
+ task :setup => :environment do
4
+ require 'rails_generator'
5
+ require 'rails_generator/scripts/generate'
6
+ Rails::Generator::Scripts::Generate.new.run(["rude_q", ENV["QUEUE"] || "RudeQueue"])
7
+ end
8
+
9
+ desc "Removes all the old queue items"
10
+ task :cleanup => :environment do
11
+ queue_model = (ENV["QUEUE"] || "RudeQueue").constantize
12
+ args = [ENV["CLEANUP_TIME"]].compact
13
+ queue_model.cleanup!(*args) # no arg if no CLEANUP_TIME specified
14
+ end
15
+ end
16
+
17
+ #namespace :spec do
18
+ # namespace :plugins do
19
+ # desc "Runs the examples for RudeQ"
20
+ # Spec::Rake::SpecTask.new(:rude_q) do |t|
21
+ # t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
22
+ # t.spec_files = FileList['vendor/plugins/rude_q/spec/**/*_spec.rb']
23
+ # end
24
+ # end
25
+ #end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matthewrudy-rudeq
3
3
  version: !ruby/object:Gem::Version
4
- version: "2.0"
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Rudy Jacobs
@@ -9,11 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-12 00:00:00 -08:00
12
+ date: 2009-06-09 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -32,13 +33,24 @@ extra_rdoc_files:
32
33
  files:
33
34
  - README
34
35
  - Rakefile
36
+ - MIT-LICENSE
37
+ - lib/rude_q/worker.rb
38
+ - lib/rude_q/scope.rb
35
39
  - lib/rude_q.rb
40
+ - generators/rude_q/templates/rude_q_model.rb
41
+ - generators/rude_q/templates/rude_q_model_spec.rb
42
+ - generators/rude_q/templates/rude_q_migration.rb
43
+ - generators/rude_q/rude_q_generator.rb
44
+ - generators/rude_q/USAGE
45
+ - spec/spec.opts
46
+ - spec/worker_spec.rb
47
+ - spec/spec_helper.rb
36
48
  - spec/database.yml
37
- - spec/process_queue.rb
38
49
  - spec/rude_q_spec.rb
50
+ - spec/models/rude_queue.rb
51
+ - spec/models/something.rb
39
52
  - spec/schema.rb
40
- - spec/spec.opts
41
- - spec/spec_helper.rb
53
+ - tasks/rude_q_tasks.rake
42
54
  has_rdoc: true
43
55
  homepage: http://github.com/matthewrudy/rudeq
44
56
  post_install_message:
@@ -68,3 +80,4 @@ specification_version: 2
68
80
  summary: ActiveRecord-based DB-queue
69
81
  test_files:
70
82
  - spec/rude_q_spec.rb
83
+ - spec/worker_spec.rb