myobie-merb_queue 0.0.1

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Nathan Herald
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,47 @@
1
+ merb_queue
2
+ ==========
3
+
4
+ <http://github.com/myobie/merb_queue>
5
+
6
+ Description
7
+ -----------
8
+
9
+ A persistent queue used to perform repetitive actions with many merb processes across many servers if needed.
10
+
11
+ Requirements
12
+ ------------
13
+
14
+ * merb-core
15
+ * sequel-core (if using db persistence)
16
+ * fiveruns-memcache-client (if using memcache persistence)
17
+
18
+ Install
19
+ -------
20
+
21
+ gem install myobie-merb_queue -s http://gems.github.com
22
+
23
+ License
24
+ -------
25
+
26
+ (The MIT License)
27
+
28
+ Copyright (c) 2008 Nathan Herald
29
+
30
+ Permission is hereby granted, free of charge, to any person obtaining
31
+ a copy of this software and associated documentation files (the
32
+ 'Software'), to deal in the Software without restriction, including
33
+ without limitation the rights to use, copy, modify, merge, publish,
34
+ distribute, sublicense, and/or sell copies of the Software, and to
35
+ permit persons to whom the Software is furnished to do so, subject to
36
+ the following conditions:
37
+
38
+ The above copyright notice and this permission notice shall be
39
+ included in all copies or substantial portions of the Software.
40
+
41
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
42
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
43
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
44
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
45
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
46
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
47
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+ require "spec/rake/spectask"
6
+
7
+ PLUGIN = "merb_queue"
8
+ NAME = "merb_queue"
9
+ GEM_VERSION = "0.0.1"
10
+ AUTHOR = "Nathan Herald"
11
+ EMAIL = "nathan@myobie.com"
12
+ HOMEPAGE = "http://github.com/myobie/merb_queue"
13
+ SUMMARY = "A persistent queue across multiple merb processes"
14
+
15
+ spec = Gem::Specification.new do |s|
16
+ s.name = NAME
17
+ s.version = GEM_VERSION
18
+ s.platform = Gem::Platform::RUBY
19
+ s.has_rdoc = true
20
+ s.extra_rdoc_files = ["README.markdown", "LICENSE", 'TODO']
21
+ s.summary = SUMMARY
22
+ s.description = s.summary
23
+ s.author = AUTHOR
24
+ s.email = EMAIL
25
+ s.homepage = HOMEPAGE
26
+ s.add_dependency('merb-core', '>= 0.9.3')
27
+ s.require_path = 'lib'
28
+ s.autorequire = PLUGIN
29
+ s.files = %w(LICENSE README.markdown Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
30
+ end
31
+
32
+ Rake::GemPackageTask.new(spec) do |pkg|
33
+ pkg.gem_spec = spec
34
+ end
35
+
36
+ desc "install the plugin locally"
37
+ task :install => [:package] do
38
+ sh %{sudo gem install pkg/#{NAME}-#{VERSION}}
39
+ end
40
+
41
+ desc "create a gemspec file"
42
+ task :make_spec do
43
+ File.open("#{NAME}.gemspec", "w") do |file|
44
+ file.puts spec.to_ruby
45
+ end
46
+ end
47
+
48
+ namespace :jruby do
49
+
50
+ desc "Run :package and install the resulting .gem with jruby"
51
+ task :install => :package do
52
+ sh %{#{SUDO} jruby -S gem install pkg/#{NAME}-#{Merb::VERSION}.gem --no-rdoc --no-ri}
53
+ end
54
+
55
+ end
56
+
57
+ desc "Run the specs"
58
+ Spec::Rake::SpecTask.new("specs") do |t|
59
+ t.spec_opts = ["--format", "specdoc", "--colour"]
60
+ t.spec_files = Dir["spec/**/*_spec.rb"].sort
61
+ end
data/TODO ADDED
@@ -0,0 +1,5 @@
1
+ - More specs!
2
+ - Make it actually persistent using sqlite3
3
+ - Use PStore for persistence
4
+ - Use memcache for persistence
5
+ - Use starling for persistence
@@ -0,0 +1,45 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'logger'
5
+ require 'merb-core'
6
+
7
+ module MerbQueueError
8
+ class QueueEmpty < StandardError; end
9
+ class WrongQueueDatatype < StandardError; end
10
+ end
11
+
12
+ require 'merb_queue/base'
13
+ require 'merb_queue/queue'
14
+
15
+ module MerbQueue
16
+
17
+ def self.[](what)
18
+ MerbQueue::Base[what]
19
+ end
20
+
21
+ def self.register(name, &block)
22
+ MerbQueue::Base.register(name, &block)
23
+ end
24
+
25
+ def self.add(name, &block)
26
+ MerbQueue::Base.add(name, &block)
27
+ end
28
+
29
+ def self.all
30
+ MerbQueue::Base.all
31
+ end
32
+
33
+ def self.logger
34
+ MerbQueue::Base.logger
35
+ end
36
+
37
+ def self.delete(what)
38
+ MerbQueue::Base.delete(what)
39
+ end
40
+
41
+ end
42
+
43
+ Merb::BootLoader.after_app_loads do
44
+ require Merb.root / "config" / "queues.rb" if File.exists?(Merb.root / "config" / "queues.rb")
45
+ end
@@ -0,0 +1,38 @@
1
+ module MerbQueue
2
+
3
+ class Base
4
+ @@queues = {}
5
+ @@logger = Logger.new(Merb.root / "log" / "queue.log", 5, 512000)
6
+
7
+ def self.logger
8
+ @@logger
9
+ end
10
+
11
+ def self.register(name, &block)
12
+ logger.info "Registering #{name}..."
13
+ a = MerbQueue.add(name, &block)
14
+ a.start
15
+ end
16
+
17
+ def self.add(name, &block)
18
+ logger.info "Adding #{name}..."
19
+ a = MerbQueue::Queue.new(name, &block)
20
+ @@queues[name] = a
21
+ a
22
+ end
23
+
24
+ def self.[](what)
25
+ @@queues[what]
26
+ end
27
+
28
+ def self.all
29
+ @@queues
30
+ end
31
+
32
+ def self.delete(what)
33
+ @@queues.delete(what)
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,130 @@
1
+ module MerbQueue
2
+
3
+ class Queue
4
+
5
+ attr_accessor :queue, :name, :running, :logger, :t, :wait_seconds, :max_attempts
6
+
7
+ def initialize(name, &block)
8
+ @queue = []
9
+ @running = false
10
+ @max_attempts = 3
11
+ @wait_seconds = 10
12
+ @name = name
13
+ @logger = MerbQueue::Base.logger
14
+ @work_to_be_done = block
15
+ end
16
+
17
+ def running?
18
+ @running
19
+ end
20
+
21
+ def queue
22
+ @queue
23
+ end
24
+
25
+ def length
26
+ queue.length
27
+ end
28
+
29
+ def working?
30
+ length > 0
31
+ end
32
+
33
+ def push(something)
34
+ self.queue = queue.push(something)
35
+ end
36
+
37
+ def unshift(something)
38
+ self.queue = queue.unshift(something)
39
+ end
40
+
41
+ def shift
42
+ queue.shift
43
+ end
44
+
45
+ def first
46
+ queue.first
47
+ end
48
+
49
+ alias :get :shift
50
+ alias :remove! :shift
51
+ alias :add :push
52
+ alias :amount :length
53
+ alias :size :length
54
+ alias :<< :push
55
+ alias :>> :unshift
56
+
57
+ def start!
58
+ unless running?
59
+ logger.info "Starting!!! #{name}..."
60
+
61
+ @t = Thread.new(name) do |my_name|
62
+ loop do
63
+ MerbQueue[my_name].next!
64
+ MerbQueue[my_name].working? ? sleep(0.25) : sleep(wait_seconds)
65
+ end
66
+ end
67
+ @t.priority = -9
68
+
69
+ @running = true
70
+ end
71
+ end#of start!
72
+
73
+ def start
74
+ unless running?
75
+ logger.info "Starting #{name}..."
76
+
77
+ @t = Thread.new(name) do |my_name|
78
+ loop do
79
+ MerbQueue[my_name].next
80
+ MerbQueue[my_name].working? ? sleep(0.25) : sleep(wait_seconds)
81
+ end
82
+ end
83
+ @t.priority = -9
84
+
85
+ @running = true
86
+ end
87
+ end#of start
88
+
89
+ def clear!
90
+ @queue = [] # TODO: this might should be a bit nicer?
91
+ end
92
+
93
+ def next
94
+ begin
95
+ self.next!
96
+ rescue MerbQueueError::QueueEmpty
97
+ rescue Exception => e
98
+ logger.error(e) # TODO: log this somewhere?
99
+ end
100
+ end#of next
101
+
102
+ def next!
103
+
104
+ current_work = self.get # pull an item off the top of the queue
105
+ max_tries = @max_attempts
106
+ raise MerbQueueError::QueueEmpty if current_work.nil?
107
+ raise MerbQueueError::WrongQueueDatatype unless current_work.is_a?(Hash)
108
+ current_work[:attempts] = current_work[:attempts] ? current_work[:attempts] + 1 : 1
109
+
110
+ begin
111
+ @work_to_be_done.call(current_work)
112
+ rescue Exception => e
113
+ if current_work[:attempts] >= max_tries
114
+ logger.error "#### This crap just doesn't work!"
115
+ logger.error current_work.to_yaml
116
+ # TODO: log this failure and all the errors somewhere?
117
+ else
118
+ current_work[:errors] = current_work[:errors] ? current_work[:errors] << e : current_work[:errors] = [e]
119
+ self << current_work # put it back so it can try again
120
+
121
+ logger.warn "There was an error, trying again."
122
+ logger.error e
123
+ end
124
+ end
125
+
126
+ end#of next!
127
+
128
+ end#of Queue class
129
+
130
+ end
@@ -0,0 +1,9 @@
1
+ module MerbQueue
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,97 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ # Time to add your specs!
4
+ # http://rspec.info/
5
+ describe MerbQueue do
6
+
7
+ describe "adding" do
8
+
9
+ before(:each) do
10
+ MerbQueue.delete(:test)
11
+ end
12
+
13
+ it "should let you add" do
14
+ MerbQueue.should respond_to(:add)
15
+ MerbQueue.add(:test) { |w| true }
16
+ MerbQueue[:test].should_not be_nil
17
+ end
18
+
19
+ it "should know how long the queue is" do
20
+ MerbQueue[:test].should be_nil # just to make sure the queue from before is now gone
21
+
22
+ MerbQueue::Queue.stubs(:next).returns(true)
23
+
24
+ MerbQueue.add(:test) { |w| true }
25
+ MerbQueue[:test].length.should == 0
26
+
27
+ MerbQueue[:test] << {}
28
+ MerbQueue[:test].length.should == 1
29
+ end
30
+
31
+ it "should report that it's not running" do
32
+ MerbQueue.add(:test) { |w| true }
33
+ MerbQueue[:test].should_not be_running
34
+ end
35
+ end
36
+
37
+ describe "registering" do
38
+
39
+ before(:each) do
40
+ MerbQueue.delete(:test)
41
+ end
42
+
43
+ it "should let you register" do
44
+ MerbQueue::Queue.stubs(:next).returns(true)
45
+
46
+ MerbQueue.should respond_to(:register)
47
+ MerbQueue.register(:test) { |w| true }
48
+ MerbQueue[:test].should_not be_nil
49
+ end
50
+
51
+ it "should start a queue that is registered" do
52
+ MerbQueue::Queue.expects(:start).returns(true)
53
+ MerbQueue.register(:test) { |w| true }
54
+ end
55
+
56
+ it "should know that it's running" do
57
+ MerbQueue::Queue.stubs(:next).returns(true)
58
+
59
+ MerbQueue.register(:test) { |w| true }
60
+ MerbQueue[:test].should be_running
61
+ end
62
+
63
+ end
64
+
65
+ describe "looping" do
66
+
67
+ before(:each) do
68
+ MerbQueue.delete(:test)
69
+ end
70
+
71
+ it "should be processing the queue every so often and in order" do
72
+ $counter = 1
73
+ MerbQueue.add(:test) { |w| $counter = w[:amount] }
74
+ MerbQueue[:test].wait_seconds = 0
75
+
76
+ MerbQueue[:test] << { :amount => 1 }
77
+ MerbQueue[:test] << { :amount => 2 }
78
+ MerbQueue[:test] << { :amount => 3 }
79
+ MerbQueue[:test] << { :amount => 4 }
80
+
81
+ MerbQueue[:test].start
82
+
83
+ sleep(1.25) # wait on the thread to process
84
+
85
+ MerbQueue[:test].should_not be_working
86
+ $counter.should == 4
87
+ end
88
+
89
+ it "should know how many items are left to go" do
90
+ MerbQueue.add(:test) { |w| true }
91
+ MerbQueue[:test] << {}
92
+ MerbQueue[:test] << {}
93
+ MerbQueue[:test].amount.should == 2
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,25 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $TESTING=true
10
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
11
+ require 'rubygems'
12
+ require 'mocha'
13
+ require "merb-core"
14
+ require 'merb_queue'
15
+
16
+ Merb.load_dependencies :environment => "test"
17
+
18
+ Spec::Runner.configure do |config|
19
+ # config.include(Merb::Test::ViewHelper)
20
+ config.include Merb::Test::RouteHelper
21
+ config.include Merb::Test::RequestHelper
22
+ config.include Merb::Test::ControllerHelper
23
+ end
24
+
25
+ Merb.load_dependencies(:environment => 'test')
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: myobie-merb_queue
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Herald
8
+ autorequire: merb_queue
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-25 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: merb-core
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.9.3
23
+ version:
24
+ description: A persistent queue across multiple merb processes
25
+ email: nathan@myobie.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - README.markdown
32
+ - LICENSE
33
+ - TODO
34
+ files:
35
+ - LICENSE
36
+ - README.markdown
37
+ - Rakefile
38
+ - TODO
39
+ - lib/merb_queue
40
+ - lib/merb_queue/base.rb
41
+ - lib/merb_queue/queue.rb
42
+ - lib/merb_queue/version.rb
43
+ - lib/merb_queue.rb
44
+ - spec/merb_queue_spec.rb
45
+ - spec/spec.opts
46
+ - spec/spec_helper.rb
47
+ has_rdoc: false
48
+ homepage: http://github.com/myobie/merb_queue
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.2.0
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: A persistent queue across multiple merb processes
73
+ test_files: []
74
+