amqp-utils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2009-01-12
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Doug Barth
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.
data/Manifest.txt ADDED
@@ -0,0 +1,25 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/amqp-dequeue
7
+ bin/amqp-enqueue
8
+ bin/amqp-peek
9
+ bin/amqp-pop
10
+ bin/amqp-deleteq
11
+ bin/amqp-statq
12
+ config/hoe.rb
13
+ config/requirements.rb
14
+ lib/amqp_utils.rb
15
+ lib/amqp_utils/command.rb
16
+ lib/amqp_utils/version.rb
17
+ script/console
18
+ script/destroy
19
+ script/generate
20
+ setup.rb
21
+ tasks/deployment.rake
22
+ tasks/environment.rake
23
+ tasks/website.rake
24
+ test/test_amqp_utils.rb
25
+ test/test_helper.rb
data/README.txt ADDED
@@ -0,0 +1,48 @@
1
+ = amqp-utils
2
+
3
+ == DESCRIPTION:
4
+
5
+ CLI utility programs for interacting with an AMQP queue. Using these utilities,
6
+ one can interact with an AMQP queue from the command line or via a shell
7
+ script.
8
+
9
+ These utilities have been tested against RabbitMQ, but they should work with
10
+ other AMQP compliant queues. They depend on the amqp gem available at
11
+ <http://github.com/tmm1/amqp>.
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ == SYNOPSIS:
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * amqp 0.6.0 or greater
20
+
21
+ == INSTALL:
22
+
23
+ * sudo gem install amqp-utils
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2009 Doug Barth
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
data/bin/amqp-deleteq ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/amqp_utils/command'
4
+
5
+ class QueueDeleteCommand < AmqpUtils::Command
6
+ def prepare_options(options)
7
+ options.banner %Q{
8
+ |Deletes the supplied queues.
9
+ |
10
+ | #{command_name} <queue>[, <another queue>, ...]
11
+ }.margin
12
+ end
13
+
14
+ def execute
15
+ @queues = ARGV
16
+ def @queues.delete_or_stop
17
+ queue = pop
18
+ if queue
19
+ puts "Deleteing #{queue}..."
20
+ MQ.new.queue(queue).delete
21
+ EM.next_tick { delete_or_stop }
22
+ else
23
+ AMQP.stop { EM.stop }
24
+ end
25
+ end
26
+
27
+ EM.next_tick { @queues.delete_or_stop }
28
+ end
29
+ end
30
+
31
+ QueueDeleteCommand.run
data/bin/amqp-dequeue ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/amqp_utils/command'
4
+
5
+ class DequeueCommand < AmqpUtils::Command
6
+ def prepare_options(options)
7
+ options.banner %Q{
8
+ |Removes messages from the supplied queues and displays them on STDOUT.
9
+ |
10
+ | #{command_name} <queue>[, <another queue>, ...]
11
+ }.margin
12
+ end
13
+
14
+ def execute
15
+ @queues = ARGV
16
+ @queues.each do |queue|
17
+ puts "Dequeueing from #{queue}..."
18
+ mq = MQ.new
19
+
20
+ process_message = lambda do |header, message|
21
+ puts "(#{queue})"
22
+ puts " Header: #{header.properties.inspect}"
23
+ puts " Message: #{message.inspect}"
24
+ end
25
+ mq.queue(queue).subscribe &process_message
26
+ end
27
+ end
28
+ end
29
+
30
+ DequeueCommand.run
data/bin/amqp-enqueue ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/amqp_utils/command'
4
+
5
+ class EnqueueCommand < AmqpUtils::Command
6
+ def prepare_options(options)
7
+ options.banner %Q{
8
+ |Publishes a message to a particular queue.
9
+ |
10
+ | #{command_name} <queue> <message>
11
+ |
12
+ |Enqueue options:
13
+ }.margin
14
+ options.opt :persistent, 'Mark messages as persistent.'
15
+ options.opt :count, 'Number of times the message should be published.', :type => :int, :default => 1
16
+ end
17
+
18
+ def execute
19
+ @queue = ARGV[0]
20
+ @message = ARGV[1]
21
+
22
+ publisher = EM.spawn do |queue, message, messages, options|
23
+ if messages > 0
24
+ @mq ||= MQ.new
25
+ @mq.queue(queue, :durable => true, :auto_delete => false).
26
+ publish(message, :persistent => options.persistent)
27
+
28
+ print '.'; STDOUT.flush
29
+ publisher.notify(queue, message, messages - 1, options)
30
+ else
31
+ EM.next_tick { AMQP.stop { EM.stop } }
32
+ end
33
+ end
34
+
35
+ publisher.notify(@queue, @message, options.count, options)
36
+ end
37
+ end
38
+
39
+ EnqueueCommand.run
data/bin/amqp-peek ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/amqp_utils/command'
4
+
5
+ class PeekCommand < AmqpUtils::Command
6
+ def prepare_options(options)
7
+ options.banner %Q{
8
+ |Displays the head of the queue without removing the message from the queue.
9
+ |
10
+ | #{command_name} <queue>
11
+ |
12
+ | NOTE: This operation does have side effects on the server. The message is
13
+ | placed at the end of the queue after returning from this method. The
14
+ | message is also marked as being redelivered.
15
+ }.margin
16
+ end
17
+
18
+ def execute
19
+ @queue = args[0]
20
+
21
+ mq = MQ.new
22
+
23
+ mq.queue(@queue).pop(:ack => true) do |header, message|
24
+ if message
25
+ puts "(#{@queue})"
26
+ puts " Header: "
27
+ header.properties.each do |key, value|
28
+ puts " #{key.inspect} => #{value.inspect}"
29
+ end
30
+ puts " Message: #{message.inspect}"
31
+ else
32
+ puts "(#{@queue}) empty"
33
+ end
34
+
35
+ AMQP.stop { EM.stop }
36
+ end
37
+ end
38
+ end
39
+
40
+ PeekCommand.run
data/bin/amqp-pop ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/amqp_utils/command'
4
+
5
+ class PopCommand < AmqpUtils::Command
6
+ def prepare_options(options)
7
+ options.banner %Q{
8
+ |Pops a single message from the queue.
9
+ |
10
+ | #{command_name} <queue>
11
+ }.margin
12
+ end
13
+
14
+ def execute
15
+ @queue = args[0]
16
+
17
+ mq = MQ.new
18
+ mq.queue(@queue).pop do |header, message|
19
+ if message
20
+ puts "(#{@queue})"
21
+ puts " Header: "
22
+ header.properties.each do |key, value|
23
+ puts " #{key.inspect} => #{value.inspect}"
24
+ end
25
+ puts " Message: #{message.inspect}"
26
+ else
27
+ puts "(#{@queue}) empty"
28
+ end
29
+
30
+ AMQP.stop { EM.stop }
31
+ end
32
+ end
33
+ end
34
+
35
+ PopCommand.run
data/bin/amqp-statq ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/amqp_utils/command'
4
+
5
+ class QueueStatCommand < AmqpUtils::Command
6
+ def prepare_options(options)
7
+ options.banner %Q{
8
+ |Gets statistics on the queues specified.
9
+ |
10
+ | #{command_name} <queue> [<another_queue> ..]
11
+ }.margin
12
+ end
13
+
14
+ def execute
15
+ @queues = ARGV
16
+
17
+ @queues.each do |queue|
18
+ MQ.new.queue(queue).status do |size, consumers|
19
+ puts "Queue <#{queue}>: #{size} message(s), #{consumers} consumer(s)"
20
+
21
+ @queues.delete(queue)
22
+ AMQP.stop { EM.stop } if @queues.empty?
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ QueueStatCommand.run
data/config/hoe.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'amqp_utils/version'
2
+
3
+ AUTHOR = 'Doug Barth' # can also be an array of Authors
4
+ EMAIL = "dougbarth@gmail.com"
5
+ DESCRIPTION = "Command line utilities for interacting with AMQP compliant queues"
6
+ GEM_NAME = 'amqp-utils' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'amqp-utils' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+ EXTRA_DEPENDENCIES = [
11
+ ['amqp', '>= 0.6.0'],
12
+ ['trollop', '>= 1.10.2'],
13
+ ['facets', '>= 2.4.4']
14
+ ] # An array of rubygem dependencies [name, version]
15
+
16
+ @config_file = "~/.rubyforge/user-config.yml"
17
+ @config = nil
18
+ RUBYFORGE_USERNAME = "unknown"
19
+ def rubyforge_username
20
+ unless @config
21
+ begin
22
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
23
+ rescue
24
+ puts <<-EOS
25
+ ERROR: No rubyforge config file found: #{@config_file}
26
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
27
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
28
+ EOS
29
+ exit
30
+ end
31
+ end
32
+ RUBYFORGE_USERNAME.replace @config["username"]
33
+ end
34
+
35
+
36
+ REV = nil
37
+ # UNCOMMENT IF REQUIRED:
38
+ # REV = YAML.load(`svn info`)['Revision']
39
+ VERS = AmqpUtils::VERSION::STRING + (REV ? ".#{REV}" : "")
40
+ RDOC_OPTS = ['--quiet', '--title', 'amqp-utils documentation',
41
+ "--opname", "index.html",
42
+ "--line-numbers",
43
+ "--main", "README",
44
+ "--inline-source"]
45
+
46
+ class Hoe
47
+ def extra_deps
48
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
49
+ @extra_deps
50
+ end
51
+ end
52
+
53
+ # Generate all the Rake tasks
54
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
55
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
56
+ p.developer(AUTHOR, EMAIL)
57
+ p.description = DESCRIPTION
58
+ p.summary = DESCRIPTION
59
+ p.url = HOMEPATH
60
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
61
+ p.test_globs = ["test/**/test_*.rb"]
62
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
63
+
64
+ # == Optional
65
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
66
+ p.extra_deps = EXTRA_DEPENDENCIES
67
+
68
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
69
+ end
70
+
71
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
72
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
73
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
74
+ $hoe.rsync_args = '-av --delete --ignore-errors'
75
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/../amqp_utils'
2
+
3
+ class AmqpUtils::Command
4
+ class << self
5
+ def run(args = ARGV)
6
+ command = new(args)
7
+ command.process_options
8
+ command.go
9
+ end
10
+ end
11
+
12
+ def initialize(args)
13
+ @args = args
14
+ end
15
+
16
+ attr_reader :args, :options
17
+
18
+ def process_options
19
+ command = self
20
+ @options = Trollop::options(@args) do
21
+ command.prepare_options(self) if command.respond_to?(:prepare_options)
22
+
23
+ banner %Q{
24
+ |
25
+ |Standard options:
26
+ }.margin
27
+ opt :host, 'The AMQP host to connect to', :default => 'localhost'
28
+ opt :port, 'The AMQP port to connect to', :default => 5672
29
+ opt :vhost, 'The vhost to connect to', :default => '/'
30
+ opt :user, 'The user name to authenticate with', :default => 'guest'
31
+ opt :password, 'The password to connect with', :default => 'guest'
32
+ opt :timeout, 'The connect timeout in seconds', :default => 5
33
+ opt :verbose, 'Print all AMQP commands sent and received.'
34
+ end
35
+ end
36
+
37
+ def command_name
38
+ File.basename($0)
39
+ end
40
+
41
+ def go
42
+ EM.run do
43
+ %w(host port vhost user timeout).each do |val|
44
+ AMQP.settings[val.to_sym] = options[val.to_sym]
45
+ end
46
+ AMQP.settings[:pass] = options.password
47
+ AMQP.logging = options.verbose
48
+
49
+ trap("INT") do
50
+ if @nice_tried
51
+ EM.stop
52
+ else
53
+ AMQP.stop { EM.stop }
54
+ @nice_tried = true
55
+ end
56
+ end
57
+
58
+ execute
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,9 @@
1
+ module AmqpUtils
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/amqp_utils.rb ADDED
@@ -0,0 +1,17 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module AmqpUtils
5
+
6
+ end
7
+
8
+ require 'rubygems'
9
+
10
+ gem 'trollop'
11
+ require 'trollop'
12
+
13
+ gem 'amqp'
14
+ require 'mq'
15
+
16
+ gem 'facets'
17
+ require 'facets/string/tab'
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/amqp_utils.rb'}"
9
+ puts "Loading amqp-utils gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)