amqp 0.6.7 → 0.7.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -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