amqp-utils 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/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)