bluth 0.5.3 → 0.6.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.
data/CHANGES.txt CHANGED
@@ -1,5 +1,18 @@
1
1
  BLUTH, CHANGES
2
2
 
3
+ #### 0.6.0 (2010-12-30) ###############################
4
+
5
+ * CHANGE: Now depends on Familia 0.6
6
+ * CHANGE: Worker process name now starts with 'bluth'
7
+ * CHANGE: Bluth.pop is now correctly named Bluth.shift (b/c it's returning
8
+ the first value in the lists)
9
+ * ADDED: Bluth::Handler
10
+
11
+
12
+ #### 0.5.3 (2010-12-17) ###############################
13
+
14
+ * CHANGE: requires Familia 0.5.3
15
+
3
16
  #### 0.5.2 (2010-12-10) ###############################
4
17
 
5
18
  Initial public release
data/Rakefile CHANGED
@@ -25,8 +25,9 @@ begin
25
25
  gem.email = "delano@solutious.com"
26
26
  gem.homepage = "http://github.com/delano/bluth"
27
27
  gem.authors = ["Delano Mandelbaum"]
28
- gem.add_dependency("familia", "= 0.5.3")
28
+ gem.add_dependency("familia", "= 0.6.3")
29
29
  gem.add_dependency('sysinfo', '>= 0.7.3')
30
+ gem.add_dependency('annoy')
30
31
 
31
32
  #gem.add_development_dependency("rspec", ">= 1.2.9")
32
33
  #gem.add_development_dependency("mocha", ">= 0.9.8")
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :MAJOR: 0
3
- :MINOR: 5
4
- :PATCH: 3
3
+ :MINOR: 6
4
+ :PATCH: 0
data/bin/bluth ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # = Bluth: the queuing system.
4
+ #
5
+ #
6
+ # Usage:
7
+ #
8
+ # $ bluth -h
9
+ # $ bluth -Ipath/2/inc -ryourlib start
10
+ # $ bluth -Ipath/2/inc -ryourlib stop
11
+ #
12
+ #--
13
+
14
+ # Put our local lib in first place
15
+ BASE_PATH = File.expand_path File.join(File.dirname(__FILE__), '..')
16
+ $:.unshift File.join(BASE_PATH, 'lib')
17
+
18
+ require 'bluth'
19
+ require 'bluth/cli'
20
+
21
+ autoload :Rye, 'rye'
22
+ autoload :Annoy, 'annoy'
23
+
24
+ # Command-line interface for bin/bluth
25
+ class Bluth::CLI::Definition
26
+ extend Drydock
27
+
28
+ debug :on
29
+
30
+ global :Y, :auto, "Auto confirm"
31
+ global :d, :database, Integer, "Redis database"
32
+ global :e, :environment, String
33
+ global :d, :daemon, "Start as a daemon"
34
+ global :D, :debug do
35
+ Familia.debug = true
36
+ end
37
+ global :U, :uri, String, "Redis connection URI" do |v|
38
+ uri = URI.parse v
39
+ Bluth.uri = uri
40
+ end
41
+ global :v, :verbose, "Increase output" do
42
+ @verbose ||= 0
43
+ @verbose += 1
44
+ end
45
+ global :I, String, "Add a load path" do |v|
46
+ $LOAD_PATH << v
47
+ end
48
+ global :r, String, "Require a library" do |v|
49
+ $LOAD_PATH << 'lib' if File.exists? 'lib'
50
+ begin
51
+ require v
52
+ rescue LoadError => ex
53
+ puts ex.message
54
+ exit
55
+ end
56
+ end
57
+ global :V, :version, "Display version" do
58
+ puts "Version: #{Bluth::VERSION.to_s}"
59
+ exit 0
60
+ end
61
+
62
+ before do |obj|
63
+ obj.global.environment ||= 'dev'
64
+ end
65
+
66
+ #TODO: command :enqueue
67
+
68
+ command :start_worker => Bluth::CLI
69
+ command :start_scheduler => Bluth::CLI
70
+
71
+ option :f, :force
72
+ command :stop_workers => Bluth::CLI
73
+ option :f, :force
74
+ command :stop_worker => Bluth::CLI
75
+ option :f, :force
76
+ command :stop_scheduler => Bluth::CLI
77
+
78
+ command :workers => Bluth::CLI
79
+ command :schedulers => Bluth::CLI
80
+
81
+ #command :flush_workers => Bluth::CLI
82
+ end
83
+
84
+ begin
85
+ Drydock.run!(ARGV, STDIN) if Drydock.run? && !Drydock.has_run?
86
+ rescue Drydock::ArgError, Drydock::OptError => ex
87
+ STDERR.puts ex.message
88
+ STDERR.puts ex.usage
89
+ rescue Drydock::InvalidArgument => ex
90
+ STDERR.puts ex.message
91
+ rescue Drydock::UnknownCommand => ex
92
+ STDERR.puts "Unknown command: %s" % ex.name
93
+ rescue Interrupt
94
+ puts $/, "Exiting..."
95
+ exit 1
96
+ rescue => ex
97
+ STDERR.puts "ERROR (#{ex.class.to_s}): #{ex.message}"
98
+ STDERR.puts ex.backtrace #if Familia.debug
99
+ end
data/bluth.gemspec CHANGED
@@ -5,13 +5,15 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bluth}
8
- s.version = "0.5.3"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Delano Mandelbaum"]
12
- s.date = %q{2010-12-17}
12
+ s.date = %q{2010-12-30}
13
+ s.default_executable = %q{bluth}
13
14
  s.description = %q{A Redis queuing system built on top of Familia}
14
15
  s.email = %q{delano@solutious.com}
16
+ s.executables = ["bluth"]
15
17
  s.extra_rdoc_files = [
16
18
  "LICENSE.txt",
17
19
  "README.rdoc"
@@ -22,11 +24,19 @@ Gem::Specification.new do |s|
22
24
  "README.rdoc",
23
25
  "Rakefile",
24
26
  "VERSION.yml",
27
+ "bin/bluth",
25
28
  "bluth.gemspec",
26
29
  "lib/bluth.rb",
30
+ "lib/bluth/cli.rb",
27
31
  "lib/bluth/gob.rb",
32
+ "lib/bluth/test_helpers.rb",
28
33
  "lib/bluth/worker.rb",
29
- "lib/daemonizing.rb"
34
+ "lib/daemonizing.rb",
35
+ "try/15_queue_try.rb",
36
+ "try/16_worker_try.rb",
37
+ "try/17_gob_try.rb",
38
+ "try/18_handler_try.rb",
39
+ "try/19_bluth_try.rb"
30
40
  ]
31
41
  s.homepage = %q{http://github.com/delano/bluth}
32
42
  s.rdoc_options = ["--charset=UTF-8"]
@@ -40,15 +50,18 @@ Gem::Specification.new do |s|
40
50
  s.specification_version = 3
41
51
 
42
52
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
- s.add_runtime_dependency(%q<familia>, ["= 0.5.3"])
53
+ s.add_runtime_dependency(%q<familia>, ["= 0.6.3"])
44
54
  s.add_runtime_dependency(%q<sysinfo>, [">= 0.7.3"])
55
+ s.add_runtime_dependency(%q<annoy>, [">= 0"])
45
56
  else
46
- s.add_dependency(%q<familia>, ["= 0.5.3"])
57
+ s.add_dependency(%q<familia>, ["= 0.6.3"])
47
58
  s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
59
+ s.add_dependency(%q<annoy>, [">= 0"])
48
60
  end
49
61
  else
50
- s.add_dependency(%q<familia>, ["= 0.5.3"])
62
+ s.add_dependency(%q<familia>, ["= 0.6.3"])
51
63
  s.add_dependency(%q<sysinfo>, [">= 0.7.3"])
64
+ s.add_dependency(%q<annoy>, [">= 0"])
52
65
  end
53
66
  end
54
67
 
data/lib/bluth/cli.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'drydock'
2
+
3
+ module Bluth
4
+ class CLI < Drydock::Command
5
+
6
+
7
+ def start_workers
8
+ start_worker
9
+ end
10
+
11
+ def start_scheduler
12
+ start_worker Bluth.scheduler
13
+ end
14
+
15
+ def stop_scheduler
16
+ stop_workers Bluth.scheduler
17
+ end
18
+
19
+ def schedulers
20
+ workers Bluth.scheduler
21
+ end
22
+
23
+ #def flush_workers
24
+ # if @global.auto || Annoy.are_you_sure?
25
+ # Bluth::Worker.prefix
26
+ # end
27
+ #end
28
+
29
+ def start_worker worker_class=Bluth::Worker
30
+ if @global.daemon
31
+ worker = worker_class.new
32
+ Familia.info "Created: #{worker.rediskey}"
33
+ worker.daemonize
34
+ worker.run
35
+ else
36
+ Bluth.poptimeout = 3.seconds
37
+ worker_class.run
38
+ end
39
+ end
40
+
41
+ def stop_workers worker_class=Bluth::Worker
42
+ worker_class.instances.each do |worker|
43
+ kill_worker worker, worker_class
44
+ end
45
+ end
46
+
47
+ def stop_worker wid=nil,worker_class=Bluth::Worker
48
+ wids = wid ? [wid] : @argv
49
+ wids.each do |wid|
50
+ worker = worker_class.from_redis wid
51
+ kill_worker worker, worker_class
52
+ end
53
+ end
54
+
55
+ def workers worker_class=Bluth::Worker
56
+ Familia.info worker_class.all.collect &:key
57
+ end
58
+
59
+ private
60
+
61
+ def kill_worker worker, worker_class=Bluth::Worker
62
+ if worker.nil?
63
+ Familia.info "No such worker"
64
+ exit 1
65
+ else
66
+ Familia.info "Killing #{worker.rediskey}"
67
+ worker.kill @global.auto
68
+ end
69
+ end
70
+
71
+ end
72
+ end
data/lib/bluth/gob.rb CHANGED
@@ -1,180 +1 @@
1
1
 
2
-
3
- module Bluth
4
-
5
- class Gob < Storable
6
- MAX_ATTEMPTS = 3.freeze unless defined?(Gob::MAX_ATTEMPTS)
7
- include Familia
8
- prefix :gob
9
- ttl 1.hour
10
- field :id => Gibbler::Digest
11
- field :kind => String
12
- field :data => Hash
13
- field :messages => Array
14
- field :attempts => Integer
15
- field :create_time => Float
16
- field :stime => Float
17
- field :etime => Float
18
- field :current_queue => String
19
- field :thread_id => Integer
20
- field :cpu => Array
21
- field :wid => Gibbler::Digest
22
-
23
- def self.inherited(obj)
24
- obj.extend Bluth::Gob::ClassMethods
25
- obj.prefix [:job, obj.to_s.split('::').last.downcase].join(':')
26
- Bluth.handlers << obj
27
- end
28
-
29
- module ClassMethods
30
- def clear
31
- keys.each do |key|
32
- Gob.redis.del key
33
- end
34
- end
35
- def enqueue(data={},q=nil)
36
- q ||= self.queue
37
- job = Gob.create generate_id(data), self, data
38
- job.current_queue = q
39
- Familia.ld "ENQUEUING: #{self} #{job.id.short} to #{q}"
40
- Bluth::Queue.redis.lpush q.key, job.id
41
- job.create_time = Time.now.utc.to_f
42
- job.attempts = 0
43
- job
44
- end
45
- def queue(name=nil)
46
- @queue = name if name
47
- @queue || Bluth::High
48
- end
49
- def generate_id(*args)
50
- a = [self, Process.pid, Bluth.sysinfo.hostname, Time.now.to_f, *args]
51
- a.gibbler
52
- end
53
- def all
54
- Bluth::Gob.all.select do |job|
55
- job.kind == self
56
- end
57
- end
58
- def size
59
- all.size
60
- end
61
- def lock_key
62
- Familia.key(prefix, :lock)
63
- end
64
- def lock!
65
- raise Bluth::Buster, "#{self} is already locked!" if locked?
66
- Familia.info "Locking #{self}"
67
- ret = Bluth::Gob.redis.set lock_key, 1
68
- Bluth.locks << lock_key
69
- ret == 'OK'
70
- end
71
- def unlock!
72
- Familia.info "Unlocking #{self}"
73
- ret = Bluth::Gob.redis.del lock_key
74
- Bluth.locks.delete lock_key
75
- ret
76
- end
77
- def locked?
78
- Bluth::Gob.redis.exists lock_key
79
- end
80
- def prepare
81
- end
82
-
83
- [:success, :failure, :running].each do |w|
84
- define_method "#{w}_key" do # success_key
85
- Familia.key(self.prefix, w)
86
- end
87
- define_method "#{w}!" do |*args| # success!(1)
88
- by = args.first || 1
89
- Bluth::Gob.redis.incrby send("#{w}_key"), by
90
- end
91
- define_method "#{w}" do # success
92
- Bluth::Gob.redis.get(send("#{w}_key")).to_i
93
- end
94
- end
95
- end
96
-
97
- def id
98
- @id = Gibbler::Digest.new(@id) if String === @id
99
- end
100
- def clear!
101
- @attempts = 0
102
- @messages = []
103
- save
104
- end
105
- def preprocess
106
- @attempts ||= 0
107
- @messages ||= []
108
- @create_time ||= Time.now.utc.to_f
109
- end
110
- def attempt?
111
- attempts < MAX_ATTEMPTS
112
- end
113
- def attempt!
114
- @attempts = attempts + 1
115
- end
116
- def current_queue
117
- @current_queue
118
- end
119
- def kind
120
- @kind = eval "::#{@kind}" rescue @kind if @kind.is_a?(String)
121
- @kind
122
- end
123
- def kind=(v)
124
- @kind = v
125
- end
126
- def perform
127
- @attempts += 1
128
- Familia.ld "PERFORM: #{self.to_hash.inspect}"
129
- @stime = Time.now.utc.to_f
130
- save # update the time
131
- self.kind.prepare if self.class.respond_to?(:prepare)
132
- self.kind.perform @data
133
- @etime = Time.now.utc.to_f
134
- save # update the time
135
- end
136
- def delayed?
137
- start = @stime || 0
138
- start > Time.now.utc.to_f
139
- end
140
- def retry!(msg=nil)
141
- move! Bluth::High, msg
142
- end
143
- def failure!(msg=nil)
144
- @etime = Time.now.utc.to_i
145
- self.kind.failure!
146
- move! Bluth::Failed, msg
147
- end
148
- def success!(msg=nil)
149
- @etime = Time.now.utc.to_i
150
- self.kind.success!
151
- move! Bluth::Successful, msg
152
- end
153
- def duration
154
- return 0 if @stime.nil?
155
- et = @etime || Time.now.utc.to_i
156
- et - @stime
157
- end
158
- def dequeue!
159
- Familia.ld "Deleting #{self.id} from #{current_queue.key}"
160
- Bluth::Queue.redis.lrem current_queue.key, 0, self.id
161
- end
162
- private
163
- def move!(to, msg=nil)
164
- @thread_id = $$
165
- if to.to_s == current_queue.to_s
166
- raise Bluth::Buster, "Cannot move job to the queue it's in: #{to}"
167
- end
168
- Familia.ld "Moving #{self.id.short} from #{current_queue.key} to #{to.key}"
169
- @messages << msg unless msg.nil? || msg.empty?
170
- # We push first to make sure we never lose a Gob ID. Instead
171
- # there's the small chance of a job ID being in two queues.
172
- Bluth::Queue.redis.lpush to.key, @id
173
- dequeue!
174
- save # update messages
175
- @current_queue = to
176
- end
177
- end
178
-
179
- end
180
-
@@ -0,0 +1,33 @@
1
+
2
+
3
+ module ExampleHandler
4
+ extend Bluth::Handler
5
+ queue :critical
6
+
7
+ # :hostid => String
8
+ # :force => Boolean (update all monitors)
9
+ def self.enqueue(opts={})
10
+ super opts, opts.delete(:queue)
11
+ end
12
+
13
+ def self.perform(data={})
14
+ begin
15
+
16
+ rescue => ex
17
+
18
+ end
19
+ end
20
+ end
21
+
22
+ class ExampleWorker < Bluth::Worker
23
+
24
+ end
25
+
26
+
27
+ Bluth::Worker.onstart do
28
+ puts "onstart called"
29
+ end
30
+
31
+ Bluth::Worker.onexit do
32
+ puts "onexit called"
33
+ end