amqp 0.8.0.rc13 → 0.8.0.rc14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/.rspec +2 -1
  2. data/.travis.yml +8 -2
  3. data/.yardopts +1 -0
  4. data/CHANGELOG +9 -0
  5. data/Gemfile +17 -11
  6. data/README.md +26 -16
  7. data/amqp.gemspec +2 -2
  8. data/bin/ci/before_build.sh +21 -0
  9. data/docs/08Migration.textile +199 -5
  10. data/docs/AMQP091ModelExplained.textile +322 -0
  11. data/docs/Bindings.textile +24 -4
  12. data/docs/Clustering.textile +1 -1
  13. data/docs/ConnectingToTheBroker.textile +98 -82
  14. data/docs/ConnectionEncryptionWithTLS.textile +65 -5
  15. data/docs/DocumentationGuidesIndex.textile +93 -13
  16. data/docs/Durability.textile +1 -1
  17. data/docs/ErrorHandling.textile +458 -94
  18. data/docs/Exchanges.textile +901 -87
  19. data/docs/GettingStarted.textile +278 -143
  20. data/docs/PatternsAndUseCases.textile +420 -0
  21. data/docs/Queues.textile +730 -178
  22. data/docs/RabbitMQVersions.textile +18 -3
  23. data/docs/RunningTests.textile +1 -1
  24. data/docs/TestingWithEventedSpec.textile +121 -0
  25. data/docs/Troubleshooting.textile +15 -1
  26. data/docs/VendorSpecificExtensions.textile +1 -1
  27. data/docs/diagrams/001_hello_world_example_routing.png +0 -0
  28. data/docs/diagrams/002_blabbr_example_routing.png +0 -0
  29. data/docs/diagrams/003_weathr_example_routing.png +0 -0
  30. data/docs/diagrams/004_fanout_exchange.png +0 -0
  31. data/docs/diagrams/005_direct_exchange.png +0 -0
  32. data/docs/diagrams/redhat/direct_exchange.png +0 -0
  33. data/docs/diagrams/redhat/fanout_exchange.png +0 -0
  34. data/docs/diagrams/redhat/topic_exchange.png +0 -0
  35. data/examples/error_handling/automatic_recovery_of_channel_and_queues.rb +50 -0
  36. data/examples/error_handling/automatically_recovering_hello_world_consumer.rb +51 -0
  37. data/examples/error_handling/automatically_recovering_hello_world_consumer_that_uses_a_server_named_queue.rb +51 -0
  38. data/examples/error_handling/basic_connection_failover.rb +22 -0
  39. data/examples/error_handling/channel_level_exception.rb +9 -2
  40. data/examples/error_handling/connection_level_exception.rb +8 -1
  41. data/examples/error_handling/connection_level_exception_with_objects.rb +49 -0
  42. data/examples/error_handling/connection_loss_handler.rb +1 -5
  43. data/examples/error_handling/hello_world_producer.rb +43 -0
  44. data/examples/error_handling/insufficient_permissions.rb +54 -0
  45. data/examples/error_handling/manual_connection_and_channel_recovery.rb +71 -0
  46. data/examples/error_handling/queue_exclusivity_violation.rb +41 -0
  47. data/examples/error_handling/queue_name_violation.rb +31 -0
  48. data/examples/exchanges/autodeletion_of_exchanges.rb +1 -4
  49. data/examples/guides/queues/01a_declaring_a_server_named_queue_using_queue_constructor.rb +7 -8
  50. data/examples/guides/queues/01b_declaring_a_queue_using_queue_constructor.rb +7 -8
  51. data/examples/guides/queues/02a_declaring_a_durable_shared_queue.rb +5 -8
  52. data/examples/guides/queues/02b_declaring_a_durable_shared_queue.rb +5 -8
  53. data/examples/guides/queues/03a_declaring_a_temporary_exclusive_queue.rb +7 -8
  54. data/examples/guides/queues/04_bind_a_queue_using_exchange_instance.rb +9 -10
  55. data/examples/guides/queues/05_bind_a_queue_using_exchange_name.rb +8 -10
  56. data/examples/guides/queues/06_subscribe_to_receive_messages.rb +10 -12
  57. data/examples/guides/queues/07_fetch_a_message_from_the_queue.rb +14 -14
  58. data/examples/guides/queues/08_unsubscribing_a_consumer.rb +13 -16
  59. data/examples/guides/queues/09_unbinding_from_exchange.rb +16 -22
  60. data/examples/guides/queues/10_purge_a_queue.rb +13 -18
  61. data/examples/guides/queues/11_deleting_a_queue.rb +14 -19
  62. data/examples/guides/queues/12_objects_that_consume_messages.rb +69 -0
  63. data/examples/guides/queues/13_objects_that_consume_messages_take_two.rb +89 -0
  64. data/examples/hello_world.rb +1 -3
  65. data/examples/hello_world_with_an_empty_string.rb +5 -6
  66. data/examples/inspecting_server_information.rb +45 -0
  67. data/examples/issues/issue_93.rb +23 -0
  68. data/examples/issues/issue_94.rb +23 -0
  69. data/examples/patterns/command/consumer.rb +45 -0
  70. data/examples/patterns/command/producer.rb +26 -0
  71. data/examples/patterns/request_reply/client.rb +29 -0
  72. data/examples/patterns/request_reply/server.rb +26 -0
  73. data/examples/publishing/publishing_a_one_off_message.rb +6 -4
  74. data/examples/publishing/returned_messages.rb +2 -10
  75. data/examples/queues/accessing_message_metadata.rb +15 -13
  76. data/examples/queues/queue_status.rb +12 -15
  77. data/examples/routing/fanout_routing.rb +33 -0
  78. data/examples/routing/headers_routing.rb +17 -15
  79. data/examples/routing/round_robin_with_direct_exchange.rb +39 -0
  80. data/examples/routing/round_robin_with_the_default_exchange.rb +38 -0
  81. data/examples/routing/unroutable_mandatory_message_is_returned.rb +33 -0
  82. data/examples/routing/weather_updates.rb +15 -20
  83. data/examples/tls/using_tls.rb +41 -0
  84. data/lib/amqp/bit_set.rb +80 -0
  85. data/lib/amqp/broker.rb +72 -0
  86. data/lib/amqp/channel.rb +93 -13
  87. data/lib/amqp/client.rb +11 -22
  88. data/lib/amqp/compatibility/ruby187_patchlevel_check.rb +2 -0
  89. data/lib/amqp/connection.rb +2 -3
  90. data/lib/amqp/consumer.rb +208 -0
  91. data/lib/amqp/deprecated/fork.rb +2 -0
  92. data/lib/amqp/deprecated/mq.rb +2 -0
  93. data/lib/amqp/exchange.rb +6 -4
  94. data/lib/amqp/extensions/rabbitmq.rb +3 -1
  95. data/lib/amqp/header.rb +76 -14
  96. data/lib/amqp/int_allocator.rb +96 -0
  97. data/lib/amqp/logger.rb +2 -0
  98. data/lib/amqp/queue.rb +242 -86
  99. data/lib/amqp/rpc.rb +2 -0
  100. data/lib/amqp/session.rb +169 -9
  101. data/lib/amqp/utilities/event_loop_helper.rb +2 -0
  102. data/lib/amqp/utilities/server_type.rb +2 -0
  103. data/lib/amqp/version.rb +2 -2
  104. data/lib/mq.rb +4 -2
  105. data/lib/mq/logger.rb +3 -1
  106. data/lib/mq/rpc.rb +3 -1
  107. data/spec/integration/authentication_spec.rb +17 -10
  108. data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +1 -1
  109. data/spec/integration/automatic_recovery_predicate_spec.rb +68 -0
  110. data/spec/integration/basic_get_spec.rb +2 -1
  111. data/spec/integration/{extensions/basic_return_spec.rb → basic_return_spec.rb} +2 -1
  112. data/spec/integration/channel_level_exception_handling_spec.rb +53 -0
  113. data/spec/integration/connection_level_exception_handling_spec.rb +49 -0
  114. data/spec/integration/declare_and_immediately_bind_a_server_named_queue_spec.rb +38 -17
  115. data/spec/integration/declare_one_hundred_server_named_queues_spec.rb +44 -0
  116. data/spec/integration/direct_exchange_routing_spec.rb +125 -0
  117. data/spec/integration/exchange_declaration_spec.rb +75 -46
  118. data/spec/integration/extensions/rabbitmq/publisher_confirmations_spec.rb +180 -0
  119. data/spec/integration/{workload_distribution_spec.rb → fanout_exchange_routing_spec.rb} +10 -9
  120. data/spec/integration/headers_exchange_routing_spec.rb +269 -0
  121. data/spec/integration/hello_world_spec.rb +77 -0
  122. data/spec/integration/immediate_messages_spec.rb +59 -0
  123. data/spec/integration/mandatory_messages_spec.rb +52 -0
  124. data/spec/integration/message_metadata_access_spec.rb +106 -0
  125. data/spec/integration/multiple_consumers_per_queue_spec.rb +319 -0
  126. data/spec/integration/ordering_of_published_messages_spec.rb +96 -0
  127. data/spec/integration/queue_declaration_spec.rb +8 -8
  128. data/spec/integration/queue_status_spec.rb +66 -0
  129. data/spec/integration/recovery/per_channel_automatic_recovery_on_graceful_broker_shutdown_spec.rb +76 -0
  130. data/spec/integration/recovery/per_channel_automatic_recovery_spec.rb +72 -0
  131. data/spec/integration/redelivery_of_unacknowledged_messages_spec.rb +96 -0
  132. data/spec/integration/regressions/concurrent_publishing_on_the_same_channel_spec.rb +91 -0
  133. data/spec/integration/regressions/empty_message_body_spec.rb +56 -0
  134. data/spec/integration/regressions/issue66_spec.rb +2 -1
  135. data/spec/integration/reply_queue_communication_spec.rb +2 -1
  136. data/spec/integration/store_and_forward_spec.rb +4 -3
  137. data/spec/integration/topic_subscription_spec.rb +2 -1
  138. data/spec/integration/tx_commit_spec.rb +124 -0
  139. data/spec/integration/tx_rollback_spec.rb +167 -0
  140. data/spec/spec_helper.rb +44 -71
  141. data/spec/unit/amqp/bit_set_spec.rb +127 -0
  142. data/spec/unit/amqp/channel_id_allocation_spec.rb +40 -0
  143. data/spec/unit/amqp/connection_spec.rb +4 -2
  144. data/spec/unit/amqp/int_allocator_spec.rb +116 -0
  145. metadata +92 -26
  146. data/CONTRIBUTORS +0 -29
  147. data/docs/Routing.textile +0 -30
  148. data/examples/real-world/task-queue/README.textile +0 -3
  149. data/examples/real-world/task-queue/consumer.rb +0 -27
  150. data/examples/real-world/task-queue/producer.rb +0 -22
  151. data/spec/unit/amqp/basic_spec.rb +0 -39
  152. data/tasks.rb +0 -4
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require "bundler"
5
+ Bundler.setup
6
+
7
+ $:.unshift(File.expand_path("../../lib", __FILE__))
8
+
9
+ require 'amqp'
10
+
11
+ EventMachine.run do
12
+ AMQP.connect(:host => '127.0.0.1') do |connection|
13
+ puts
14
+ puts "Connected to #{connection.hostname}:#{connection.port}/#{connection.vhost}"
15
+ puts
16
+ puts "Client properties:"
17
+ puts
18
+ puts connection.client_properties.inspect
19
+
20
+ puts "Server properties:"
21
+ puts
22
+ puts connection.server_properties.inspect
23
+
24
+ puts "Server capabilities:"
25
+ puts
26
+ puts connection.server_capabilities.inspect
27
+
28
+ puts "Broker product: #{connection.broker.product}, version: #{connection.broker.version}"
29
+ puts "Connected to RabbitMQ? #{connection.broker.rabbitmq?}"
30
+
31
+ puts
32
+ puts "Broker supports publisher confirms? #{connection.broker.supports_publisher_confirmations?}"
33
+
34
+ puts
35
+ puts "Broker supports basic.nack? #{connection.broker.supports_basic_nack?}"
36
+
37
+ puts
38
+ puts "Broker supports consumer cancel notifications? #{connection.broker.supports_consumer_cancel_notifications?}"
39
+
40
+ puts
41
+ puts "Broker supports exchange-to-exchange bindings? #{connection.broker.supports_exchange_to_exchange_bindings?}"
42
+
43
+ connection.disconnect { EventMachine.stop }
44
+ end # AMQP.connect
45
+ end # EventMachine.run
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require "rubygems"
5
+ require 'amqp'
6
+
7
+ puts "Running amqp gem #{AMQP::VERSION}"
8
+
9
+
10
+ AMQP.start("amqp://guest:guest@localhost:5672") do |connection, open_ok|
11
+ ch = AMQP::Channel.new(connection)
12
+ ch.direct("amqpgem.issues.93.1")
13
+ ch.direct("amqpgem.issues.93.2", :auto_delete => false)
14
+ ch.direct("amqpgem.issues.93.3") do |ex, declare_ok|
15
+ end
16
+ ch.direct("amqpgem.issues.93.4", :auto_delete => false) do |ex, declare_ok|
17
+ end
18
+ ch.direct("amqpgem.issues.93.5", :auto_delete => true)
19
+ ch.direct("amqpgem.issues.93.6", :auto_delete => true) do |ex, declare_ok|
20
+ end
21
+
22
+ puts "Done"
23
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ if defined?(Bundler)
5
+ Bundler.setup
6
+ else
7
+ require "rubygems"
8
+ end
9
+ require "amqp"
10
+
11
+ puts "Running amqp gem #{AMQP::VERSION}"
12
+
13
+ AMQP.start(:host => '127.0.0.1') do |connection|
14
+ channel = AMQP::Channel.new(connection)
15
+ exchange = channel.direct("")
16
+ queue = channel.queue("indexer_queue", { :durable => true })
17
+
18
+ EM.add_periodic_timer(1) {
19
+ queue.status do |num_messages, num_consumers|
20
+ puts "msgs:#{num_messages}"
21
+ end
22
+ }
23
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__)
4
+
5
+ require "amqp"
6
+ require "yaml"
7
+
8
+ t = Thread.new { EventMachine.run }
9
+ sleep(0.5)
10
+
11
+
12
+ connection = AMQP.connect
13
+ channel = AMQP::Channel.new(connection, :auto_recovery => true)
14
+
15
+ channel.prefetch(1)
16
+
17
+ # Acknowledgements are good for letting the server know
18
+ # that the task is finished. If the consumer doesn't send
19
+ # the acknowledgement, then the task is considered to be unfinished
20
+ # and will be requeued when consumer closes AMQP connection (because of a crash, for example).
21
+ channel.queue("amqpgem.examples.patterns.command", :durable => true, :auto_delete => false).subscribe(:ack => true) do |metadata, payload|
22
+ case metadata.type
23
+ when "gems.install"
24
+ data = YAML.load(payload)
25
+ puts "[gems.install] Received a 'gems.install' request with #{data.inspect}"
26
+
27
+ # just to demonstrate a realistic example
28
+ shellout = "gem install #{data[:gem]} --version '#{data[:version]}'"
29
+ puts "[gems.install] Executing #{shellout}"; system(shellout)
30
+
31
+ puts
32
+ puts "[gems.install] Done"
33
+ puts
34
+ else
35
+ puts "[commands] Unknown command: #{metadata.type}"
36
+ end
37
+
38
+ # message is processed, acknowledge it so that broker discards it
39
+ metadata.ack
40
+ end
41
+
42
+ puts "[boot] Ready"
43
+ Signal.trap("INT") { connection.close { EventMachine.stop } }
44
+ t.join
45
+
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__)
4
+
5
+ require "amqp"
6
+ require "yaml"
7
+
8
+ t = Thread.new { EventMachine.run }
9
+ sleep(0.5)
10
+
11
+ connection = AMQP.connect
12
+ channel = AMQP::Channel.new(connection)
13
+
14
+ # publish new commands every 3 seconds
15
+ EventMachine.add_periodic_timer(10.0) do
16
+ puts "Publishing a command (gems.install)"
17
+ payload = { :gem => "rack", :version => "~> 1.3.0" }.to_yaml
18
+
19
+ channel.default_exchange.publish(payload,
20
+ :type => "gems.install",
21
+ :routing_key => "amqpgem.examples.patterns.command")
22
+ end
23
+
24
+ puts "[boot] Ready. Will be publishing commands every 10 seconds."
25
+ Signal.trap("INT") { connection.close { EventMachine.stop } }
26
+ t.join
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__)
4
+
5
+ require "amqp"
6
+
7
+ EventMachine.run do
8
+ connection = AMQP.connect
9
+ channel = AMQP::Channel.new(connection)
10
+
11
+ replies_queue = channel.queue("", :exclusive => true, :auto_delete => true)
12
+ replies_queue.subscribe do |metadata, payload|
13
+ puts "[response] Response for #{metadata.correlation_id}: #{payload.inspect}"
14
+ end
15
+
16
+ # request time from a peer every 3 seconds
17
+ EventMachine.add_periodic_timer(3.0) do
18
+ puts "[request] Sending a request..."
19
+ channel.default_exchange.publish("get.time",
20
+ :routing_key => "amqpgem.examples.services.time",
21
+ :message_id => Kernel.rand(10101010).to_s,
22
+ :reply_to => replies_queue.name,
23
+ :immediate => true)
24
+ end
25
+
26
+
27
+
28
+ Signal.trap("INT") { connection.close { EventMachine.stop } }
29
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__)
4
+
5
+ require "amqp"
6
+
7
+ EventMachine.run do
8
+ connection = AMQP.connect
9
+ channel = AMQP::Channel.new(connection)
10
+
11
+ requests_queue = channel.queue("amqpgem.examples.services.time", :exclusive => true, :auto_delete => true)
12
+ requests_queue.subscribe(:ack => true) do |metadata, payload|
13
+ puts "[requests] Got a request #{metadata.message_id}. Sending a reply..."
14
+ channel.default_exchange.publish(Time.now.to_s,
15
+ :routing_key => metadata.reply_to,
16
+ :correlation_id => metadata.message_id,
17
+ :immediate => true,
18
+ :mandatory => true)
19
+
20
+ metadata.ack
21
+ end
22
+
23
+
24
+
25
+ Signal.trap("INT") { connection.close { EventMachine.stop } }
26
+ end
@@ -24,11 +24,13 @@ EventMachine.run do
24
24
  connection.close { EventMachine.stop }
25
25
  end
26
26
 
27
- queue = channel.queue("some_topic", :auto_delete => true)
28
- exchange = channel.topic("foo", :durable => true, :auto_delete => true)
27
+ # topic exchange is used just as example. Often it is more convenient to use default exchange,
28
+ # see http://bit.ly/amqp-gem-default-exchange
29
+ exchange = channel.topic("a.topic", :durable => true, :auto_delete => true)
30
+ queue = channel.queue("a.queue", :auto_delete => true).bind(exchange, :routing_key => "events.#")
29
31
 
30
- exchange.publish('hello world', :routing_key => "some_topic", :persistent => true, :nowait => false ) do
31
- puts 'About to disconnect'
32
+ exchange.publish('hello world', :routing_key => "events.hits.homepage", :persistent => true, :nowait => false) do
33
+ puts "About to disconnect..."
32
34
  connection.close { EventMachine.stop }
33
35
  end
34
36
  end
@@ -8,13 +8,7 @@ $:.unshift(File.expand_path("../../../lib", __FILE__))
8
8
 
9
9
  require 'amqp'
10
10
 
11
- if RUBY_VERSION == "1.8.7"
12
- class Array
13
- alias sample choice
14
- end
15
- end
16
-
17
- puts "=> Handling message returns"
11
+ puts "=> Handling returned messages"
18
12
  puts
19
13
 
20
14
  AMQP.start(:host => '127.0.0.1') do |connection|
@@ -33,8 +27,6 @@ AMQP.start(:host => '127.0.0.1') do |connection|
33
27
  }
34
28
 
35
29
  EventMachine.add_timer(2) {
36
- connection.close {
37
- EventMachine.stop
38
- }
30
+ connection.close { EventMachine.stop }
39
31
  }
40
32
  end
@@ -16,7 +16,7 @@ EventMachine.run do
16
16
  queue = channel.queue("amqpgem.examples.hello_world", :auto_delete => true)
17
17
  exchange = channel.direct("amq.direct")
18
18
 
19
- queue.bind(exchange)
19
+ queue.bind(exchange, :routing_key => "amqpgem.key")
20
20
 
21
21
  channel.on_error do |ch, channel_close|
22
22
  puts channel_close.reply_text
@@ -30,25 +30,26 @@ EventMachine.run do
30
30
  puts "metadata.headers : #{metadata.headers.inspect}"
31
31
  puts "metadata.timestamp : #{metadata.timestamp.inspect}"
32
32
  puts "metadata.type : #{metadata.type}"
33
+ puts "metadata.consumer_tag: #{metadata.consumer_tag}"
33
34
  puts "metadata.delivery_tag: #{metadata.delivery_tag}"
34
- puts "metadata.redelivered : #{metadata.redelivered}"
35
+ puts "metadata.redelivered : #{metadata.redelivered?}"
35
36
 
36
- puts "metadata.app_id : #{metadata.app_id}"
37
- puts "metadata.exchange : #{metadata.exchange}"
37
+ puts "metadata.app_id : #{metadata.app_id}"
38
+ puts "metadata.correlation_id: #{metadata.correlation_id}"
39
+ puts "metadata.exchange : #{metadata.exchange}"
38
40
  puts
39
41
  puts "Received a message: #{payload}. Disconnecting..."
40
42
 
41
- connection.close {
42
- EventMachine.stop { exit }
43
- }
43
+ connection.close { EventMachine.stop }
44
44
  end
45
45
 
46
- exchange.publish("Hello, world!",
47
- :app_id => "amqpgem.example",
48
- :priority => 8,
49
- :type => "kinda.checkin",
46
+ exchange.publish("Hey, what a great view!",
47
+ :app_id => "amqpgem.example",
48
+ :priority => 8,
49
+ :type => "kinda.checkin",
50
+ :correlation_id => "b907b65a4876fc0d4b12fbdef1b41fb0a9876a94",
50
51
  # headers table keys can be anything
51
- :headers => {
52
+ :headers => {
52
53
  :coordinates => {
53
54
  :latitude => 59.35,
54
55
  :longitude => 18.066667
@@ -56,5 +57,6 @@ EventMachine.run do
56
57
  :participants => 11,
57
58
  :venue => "Stockholm"
58
59
  },
59
- :timestamp => Time.now.to_i)
60
+ :timestamp => Time.now.to_i,
61
+ :routing_key => "amqpgem.key")
60
62
  end
@@ -11,36 +11,33 @@ require 'amqp'
11
11
  puts "=> Queue#status example"
12
12
  puts
13
13
  AMQP.start(:host => 'localhost') do |connection|
14
- channel = AMQP::Channel.new
14
+ channel = AMQP::Channel.new(connection)
15
15
 
16
16
  queue_name = "amqpgem.integration.queue.status.queue"
17
+ exchange = channel.fanout("amqpgem.integration.queue.status.fanout", :auto_delete => true)
18
+ queue = channel.queue(queue_name, :auto_delete => true).bind(exchange)
17
19
 
18
- exchange = channel.fanout("amqpgem.integration.queue.status.fanout", :auto_delete => true)
19
- queue = channel.queue(queue_name, :auto_delete => true)
20
-
21
- queue.bind(exchange) do
22
- puts "Bound #{exchange.name} => #{queue.name}"
23
- end
24
20
  100.times do |i|
25
21
  print "."
26
22
  exchange.publish(Time.now.to_i.to_s + "_#{i}", :key => queue_name)
27
23
  end
28
24
  $stdout.flush
29
25
 
30
- sleep 1
31
-
32
- queue.status do |number_of_messages, number_of_consumers|
33
- puts "# of messages on status = #{number_of_messages}"
26
+ EventMachine.add_timer(0.5) do
27
+ queue.status do |number_of_messages, number_of_consumers|
28
+ puts
29
+ puts "# of messages on status = #{number_of_messages}"
30
+ puts
31
+ queue.purge
32
+ end
34
33
  end
35
34
 
36
35
 
37
36
  show_stopper = Proc.new do
38
37
  $stdout.puts "Stopping..."
39
- connection.close {
40
- EM.stop { exit }
41
- }
38
+ connection.close { EventMachine.stop }
42
39
  end
43
40
 
44
41
  Signal.trap "INT", show_stopper
45
- EM.add_timer(2, show_stopper)
42
+ EventMachine.add_timer(2, show_stopper)
46
43
  end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require "bundler"
5
+ Bundler.setup
6
+
7
+ $:.unshift(File.expand_path("../../../lib", __FILE__))
8
+
9
+ require "amqp"
10
+
11
+ EventMachine.run do
12
+ AMQP.connect("amqp://dev.rabbitmq.com") do |connection|
13
+ channel = AMQP::Channel.new(connection)
14
+ exchange = channel.topic("amqpgem.examples.routing.fanout_routing", :auto_delete => true)
15
+
16
+ # Subscribers.
17
+ 10.times do
18
+ q = channel.queue("", :exclusive => true, :auto_delete => true).bind(exchange)
19
+ q.subscribe do |payload|
20
+ puts "Queue #{q.name} received #{payload}"
21
+ end
22
+ end
23
+
24
+ # Publish some test data in a bit, after all queues are declared & bound
25
+ EventMachine.add_timer(1.2) { exchange.publish "Hello, fanout exchanges world!" }
26
+
27
+
28
+ show_stopper = Proc.new { connection.close { EventMachine.stop } }
29
+
30
+ Signal.trap "TERM", show_stopper
31
+ EM.add_timer(3, show_stopper)
32
+ end
33
+ end
@@ -18,35 +18,37 @@ AMQP.start do |connection|
18
18
 
19
19
  exchange = channel.headers("amq.match", :durable => true)
20
20
 
21
- channel.queue("", :auto_delete => true).bind(exchange, :arguments => { 'x-match' => 'all', :arch => "x64", :os => 'linux' }).subscribe do |metadata, payload|
22
- puts "[linux/x64] Got a message: #{payload}"
21
+ channel.queue("", :auto_delete => true).bind(exchange, :arguments => { 'x-match' => 'all', :arch => "ia64", :os => 'linux' }).subscribe do |metadata, payload|
22
+ puts "[linux/ia64] Got a message: #{payload}"
23
23
  end
24
- channel.queue("", :auto_delete => true).bind(exchange, :arguments => { 'x-match' => 'all', :arch => "x32", :os => 'linux' }).subscribe do |metadata, payload|
25
- puts "[linux/x32] Got a message: #{payload}"
24
+ channel.queue("", :auto_delete => true).bind(exchange, :arguments => { 'x-match' => 'all', :arch => "x86", :os => 'linux' }).subscribe do |metadata, payload|
25
+ puts "[linux/x86] Got a message: #{payload}"
26
26
  end
27
- channel.queue("", :auto_delete => true).bind(exchange, :arguments => { 'x-match' => 'any', :os => 'linux', :arch => "__any__" }).subscribe do |metadata, payload|
27
+ channel.queue("", :auto_delete => true).bind(exchange, :arguments => { :os => 'linux'}).subscribe do |metadata, payload|
28
28
  puts "[linux] Got a message: #{payload}"
29
29
  end
30
30
  channel.queue("", :auto_delete => true).bind(exchange, :arguments => { 'x-match' => 'any', :os => 'macosx', :cores => 8 }).subscribe do |metadata, payload|
31
31
  puts "[macosx|octocore] Got a message: #{payload}"
32
32
  end
33
-
33
+ channel.queue("", :auto_delete => true).bind(exchange, :arguments => { :package => { :name => 'riak', :version => '0.14.2' } }).subscribe do |metadata, payload|
34
+ puts "[riak/0.14.2] Got a message: #{payload}"
35
+ end
34
36
 
35
37
  EventMachine.add_timer(0.5) do
36
- exchange.publish "For linux/x64", :headers => { :arch => "x64", :os => 'linux' }
37
- exchange.publish "For linux/x32", :headers => { :arch => "x32", :os => 'linux' }
38
- exchange.publish "For linux", :headers => { :os => 'linux' }
39
- exchange.publish "For OS X", :headers => { :os => 'macosx' }
40
- exchange.publish "For solaris/x64", :headers => { :os => 'solaris', :arch => 'x64' }
41
- exchange.publish "For ocotocore", :headers => { :cores => 8 }
38
+ exchange.publish "For linux/ia64", :headers => { :arch => "ia64", :os => 'linux' }
39
+ exchange.publish "For linux/x86", :headers => { :arch => "x86", :os => 'linux' }
40
+ exchange.publish "For linux", :headers => { :os => 'linux' }
41
+ exchange.publish "For OS X", :headers => { :os => 'macosx' }
42
+ exchange.publish "For solaris/ia64", :headers => { :os => 'solaris', :arch => 'ia64' }
43
+ exchange.publish "For ocotocore", :headers => { :cores => 8 }
44
+
45
+ exchange.publish "For nodes with Riak 0.14.2", :headers => { :package => { :name => 'riak', :version => '0.14.2' } }
42
46
  end
43
47
 
44
48
 
45
49
  show_stopper = Proc.new do
46
50
  $stdout.puts "Stopping..."
47
- connection.close {
48
- EventMachine.stop { exit }
49
- }
51
+ connection.close { EventMachine.stop }
50
52
  end
51
53
 
52
54
  Signal.trap "INT", show_stopper