amqp 0.6.7 → 0.7.0.pre

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.
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ *.rbc
3
+ ~*
4
+ #*
5
+ .rvmrc
6
+ .bundle
@@ -0,0 +1,5 @@
1
+ = Version 0.7
2
+ * [BUG] Sync API for queues and exchanges, support for server-generated queues & exchange names (via semi-lazy collection).
3
+ * [BUG] Sync API for MQ#close (Channel.Close) [issue #34].
4
+ * [FEATURE] From majek's fork, with some fixes. Example: AMQP.start("amqps://")
5
+ * [DEVELOP] some em-spec-based specs, bin/irb, Gemfile.
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ source "http://gemcutter.org"
4
+
5
+ gem "eventmachine"
6
+ gem "json"
7
+
8
+ group(:test) do
9
+ gem "em-spec"
10
+ gem "bacon"
11
+ end
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: http://gemcutter.org/
3
+ specs:
4
+ bacon (1.1.0)
5
+ em-spec (0.2.1)
6
+ eventmachine (0.12.10)
7
+ json (1.4.6)
8
+
9
+ PLATFORMS
10
+ ruby
11
+
12
+ DEPENDENCIES
13
+ bacon
14
+ em-spec
15
+ eventmachine
16
+ json
@@ -0,0 +1,145 @@
1
+ What AMQP gem is
2
+ ===================
3
+
4
+ Simple asynchronous AMQP driver for Ruby/EventMachine
5
+ This library works with Ruby 1.8, Ruby 1.9, JRuby and Rubinius, and is licensed under [the Ruby License](http://www.ruby-lang.org/en/LICENSE.txt).
6
+
7
+ This library was tested primarily with RabbitMQ, although it should be compatible with any
8
+ server implementing the [AMQP 0-8 spec](http://www.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf).
9
+
10
+ Getting started
11
+ ===============
12
+
13
+ To use examples with RabbitMQ, first [install the broker](http://www.rabbitmq.com/install.html). If you have Mercurial
14
+ and Erlang/OTP installed, here is how to do it in 4 lines:
15
+
16
+ hg clone http://hg.rabbitmq.com/rabbitmq-codegen
17
+ hg clone http://hg.rabbitmq.com/rabbitmq-server
18
+ cd rabbitmq-server
19
+ make run
20
+
21
+ Then have a look at the various bundled examples:
22
+
23
+ ruby examples/mq/pingpong.rb # 1-1 communication using amq.direct
24
+ ruby examples/mq/clock.rb # 1-N communication using amq.fanout
25
+ ruby examples/mq/stocks.rb # 1-subscriber communication using amq.topic
26
+
27
+ ruby examples/mq/multiclock.rb # header based routing (new rabbitmq feature)
28
+ ruby examples/mq/ack.rb # using ack
29
+ ruby examples/mq/pop.rb # pop off messages one at a time
30
+
31
+ ruby examples/mq/hashtable.rb # simple async rpc layer
32
+ ruby examples/mq/primes.rb 4 # parallelized prime number generation
33
+ ruby examples/mq/logger.rb # simple logging api
34
+
35
+ For high level API documentation see MQ class.
36
+ For more details into the lower level AMQP client API, run the simple client example:
37
+
38
+ ruby examples/amqp/simple.rb # low-level AMQP api
39
+ ruby examples/mq/internal.rb # low-level Queue/Exchange api
40
+
41
+ Or refer to protocol/doc.txt, which enumerates packets sent between a server and client
42
+ during a typical session, in both binary and decoded formats.
43
+
44
+ How to use AMQP gem with Ruby on Rails, Merb, Sinatra and other web frameworks
45
+ ==============================================================================
46
+
47
+ To use AMQP gem from web applications, you would need to have EventMachine reactor running.
48
+ If you use [Thin](http://code.macournoyer.com/thin/), you are set: Thin uses EventMachine under
49
+ the hook.
50
+
51
+ With other web servers, you need to start EventMachine reactor in it's own thread like this:
52
+
53
+ Thread.new { EM.run }
54
+
55
+ because otherwise EventMachine will block current thread. Then connect to AMQP broker:
56
+
57
+ AMQP.connect(:host => "localhost", :user => "guest", :pass => "guest", :vhost => "/")
58
+
59
+ In a Ruby on Rails app, probably the best place for this code is initializer
60
+ (like config/initializers/amqp.rb). For Merb apps, it is config/init.rb. For
61
+ Sinatra and pure Rack applications, place it next to other configuration
62
+ code.
63
+
64
+ Same separate thread technique can be used to make EventMachine play nicely with other
65
+ libraries that would block current thread (like [File::Tail](http://rubygems.org/gems/file-tail)).
66
+
67
+ AMQP gem mailing list
68
+ ==============================
69
+
70
+ * [AMQP gem mailing list](http://groups.google.com/group/ruby-amqp)
71
+ * [AMQP gem at GitHub](http://github.com/tmm1/amqp)
72
+ * [AMQP gem at Gemcutter](http://rubygems.org/gems/amqp)
73
+
74
+ Running specifications suite
75
+ ============================
76
+
77
+ To run the test suite make sure you have [bacon](http://gemcutter.org/gems/bacon) gem installed and run:
78
+
79
+ rake spec
80
+
81
+ The lib/amqp/spec.rb file is generated automatically based on the [AMQP specification](http://www.amqp.org/confluence/display/AMQP/AMQP+Specification). To generate it:
82
+
83
+ rake codegen
84
+
85
+ Credits and more information
86
+ ============================
87
+
88
+ (c) 2008—2010 [Aman Gupta](http://github.com/tmm1) (tmm1)
89
+
90
+ Current maintainer: [Jakub Stastny](http://github.com/botanicus) aka [botanicus](http://twitter.com/botanicus).
91
+
92
+ This project was inspired by [py-amqplib](http://barryp.org/software/py-amqplib/), [rabbitmq](http://rabbitmq.com), [qpid](http://qpid.apache.org/) and [rubbyt](http://github.com/rubbyt/rubbyt).
93
+ Special thanks to Dmitriy Samovskiy, Ben Hood and Tony Garnock-Jones.
94
+
95
+ AMQP brokers
96
+ ------------
97
+
98
+ * [RabbitMQ](http://rabbitmq.com) (Rabbit Technologies, Erlang/OTP, MPL)
99
+ * [ZeroMQ](http://www.zeromq.org) (iMatix/FastMQ/Intel, C++, GPL3)
100
+ * [OpenAMQ](http://openamq.org) (iMatix, C, GPL2)
101
+ * [ActiveMQ](http://activemq.apache.org) (Apache Foundation, Java, Apache2)
102
+
103
+ AMQP resources
104
+ --------------
105
+
106
+ * Steve Vinoski [explains AMQP](http://steve.vinoski.net/pdf/IEEE-Advanced_Message_Queuing_Protocol.pdf) in his column, Towards Integration
107
+
108
+ * John O'Hara on [the history of AMQP](http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=485)
109
+
110
+ * Dmitriy's [presentation on RabbitMQ/AMQP](http://somic-org.homelinux.org/blog/2008/07/31/slides-for-my-amqprabbitmq-talk/)
111
+
112
+ * ZeroMQ's [analysis of the messaging technology market](http://www.zeromq.org/whitepapers:market-analysis)
113
+
114
+ * Pieter Hintjens's [background to AMQP](http://www.openamq.org/doc:amqp-background)
115
+
116
+ * Barry Pederson's [py-amqplib](http://barryp.org/software/py-amqplib/)
117
+
118
+ * Ben Hood on [writing an AMQP client](http://hopper.squarespace.com/blog/2008/6/21/build-your-own-amqp-client.html)
119
+
120
+ * Dmitriy Samovskiy introduces [Ruby + QPid + RabbitMQ](http://somic-org.homelinux.org/blog/2008/06/24/ruby-amqp-rabbitmq-example/)
121
+
122
+ * Ben Hood's [as3-amqp](http://github.com/0x6e6562/as3-amqp) ([two](http://hopper.squarespace.com/blog/2008/7/4/server-side-as3.html), [three](http://hopper.squarespace.com/blog/2008/3/24/as3-amqp-client-first-cut.html))
123
+
124
+ * RabbitMQ's [AMQP protocol code generator](http://hg.rabbitmq.com/rabbitmq-codegen/)
125
+
126
+ * Erlang Exchange [presentation on the implementation of RabbitMQ](http://skillsmatter.com/podcast/erlang/presenting-rabbitmq-an-erlang-based-implementatio-nof-amqp) (and on the [LShift blog](http://www.lshift.net/blog/2008/07/01/slides-from-our-erlang-exchange-talk))
127
+
128
+ * Jonathan Conway's series on RabbitMQ and using it with Ruby and Merb: [One](http://jaikoo.com/2007/9/4/didn-t-you-get-the-memo), [Two](http://jaikoo.com/2008/2/29/friday-round-up-2008-02-29), [Three](http://jaikoo.com/2008/3/14/oh-hai-rabbitmq), [Four](http://jaikoo.com/2008/3/20/daemonize-rabbitmq)
129
+
130
+ * Open Enterprise's series on messaging middleware and AMQP: [Part 1](http://www1.interopsystems.com/analysis/can-amqp-break-ibms-mom-monopoly-part-1.html), [Part 2](http://www1.interopsystems.com/analysis/can-amqp-break-ibms-mom-monopoly-part-2.html), [Part 3](http://www1.interopsystems.com/analysis/can-amqp-break-ibms-mom-monopoly-part-3.html)
131
+
132
+ Messaging and distributed systems resources
133
+ -------------------------------------------
134
+
135
+ * [A Critique of the Remote Procedure Call Paradigm](http://www.cs.vu.nl/~ast/publications/euteco-1988.pdf)
136
+
137
+ * [A Note on Distributed Computing](http://research.sun.com/techrep/1994/smli_tr-94-29.pdf)
138
+
139
+ * [Convenience Over Correctness](http://steve.vinoski.net/pdf/IEEE-Convenience_Over_Correctness.pdf)
140
+
141
+ * [Metaprotocol Taxonomy and Communications Patterns](http://hessian.caucho.com/doc/metaprotocol-taxonomy.xtp)
142
+
143
+ * Joe Armstrong on [Erlang messaging vs RPC](http://armstrongonsoftware.blogspot.com/2008/05/road-we-didnt-go-down.html)
144
+
145
+ * [SEDA: scalable internet services using message queues](http://www.eecs.harvard.edu/~mdw/papers/seda-sosp01.pdf)
data/Rakefile CHANGED
@@ -1,15 +1,20 @@
1
+ desc "Generate AMQP specification classes"
1
2
  task :codegen do
2
3
  sh 'ruby protocol/codegen.rb > lib/amqp/spec.rb'
3
4
  sh 'ruby lib/amqp/spec.rb'
4
5
  end
5
6
 
7
+ desc "Run spec suite (uses bacon gem)"
6
8
  task :spec do
7
9
  sh 'bacon lib/amqp.rb'
8
10
  end
9
11
 
12
+ desc "Build the gem"
10
13
  task :gem do
11
14
  sh 'gem build *.gemspec'
12
15
  end
13
16
 
17
+ desc "Synonym for gem"
14
18
  task :pkg => :gem
19
+ desc "Synonym for gem"
15
20
  task :package => :gem
@@ -1,87 +1,39 @@
1
- require File.expand_path('../lib/amqp/version', __FILE__)
1
+ #!/usr/bin/env gem build
2
+ # encoding: utf-8
2
3
 
3
- spec = Gem::Specification.new do |s|
4
- s.name = 'amqp'
4
+ require "base64"
5
+ require File.expand_path("../lib/amqp/version", __FILE__)
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "amqp"
5
9
  s.version = AMQP::VERSION
6
- s.date = '2009-12-29'
7
- s.summary = 'AMQP client implementation in Ruby/EventMachine'
8
- s.email = "amqp@tmm1.net"
9
- s.homepage = "http://amqp.rubyforge.org/"
10
- s.rubyforge_project = 'amqp'
11
- s.description = "An implementation of the AMQP protocol in Ruby/EventMachine for writing clients to the RabbitMQ message broker"
10
+ s.authors = ["Aman Gupta", "Jakub Stastny aka botanicus"]
11
+ s.homepage = "http://github.com/tmm1/amqp"
12
+ s.summary = "AMQP client implementation in Ruby/EventMachine."
13
+ s.description = "An implementation of the AMQP protocol in Ruby/EventMachine for writing clients to the RabbitMQ message broker."
14
+ s.cert_chain = nil
15
+ s.email = Base64.decode64("c3Rhc3RueUAxMDFpZGVhcy5jeg==\n")
16
+
17
+ # files
18
+ s.files = `git ls-files`.split("\n")
19
+ s.require_paths = ["lib"]
20
+
21
+ # RDoc
12
22
  s.has_rdoc = true
13
23
  s.rdoc_options = '--include=examples'
24
+ s.extra_rdoc_files = ["README.md"] + Dir.glob("doc/*")
14
25
 
15
- # ruby -rpp -e' pp `git ls-files`.split("\n").grep(/^(doc|README)/) '
16
- s.extra_rdoc_files = [
17
- "README",
18
- "doc/EXAMPLE_01_PINGPONG",
19
- "doc/EXAMPLE_02_CLOCK",
20
- "doc/EXAMPLE_03_STOCKS",
21
- "doc/EXAMPLE_04_MULTICLOCK",
22
- "doc/EXAMPLE_05_ACK",
23
- "doc/EXAMPLE_05_POP",
24
- "doc/EXAMPLE_06_HASHTABLE"
25
- ]
26
+ # Dependencies
27
+ s.add_dependency "eventmachine", ">= 0.12.4"
26
28
 
27
- s.authors = ["Aman Gupta"]
28
- s.add_dependency('eventmachine', '>= 0.12.4')
29
+ begin
30
+ require "changelog"
31
+ rescue LoadError
32
+ warn "You have to have changelog gem installed for post install message"
33
+ else
34
+ s.post_install_message = CHANGELOG.new.version_changes
35
+ end
29
36
 
30
- # ruby -rpp -e' pp `git ls-files`.split("\n") '
31
- s.files = [
32
- "README",
33
- "Rakefile",
34
- "amqp.gemspec",
35
- "amqp.todo",
36
- "doc/EXAMPLE_01_PINGPONG",
37
- "doc/EXAMPLE_02_CLOCK",
38
- "doc/EXAMPLE_03_STOCKS",
39
- "doc/EXAMPLE_04_MULTICLOCK",
40
- "doc/EXAMPLE_05_ACK",
41
- "doc/EXAMPLE_05_POP",
42
- "doc/EXAMPLE_06_HASHTABLE",
43
- "examples/amqp/simple.rb",
44
- "examples/mq/ack.rb",
45
- "examples/mq/clock.rb",
46
- "examples/mq/pop.rb",
47
- "examples/mq/hashtable.rb",
48
- "examples/mq/internal.rb",
49
- "examples/mq/logger.rb",
50
- "examples/mq/multiclock.rb",
51
- "examples/mq/pingpong.rb",
52
- "examples/mq/primes-simple.rb",
53
- "examples/mq/primes.rb",
54
- "examples/mq/stocks.rb",
55
- "lib/amqp.rb",
56
- "lib/amqp/version.rb",
57
- "lib/amqp/buffer.rb",
58
- "lib/amqp/client.rb",
59
- "lib/amqp/frame.rb",
60
- "lib/amqp/protocol.rb",
61
- "lib/amqp/server.rb",
62
- "lib/amqp/spec.rb",
63
- "lib/ext/blankslate.rb",
64
- "lib/ext/em.rb",
65
- "lib/ext/emfork.rb",
66
- "lib/mq.rb",
67
- "lib/mq/exchange.rb",
68
- "lib/mq/header.rb",
69
- "lib/mq/logger.rb",
70
- "lib/mq/queue.rb",
71
- "lib/mq/rpc.rb",
72
- "old/README",
73
- "old/Rakefile",
74
- "old/amqp-0.8.json",
75
- "old/amqp_spec.rb",
76
- "old/amqpc.rb",
77
- "old/codegen.rb",
78
- "protocol/amqp-0.8.json",
79
- "protocol/amqp-0.8.xml",
80
- "protocol/codegen.rb",
81
- "protocol/doc.txt",
82
- "research/api.rb",
83
- "research/primes-forked.rb",
84
- "research/primes-processes.rb",
85
- "research/primes-threaded.rb"
86
- ]
37
+ # RubyForge
38
+ s.rubyforge_project = "amqp"
87
39
  end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env gem build
2
+ # encoding: utf-8
3
+
4
+ eval(File.read("amqp.gemspec")).tap do |specification|
5
+ specification.version = "#{specification.version}.pre"
6
+ end
data/bin/irb ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
5
+
6
+ require "irb"
7
+ require "mq"
8
+
9
+ IRB.start(__FILE__)
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ $:.unshift File.expand_path("../../../lib", __FILE__)
4
+ require "mq"
5
+
6
+ AMQP.start(:host => "localhost") do
7
+ @counter = 0
8
+ amq = MQ.new
9
+
10
+ 3.times do
11
+ amq.queue("") do |queue|
12
+ puts "Queue #{queue.name} declared."
13
+ puts "All queues: #{amq.queues.map(&:name).inspect}", ""
14
+
15
+ @counter += 1
16
+ end
17
+ end
18
+
19
+ EM.add_periodic_timer(0.1) do
20
+ EM.stop if @counter == 3
21
+ end
22
+ end
23
+
24
+ __END__
25
+ Queue amq.gen-qeaCcyVCG50S6QC4U/zNoA== declared.
26
+ All queues: [nil, nil, "amq.gen-qeaCcyVCG50S6QC4U/zNoA=="]
27
+
28
+ Queue amq.gen-AinMI7PBa2n1fFRIaGEAog== declared.
29
+ All queues: [nil, "amq.gen-AinMI7PBa2n1fFRIaGEAog==", "amq.gen-qeaCcyVCG50S6QC4U/zNoA=="]
30
+
31
+ Queue amq.gen-ROdJW1LZJVJulUIh8KZqkw== declared.
32
+ All queues: ["amq.gen-ROdJW1LZJVJulUIh8KZqkw==", "amq.gen-AinMI7PBa2n1fFRIaGEAog==", "amq.gen-qeaCcyVCG50S6QC4U/zNoA=="]
@@ -1,7 +1,7 @@
1
1
  $:.unshift File.dirname(__FILE__) + '/../../lib'
2
2
  require 'mq'
3
3
 
4
- AMQP.start(:host => 'localhost') do
4
+ AMQP.start(:host => 'localhost', port: 5673) do
5
5
 
6
6
  def log *args
7
7
  p args
@@ -10,6 +10,8 @@ AMQP.start(:host => 'localhost') do
10
10
  # AMQP.logging = true
11
11
 
12
12
  clock = MQ.new.fanout('clock')
13
+ clock2 = MQ.new.fanout('clock2')
14
+
13
15
  EM.add_periodic_timer(1){
14
16
  puts
15
17
 
@@ -17,17 +19,24 @@ AMQP.start(:host => 'localhost') do
17
19
  clock.publish(Marshal.dump(time))
18
20
  }
19
21
 
22
+ EM.add_periodic_timer(1){
23
+ puts
24
+
25
+ log 2, :publishing, time = Time.now
26
+ clock.publish(Marshal.dump(time))
27
+ }
28
+
20
29
  amq = MQ.new
21
- amq.queue('every second').bind(amq.fanout('clock')).subscribe{ |time|
30
+ q = amq.queue('every second')
31
+ q.bind(amq.fanout('clock')).subscribe{ |time|
22
32
  log 'every second', :received, Marshal.load(time)
23
33
  }
24
34
 
25
- amq = MQ.new
26
- amq.queue('every 5 seconds').bind(amq.fanout('clock')).subscribe{ |time|
27
- time = Marshal.load(time)
28
- log 'every 5 seconds', :received, time if time.strftime('%S').to_i%5 == 0
35
+ amq.queue!('every second').bind(amq.fanout('clock2')).subscribe{ |time|
36
+ log 2, 'every second', :received, Marshal.load(time)
29
37
  }
30
38
 
39
+
31
40
  end
32
41
 
33
42
  __END__
@@ -32,7 +32,7 @@ module AMQP
32
32
  end
33
33
 
34
34
  def length
35
- @data.length
35
+ @data.bytesize
36
36
  end
37
37
 
38
38
  def empty?
@@ -155,13 +155,13 @@ module AMQP
155
155
  _write([upper, lower], 'NN')
156
156
  when :shortstr
157
157
  data = (data || '').to_s
158
- _write([data.length, data], 'Ca*')
158
+ _write([data.bytesize, data], 'Ca*')
159
159
  when :longstr
160
160
  if data.is_a? Hash
161
161
  write(:table, data)
162
162
  else
163
163
  data = (data || '').to_s
164
- _write([data.length, data], 'Na*')
164
+ _write([data.bytesize, data], 'Na*')
165
165
  end
166
166
  when :timestamp
167
167
  write(:longlong, data.to_i)
@@ -180,7 +180,7 @@ module AMQP
180
180
  when Float
181
181
  table.write(:octet, 68) # 'D'
182
182
  # XXX there's gotta be a better way to do this..
183
- exp = value.to_s.split('.').last.length
183
+ exp = value.to_s.split('.').last.bytesize
184
184
  num = value * 10**exp
185
185
  table.write(:octet, exp)
186
186
  table.write(:long, num)
@@ -264,7 +264,7 @@ module AMQP
264
264
  def _write data, pack = nil
265
265
  data = [*data].pack(pack) if pack
266
266
  @data[@pos,0] = data
267
- @pos += data.length
267
+ @pos += data.bytesize
268
268
  end
269
269
  end
270
270
  end