super-poller 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ require "super_poller"
2
+ queue = SuperPoller::QueueUrl.parse(ARGV.shift).to_queue
3
+
4
+ memo = {:memo => Time.now.to_f}
5
+ queue.push(memo)
6
+
7
+ SuperPoller::NoneBlockingPoller.new(queue, lambda{|msg|
8
+ skip = false
9
+ begin
10
+ exit if msg == memo
11
+ p msg
12
+ print "Kill? > "
13
+ skip = gets =~ /^[Yy]/
14
+ ensure
15
+ queue.push(msg) unless skip or msg == memo
16
+ end
17
+ }).start!
@@ -0,0 +1,4 @@
1
+ require "super_poller"
2
+ in_queue, out_queue = [nil,nil].map{|url| SuperPoller::QueueUrl.parse(ARGV.shift).to_queue }
3
+
4
+ SuperPoller::QueueItterator.new(in_queue).each(&out_queue.method(:push))
@@ -0,0 +1,3 @@
1
+ require "super_poller"
2
+ queue = SuperPoller::QueueUrl.parse(ARGV.shift).to_queue
3
+ SuperPoller::NoneBlockingPoller.new(queue, lambda{|msg| }).start!
@@ -0,0 +1,51 @@
1
+ require "super_poller"
2
+ require 'optparse'
3
+
4
+ options = {}
5
+ opts = OptionParser.new do |opts|
6
+ opts.banner = "Usage queue grep QUEUE_URL [options]"
7
+ opts.on("-f STRING", "--ruby-filter STRING", "Set ruby filter") do |v|
8
+ options[:ruby_filter] = v
9
+ end
10
+
11
+ opts.on("-a STRING", "--ruby-action STRING", "Set ruby action") do |v|
12
+ options[:ruby_action] = v
13
+ end
14
+
15
+ opts.on("-d", "--delete", "Delete all matches") do |v|
16
+ options[:ruby_action] = ":delete"
17
+ end
18
+
19
+ opts.on("-c QUEUE", "--copy QUEUE", "Copy all matches") do |v|
20
+ options[:ruby_action] = "SuperPoller::QueueUrl.parse(#{v.to_s.inspect}).to_queue.push(msg)"
21
+ end
22
+
23
+ opts.on("-m QUEUE", "--move QUEUE", "Move all matches") do |v|
24
+ options[:ruby_action] = "SuperPoller::QueueUrl.parse(#{v.to_s.inspect}).to_queue.push(msg); :delete"
25
+ end
26
+
27
+ opts.on("-t TYPE", "--message-type TYPE", "Select messages of a given type") do |v|
28
+ options[:ruby_filter] = "#{v.to_s.inspect} == msg[:name].to_s rescue false"
29
+ end
30
+
31
+ opts.on_tail("-h", "--help", "Show this message") do
32
+ puts opts
33
+ exit 1
34
+ end
35
+ end
36
+
37
+ opts.parse!
38
+
39
+ unless queue_url = ARGV.shift
40
+ puts opts
41
+ exit 1
42
+ end
43
+
44
+ queue = SuperPoller::QueueUrl.parse(queue_url).to_queue
45
+
46
+ eval "def matcher_matches?(msg); #{ options[:ruby_filter] || "true" }; end"
47
+ eval "def action(msg); #{ options[:ruby_action] || "p msg" }; end"
48
+
49
+ SuperPoller::QueueItterator.new(queue).each do |msg|
50
+ action(msg) if matcher_matches? msg
51
+ end
@@ -0,0 +1,13 @@
1
+ require "super_poller"
2
+ queue_one = SuperPoller::QueueUrl.parse(ARGV.shift).to_queue
3
+ queue_two = SuperPoller::QueueUrl.parse(ARGV.shift).to_queue
4
+
5
+ SuperPoller::QueueItterator.new(queue_one).each do |msg|
6
+ p msg
7
+ print "Move to #{queue_two}? > "
8
+
9
+ if gets =~ /^[Yy]/
10
+ queue_two.push(msg)
11
+ :delete
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ require "super_poller"
2
+ in_queue, out_queue = [nil,nil].map{|url| SuperPoller::QueueUrl.parse(ARGV.shift).to_queue }
3
+
4
+ SuperPoller::NoneBlockingPoller.new(in_queue, out_queue.method(:push)).start!
@@ -0,0 +1,3 @@
1
+ require "super_poller"
2
+ queue = SuperPoller::QueueUrl.parse(ARGV.shift).to_queue
3
+ SuperPoller::QueueItterator.new(queue).each(&method(:p))
@@ -0,0 +1,33 @@
1
+ class SuperPoller::AggregatingErrorLogger
2
+ def initialize(stats_file, queue)
3
+ @stats_file, @queue = stats_file, queue
4
+ end
5
+
6
+ def call(error, failed_message)
7
+ update_error_queue(error, failed_message)
8
+ update_error_stats(error, failed_message[:name] || :unknown)
9
+ end
10
+
11
+ protected
12
+ def update_error_queue(error, failed_message)
13
+ error_class_name = error.class.name.to_sym
14
+ error_description = {:class => error_class_name, :message => error.message}
15
+ @queue.push(failed_message.merge(:error => error_description))
16
+ end
17
+
18
+ def update_error_stats(error, message_name)
19
+ stats = load_stats
20
+ error_class_name = error.class.name.to_sym
21
+ stats_for_name = (stats[message_name] ||= {})
22
+ stats_for_name[error_class_name] ||= 0
23
+ stats_for_name[error_class_name] += 1
24
+
25
+ File.open(@stats_file, "w") do |file|
26
+ file << YAML.dump(stats)
27
+ end
28
+ end
29
+
30
+ def load_stats
31
+ File.exists?(@stats_file) && YAML.load(File.read(@stats_file)) || {}
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ class SuperPoller::BufferedHandler < SuperPoller::Handler
2
+ class << self
3
+ def buffer_size(size)
4
+ @max_buffer_size = size
5
+ end
6
+
7
+ def max_buffer_size
8
+ @max_buffer_size || []
9
+ end
10
+ end
11
+
12
+ def initialize
13
+ @buffer = []
14
+ end
15
+
16
+ def call(msg)
17
+ @buffer.push msg
18
+ if @buffer.size >= self.class.max_buffer_size
19
+ handle_batch @buffer
20
+ @buffer = []
21
+ end
22
+ end
23
+
24
+ def handle_batch(batch)
25
+ raise NotImplementedError, "You must define a batch handler."
26
+ end
27
+
28
+ end
@@ -0,0 +1,12 @@
1
+ class SuperPoller::ErrorReporter
2
+ def initialize(message_handler, error_handler = nil, &block)
3
+ @message_handler = message_handler
4
+ @error_handler = error_handler || block
5
+ end
6
+
7
+ def call(*args)
8
+ @message_handler.call(*args)
9
+ rescue StandardError => e
10
+ @error_handler.call(e, *args)
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ class SuperPoller::Handler
2
+ autoload :TestCase, "super_poller/test_case"
3
+
4
+ class << self
5
+ def handles(*new_message_names)
6
+ @message_names = (message_names + new_message_names).uniq
7
+ end
8
+
9
+ def message_names
10
+ @message_names || []
11
+ end
12
+ end
13
+
14
+ def can_handle?(message)
15
+ self.class.message_names.include? message[:name].to_sym
16
+ end
17
+
18
+ def call(message)
19
+ raise NotImplementedError, "You must define a call handler."
20
+ end
21
+
22
+ end
@@ -0,0 +1,13 @@
1
+ class SuperPoller::NoneBlockingPoller < SuperPoller::Poller
2
+ EmptyQueue = Class.new(Exception)
3
+
4
+ def start!
5
+ super
6
+ rescue EmptyQueue
7
+ end
8
+
9
+ protected
10
+ def get_message
11
+ @queue.fetch or raise EmptyQueue
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ class SuperPoller::Poller
2
+ def initialize(queue, message_handler)
3
+ @message_handler, @queue = message_handler, queue
4
+ end
5
+
6
+ def poll
7
+ @message_handler.call(get_message)
8
+ end
9
+
10
+ def start!
11
+ poll while true
12
+ end
13
+
14
+ protected
15
+ def get_message
16
+ @queue.pop
17
+ rescue Interrupt
18
+ raise
19
+ rescue Object => e
20
+ STDERR.puts "Error while fetching from the queue: #{e.class}: #{e.message}"
21
+ sleep 10
22
+ retry
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ class SuperPoller::QueueItterator
2
+ def initialize(queue)
3
+ @queue = queue
4
+ end
5
+
6
+ def each(&block)
7
+ @memo = {:memo => Time.now.to_f}
8
+ @queue.push @memo
9
+ while @memo
10
+ begin
11
+ break unless msg = @queue.fetch
12
+ if msg == @memo
13
+ msg = @memo = nil
14
+ else
15
+ msg = nil if :delete == block.call(msg)
16
+ end
17
+ ensure
18
+ @queue.push msg if msg
19
+ end
20
+ end
21
+ ensure
22
+ destroy_the_memo
23
+ end
24
+
25
+ def destroy_the_memo
26
+ while @memo and msg = @queue.fetch and msg != @memo
27
+ @queue.push(msg)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require "uri"
2
+
3
+ class SuperPoller::QueueUrl < URI::Generic
4
+ def self.parse(url)
5
+ url = "starling://localhost:22122/#{url}" if url =~ /^[a-zA-Z0-9_-]+$/
6
+ new(*URI.parse(url).send(:component_ary))
7
+ end
8
+
9
+ def to_queue
10
+ raise URI::InvalidURIError unless respond_to? "to_#{scheme}_queue"
11
+ send("to_#{scheme}_queue")
12
+ end
13
+
14
+ protected
15
+ def to_starling_queue
16
+ SuperPoller::StarlingQueue.new(path, "#{host}:#{port}")
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ class SuperPoller::Router
2
+ RoutingError = Class.new(Exception)
3
+
4
+ def initialize()
5
+ @handlers = []
6
+ end
7
+
8
+ def add_handler(handler)
9
+ @handlers.push handler
10
+ @handlers.uniq!
11
+ self
12
+ end
13
+
14
+ alias << add_handler
15
+
16
+ def call(message)
17
+ handler = best_handler_for_message(message)
18
+ handler.call(message[:body])
19
+ end
20
+
21
+ protected
22
+
23
+ def best_handler_for_message(messsage)
24
+ @handlers.each do |handler|
25
+ return handler if handler.can_handle? messsage
26
+ end
27
+ raise RoutingError, "No handler found"
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ require "starling"
2
+
3
+ class SuperPoller::StarlingQueue
4
+ def initialize(queue_name, *args)
5
+ @queue_name = queue_name.to_s
6
+ @queue = Starling.new(*args)
7
+ end
8
+
9
+ def pop
10
+ @queue.get(@queue_name)
11
+ end
12
+
13
+ def push(v)
14
+ @queue.set(@queue_name, v)
15
+ end
16
+
17
+ def fetch
18
+ @queue.fetch(@queue_name)
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ class SuperPoller::Handler::TestCase < (defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase)
2
+
3
+ def handler
4
+ @handler ||= self.class.name.gsub(/Test$/, "").constantize.new
5
+ end
6
+
7
+ def self.should_handle(name)
8
+ should "handle a #{name.inspect} message" do
9
+ assert handler.can_handle?(:name => name)
10
+ end
11
+ end
12
+
13
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Tom Lea
@@ -29,6 +29,24 @@ extra_rdoc_files: []
29
29
 
30
30
  files:
31
31
  - bin/queue
32
+ - bin/scripts/queue_choose
33
+ - bin/scripts/queue_copy
34
+ - bin/scripts/queue_flush
35
+ - bin/scripts/queue_grep
36
+ - bin/scripts/queue_interactive_move
37
+ - bin/scripts/queue_move
38
+ - bin/scripts/queue_scan
39
+ - lib/super_poller/aggregating_error_logger.rb
40
+ - lib/super_poller/buffered_handler.rb
41
+ - lib/super_poller/error_reporter.rb
42
+ - lib/super_poller/handler.rb
43
+ - lib/super_poller/none_blocking_poller.rb
44
+ - lib/super_poller/poller.rb
45
+ - lib/super_poller/queue_itterator.rb
46
+ - lib/super_poller/queue_url.rb
47
+ - lib/super_poller/router.rb
48
+ - lib/super_poller/starling_queue.rb
49
+ - lib/super_poller/test_case.rb
32
50
  - lib/super_poller.rb
33
51
  - test/aggregating_error_logger_test.rb
34
52
  - test/buffered_handler_test.rb