bunny 0.8.0 → 0.9.0.pre1

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.
Files changed (91) hide show
  1. data/.gitignore +7 -1
  2. data/.travis.yml +14 -4
  3. data/ChangeLog.md +72 -0
  4. data/Gemfile +17 -11
  5. data/README.md +82 -0
  6. data/bunny.gemspec +6 -13
  7. data/examples/connection/heartbeat.rb +17 -0
  8. data/lib/bunny.rb +40 -56
  9. data/lib/bunny/channel.rb +615 -19
  10. data/lib/bunny/channel_id_allocator.rb +59 -0
  11. data/lib/bunny/compatibility.rb +24 -0
  12. data/lib/bunny/concurrent/condition.rb +63 -0
  13. data/lib/bunny/consumer.rb +42 -26
  14. data/lib/bunny/consumer_tag_generator.rb +22 -0
  15. data/lib/bunny/consumer_work_pool.rb +67 -0
  16. data/lib/bunny/exceptions.rb +128 -0
  17. data/lib/bunny/exchange.rb +131 -136
  18. data/lib/bunny/framing.rb +53 -0
  19. data/lib/bunny/heartbeat_sender.rb +59 -0
  20. data/lib/bunny/main_loop.rb +70 -0
  21. data/lib/bunny/message_metadata.rb +126 -0
  22. data/lib/bunny/queue.rb +102 -275
  23. data/lib/bunny/session.rb +478 -0
  24. data/lib/bunny/socket.rb +44 -0
  25. data/lib/bunny/system_timer.rb +9 -9
  26. data/lib/bunny/transport.rb +179 -0
  27. data/lib/bunny/version.rb +1 -1
  28. data/spec/compatibility/queue_declare_spec.rb +40 -0
  29. data/spec/higher_level_api/integration/basic_ack_spec.rb +54 -0
  30. data/spec/higher_level_api/integration/basic_consume_spec.rb +51 -0
  31. data/spec/higher_level_api/integration/basic_get_spec.rb +47 -0
  32. data/spec/higher_level_api/integration/basic_nack_spec.rb +39 -0
  33. data/spec/higher_level_api/integration/basic_publish_spec.rb +105 -0
  34. data/spec/higher_level_api/integration/basic_qos_spec.rb +32 -0
  35. data/spec/higher_level_api/integration/basic_recover_spec.rb +18 -0
  36. data/spec/higher_level_api/integration/basic_reject_spec.rb +53 -0
  37. data/spec/higher_level_api/integration/basic_return_spec.rb +33 -0
  38. data/spec/higher_level_api/integration/channel_close_spec.rb +29 -0
  39. data/spec/higher_level_api/integration/channel_flow_spec.rb +24 -0
  40. data/spec/higher_level_api/integration/channel_open_spec.rb +57 -0
  41. data/spec/higher_level_api/integration/channel_open_stress_spec.rb +22 -0
  42. data/spec/higher_level_api/integration/confirm_select_spec.rb +19 -0
  43. data/spec/higher_level_api/integration/connection_spec.rb +340 -0
  44. data/spec/higher_level_api/integration/exchange_bind_spec.rb +31 -0
  45. data/spec/higher_level_api/integration/exchange_declare_spec.rb +183 -0
  46. data/spec/higher_level_api/integration/exchange_delete_spec.rb +37 -0
  47. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +40 -0
  48. data/spec/higher_level_api/integration/queue_bind_spec.rb +109 -0
  49. data/spec/higher_level_api/integration/queue_declare_spec.rb +129 -0
  50. data/spec/higher_level_api/integration/queue_delete_spec.rb +38 -0
  51. data/spec/higher_level_api/integration/queue_purge_spec.rb +30 -0
  52. data/spec/higher_level_api/integration/queue_unbind_spec.rb +33 -0
  53. data/spec/higher_level_api/integration/tx_commit_spec.rb +21 -0
  54. data/spec/higher_level_api/integration/tx_rollback_spec.rb +21 -0
  55. data/spec/lower_level_api/integration/basic_cancel_spec.rb +57 -0
  56. data/spec/lower_level_api/integration/basic_consume_spec.rb +100 -0
  57. data/spec/spec_helper.rb +64 -0
  58. data/spec/unit/bunny_spec.rb +15 -0
  59. data/spec/unit/concurrent/condition_spec.rb +66 -0
  60. metadata +135 -93
  61. data/CHANGELOG +0 -21
  62. data/README.textile +0 -76
  63. data/Rakefile +0 -14
  64. data/examples/simple.rb +0 -32
  65. data/examples/simple_ack.rb +0 -35
  66. data/examples/simple_consumer.rb +0 -55
  67. data/examples/simple_fanout.rb +0 -41
  68. data/examples/simple_headers.rb +0 -42
  69. data/examples/simple_publisher.rb +0 -29
  70. data/examples/simple_topic.rb +0 -61
  71. data/ext/amqp-0.9.1.json +0 -389
  72. data/ext/config.yml +0 -4
  73. data/ext/qparser.rb +0 -426
  74. data/lib/bunny/client.rb +0 -370
  75. data/lib/bunny/subscription.rb +0 -92
  76. data/lib/qrack/amq-client-url.rb +0 -165
  77. data/lib/qrack/channel.rb +0 -20
  78. data/lib/qrack/client.rb +0 -247
  79. data/lib/qrack/errors.rb +0 -5
  80. data/lib/qrack/protocol/protocol.rb +0 -135
  81. data/lib/qrack/protocol/spec.rb +0 -525
  82. data/lib/qrack/qrack.rb +0 -20
  83. data/lib/qrack/queue.rb +0 -40
  84. data/lib/qrack/subscription.rb +0 -152
  85. data/lib/qrack/transport/buffer.rb +0 -305
  86. data/lib/qrack/transport/frame.rb +0 -102
  87. data/spec/spec_09/amqp_url_spec.rb +0 -19
  88. data/spec/spec_09/bunny_spec.rb +0 -76
  89. data/spec/spec_09/connection_spec.rb +0 -34
  90. data/spec/spec_09/exchange_spec.rb +0 -173
  91. data/spec/spec_09/queue_spec.rb +0 -240
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ describe Bunny::Exchange do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
6
+ c.start
7
+ c
8
+ end
9
+
10
+ after :all do
11
+ connection.close if connection.open?
12
+ end
13
+
14
+ it "binds two existing exchanges" do
15
+ ch = connection.create_channel
16
+
17
+ source = ch.fanout("bunny.exchanges.source", :auto_delete => true)
18
+ destination = ch.fanout("bunny.exchanges.destination", :auto_delete => true)
19
+
20
+ queue = ch.queue("", :exclusive => true)
21
+ queue.bind(destination)
22
+
23
+ destination.bind(source)
24
+ source.publish("")
25
+ sleep 0.5
26
+
27
+ queue.message_count.should be > 0
28
+
29
+ ch.close
30
+ end
31
+ end
@@ -0,0 +1,183 @@
1
+ require "spec_helper"
2
+
3
+ describe Bunny::Exchange do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
6
+ c.start
7
+ c
8
+ end
9
+
10
+ after :all do
11
+ connection.close
12
+ end
13
+
14
+
15
+ context "of type fanout" do
16
+ context "with a non-predefined name" do
17
+ it "is declared" do
18
+ ch = connection.create_channel
19
+
20
+ name = "bunny.tests.exchages.fanout"
21
+ x = ch.fanout(name)
22
+ x.name.should == name
23
+
24
+ x.delete
25
+ ch.close
26
+ end
27
+ end
28
+
29
+ context "with a predefined name" do
30
+ it "is NOT declared" do
31
+ ch = connection.create_channel
32
+
33
+ name = "amq.fanout"
34
+ x = ch.fanout(name)
35
+ x.name.should == name
36
+
37
+ ch.close
38
+ end
39
+ end
40
+
41
+ context "with the durable property" do
42
+ it "is declared as durable" do
43
+ ch = connection.create_channel
44
+
45
+ name = "bunny.tests.exchages.durable"
46
+ x = ch.fanout(name, :durable => true)
47
+ x.name.should == name
48
+ x.should be_durable
49
+ x.should_not be_auto_delete
50
+
51
+ x.delete
52
+ ch.close
53
+ end
54
+ end
55
+
56
+
57
+ context "with the auto-delete property" do
58
+ it "is declared as auto-delete" do
59
+ ch = connection.create_channel
60
+
61
+ name = "bunny.tests.exchages.auto-delete"
62
+ x = ch.fanout(name, :auto_delete => true)
63
+ x.name.should == name
64
+ x.should_not be_durable
65
+ x.should be_auto_delete
66
+
67
+ x.delete
68
+ ch.close
69
+ end
70
+ end
71
+
72
+
73
+ context "when declared with a different set of attributes" do
74
+ it "raises an exception" do
75
+ ch = connection.create_channel
76
+
77
+ x = ch.fanout("bunny.tests.exchanges.fanout", :auto_delete => true, :durable => false)
78
+ expect {
79
+ # force re-declaration
80
+ ch.exchange_declare("bunny.tests.exchanges.fanout", :direct, :auto_delete => false, :durable => true)
81
+ }.to raise_error(Bunny::PreconditionFailed)
82
+
83
+ ch.should be_closed
84
+ expect {
85
+ ch.fanout("bunny.tests.exchanges.fanout", :auto_delete => true, :durable => false)
86
+ }.to raise_error(Bunny::ChannelAlreadyClosed)
87
+ end
88
+ end
89
+ end
90
+
91
+ context "of type direct" do
92
+ context "with a non-predefined name" do
93
+ it "is declared" do
94
+ ch = connection.create_channel
95
+
96
+ name = "bunny.tests.exchages.direct"
97
+ x = ch.direct(name)
98
+ x.name.should == name
99
+
100
+ x.delete
101
+ ch.close
102
+ end
103
+ end
104
+
105
+ context "with a predefined name" do
106
+ it "is NOT declared" do
107
+ ch = connection.create_channel
108
+
109
+ name = "amq.direct"
110
+ x = ch.direct(name)
111
+ x.name.should == name
112
+
113
+ ch.close
114
+ end
115
+ end
116
+ end
117
+
118
+ context "of type topic" do
119
+ context "with a non-predefined name" do
120
+ it "is declared" do
121
+ ch = connection.create_channel
122
+
123
+ name = "bunny.tests.exchages.topic"
124
+ x = ch.topic(name)
125
+ x.name.should == name
126
+
127
+ x.delete
128
+ ch.close
129
+ end
130
+ end
131
+
132
+ context "with a predefined name" do
133
+ it "is NOT declared" do
134
+ ch = connection.create_channel
135
+
136
+ name = "amq.topic"
137
+ x = ch.topic(name)
138
+ x.name.should == name
139
+
140
+ ch.close
141
+ end
142
+ end
143
+ end
144
+
145
+ context "of type headers" do
146
+ context "with a non-predefined name" do
147
+ it "is declared" do
148
+ ch = connection.create_channel
149
+
150
+ name = "bunny.tests.exchages.headers"
151
+ x = ch.headers(name)
152
+ x.name.should == name
153
+
154
+ x.delete
155
+ ch.close
156
+ end
157
+ end
158
+
159
+ context "with a predefined name (amq.match)" do
160
+ it "is NOT declared" do
161
+ ch = connection.create_channel
162
+
163
+ name = "amq.match"
164
+ x = ch.headers(name)
165
+ x.name.should == name
166
+
167
+ ch.close
168
+ end
169
+ end
170
+
171
+ context "with a predefined name (amq.headers)" do
172
+ it "is NOT declared" do
173
+ ch = connection.create_channel
174
+
175
+ name = "amq.headers"
176
+ x = ch.headers(name)
177
+ x.name.should == name
178
+
179
+ ch.close
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ describe Bunny::Exchange, "#delete" do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
6
+ c.start
7
+ c
8
+ end
9
+
10
+ after :all do
11
+ connection.close if connection.open?
12
+ end
13
+
14
+
15
+ context "with a name of an existing exchange" do
16
+ it "deletes that queue" do
17
+ ch = connection.create_channel
18
+ x = ch.fanout("bunny.tests.exchanges.fanout#{rand}")
19
+
20
+ x.delete
21
+ expect {
22
+ x.delete
23
+ }.to raise_error(Bunny::NotFound)
24
+ end
25
+ end
26
+
27
+
28
+ context "with a name of an existing exchange" do
29
+ it "raises an exception" do
30
+ ch = connection.create_channel
31
+
32
+ expect {
33
+ ch.exchange_delete("sdkhflsdjflskdjflsd#{rand}")
34
+ }.to raise_error(Bunny::NotFound)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Bunny::Exchange do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
6
+ c.start
7
+ c
8
+ end
9
+
10
+ after :all do
11
+ connection.close if connection.open?
12
+ end
13
+
14
+ it "unbinds two existing exchanges" do
15
+ ch = connection.create_channel
16
+
17
+ source = ch.fanout("bunny.exchanges.source#{rand}")
18
+ destination = ch.fanout("bunny.exchanges.destination#{rand}")
19
+
20
+ queue = ch.queue("", :exclusive => true)
21
+ queue.bind(destination)
22
+
23
+ destination.bind(source)
24
+ source.publish("")
25
+ sleep 0.5
26
+
27
+ queue.message_count.should be == 1
28
+ queue.pop(:ack => true)
29
+
30
+ destination.unbind(source)
31
+ source.publish("")
32
+ sleep 0.5
33
+
34
+ queue.message_count.should be == 0
35
+
36
+ source.delete
37
+ destination.delete
38
+ ch.close
39
+ end
40
+ end
@@ -0,0 +1,109 @@
1
+ require "spec_helper"
2
+
3
+ describe "A client-named", Bunny::Queue do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
6
+ c.start
7
+ c
8
+ end
9
+
10
+ it "can be bound to a pre-declared exchange" do
11
+ ch = connection.create_channel
12
+ q = ch.queue("bunny.tests.queues.client-named#{rand}", :exclusive => true)
13
+ q.should_not be_server_named
14
+
15
+ q.bind("amq.fanout").should be_instance_of(AMQ::Protocol::Queue::BindOk)
16
+
17
+ ch.close
18
+ end
19
+
20
+ it "can be unbound from a pre-declared exchange" do
21
+ ch = connection.create_channel
22
+ q = ch.queue("bunny.tests.queues.client-named#{rand}", :exclusive => true)
23
+ q.should_not be_server_named
24
+
25
+ q.bind("amq.fanout")
26
+ q.unbind("amq.fanout").should be_instance_of(AMQ::Protocol::Queue::UnbindOk)
27
+
28
+ ch.close
29
+ end
30
+
31
+ it "can be bound to a custom exchange" do
32
+ ch = connection.create_channel
33
+ q = ch.queue("bunny.tests.queues.client-named#{rand}", :exclusive => true)
34
+
35
+ x = ch.fanout("bunny.tests.exchanges.fanout#{rand}")
36
+ q.bind(x).should be_instance_of(AMQ::Protocol::Queue::BindOk)
37
+
38
+ x.delete
39
+ ch.close
40
+ end
41
+
42
+ it "can be unbound from a custom exchange" do
43
+ ch = connection.create_channel
44
+ q = ch.queue("bunny.tests.queues.client-named#{rand}", :exclusive => true)
45
+ q.should_not be_server_named
46
+
47
+ x = ch.fanout("bunny.tests.fanout", :auto_delete => true, :durable => false)
48
+
49
+ q.bind(x)
50
+ q.unbind(x).should be_instance_of(AMQ::Protocol::Queue::UnbindOk)
51
+
52
+ ch.close
53
+ end
54
+ end
55
+
56
+
57
+
58
+ describe "A server-named", Bunny::Queue do
59
+ let(:connection) do
60
+ c = Bunny.new
61
+ c.start
62
+ c
63
+ end
64
+
65
+ it "can be bound to a pre-declared exchange" do
66
+ ch = connection.create_channel
67
+ q = ch.queue("", :exclusive => true)
68
+ q.should be_server_named
69
+
70
+ q.bind("amq.fanout").should be_instance_of(AMQ::Protocol::Queue::BindOk)
71
+
72
+ ch.close
73
+ end
74
+
75
+ it "can be unbound from a pre-declared exchange" do
76
+ ch = connection.create_channel
77
+ q = ch.queue("", :exclusive => true)
78
+ q.should be_server_named
79
+
80
+ q.bind("amq.fanout")
81
+ q.unbind("amq.fanout").should be_instance_of(AMQ::Protocol::Queue::UnbindOk)
82
+
83
+ ch.close
84
+ end
85
+
86
+ it "can be bound to a custom exchange" do
87
+ ch = connection.create_channel
88
+ q = ch.queue("", :exclusive => true)
89
+
90
+ x = ch.fanout("bunny.tests.exchanges.fanout#{rand}")
91
+ q.bind(x).should be_instance_of(AMQ::Protocol::Queue::BindOk)
92
+
93
+ x.delete
94
+ ch.close
95
+ end
96
+
97
+ it "can be bound from a custom exchange" do
98
+ ch = connection.create_channel
99
+ q = ch.queue("", :exclusive => true)
100
+
101
+ name = "bunny.tests.exchanges.fanout#{rand}"
102
+ x = ch.fanout(name)
103
+ q.bind(x)
104
+ q.unbind(name).should be_instance_of(AMQ::Protocol::Queue::UnbindOk)
105
+
106
+ x.delete
107
+ ch.close
108
+ end
109
+ end
@@ -0,0 +1,129 @@
1
+ require "spec_helper"
2
+
3
+ describe Bunny::Queue do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
6
+ c.start
7
+ c
8
+ end
9
+
10
+ after :all do
11
+ connection.close if connection.open?
12
+ end
13
+
14
+ context "when queue name is specified" do
15
+ let(:name) { "a queue declared at #{Time.now.to_i}" }
16
+
17
+ it "declares a new queue with that name" do
18
+ ch = connection.create_channel
19
+
20
+ q = ch.queue(name)
21
+ q.name.should == name
22
+
23
+ q.delete
24
+ ch.close
25
+ end
26
+
27
+ it "caches that queue" do
28
+ ch = connection.create_channel
29
+
30
+ q = ch.queue(name)
31
+ ch.queue(name).object_id.should == q.object_id
32
+
33
+ q.delete
34
+ ch.close
35
+ end
36
+ end
37
+
38
+
39
+ context "when queue name is passed on as an empty string" do
40
+ it "uses server-assigned queue name" do
41
+ ch = connection.create_channel
42
+
43
+ q = ch.queue("")
44
+ q.name.should_not be_empty
45
+ q.name.should =~ /^amq.gen.+/
46
+ q.should be_server_named
47
+ q.delete
48
+
49
+ ch.close
50
+ end
51
+ end
52
+
53
+
54
+ context "when queue is declared as durable" do
55
+ it "declares it as durable" do
56
+ ch = connection.create_channel
57
+
58
+ q = ch.queue("bunny.tests.queues.durable", :durable => true)
59
+ q.should be_durable
60
+ q.should_not be_auto_delete
61
+ q.should_not be_exclusive
62
+ q.arguments.should be_nil
63
+ q.delete
64
+
65
+ ch.close
66
+ end
67
+ end
68
+
69
+
70
+ context "when queue is declared as exclusive" do
71
+ it "declares it as exclusive" do
72
+ ch = connection.create_channel
73
+
74
+ q = ch.queue("bunny.tests.queues.exclusive", :exclusive => true)
75
+ q.should be_exclusive
76
+ q.should_not be_durable
77
+ q.delete
78
+
79
+ ch.close
80
+ end
81
+ end
82
+
83
+
84
+ context "when queue is declared as auto-delete" do
85
+ it "declares it as auto-delete" do
86
+ ch = connection.create_channel
87
+
88
+ q = ch.queue("bunny.tests.queues.auto-delete", :auto_delete => true)
89
+ q.should be_auto_delete
90
+ q.should_not be_exclusive
91
+ q.should_not be_durable
92
+ q.delete
93
+
94
+ ch.close
95
+ end
96
+ end
97
+
98
+
99
+ context "when queue is declared with additional arguments (e.g. message TTL)" do
100
+ let(:args) do
101
+ {"x-message-ttl" => 1000}
102
+ end
103
+
104
+ it "declares it with all the arguments provided" do
105
+ ch = connection.create_channel
106
+
107
+ q = ch.queue("bunny.tests.queues.with-arguments", :arguments => args)
108
+ q.arguments.should == args
109
+ q.delete
110
+
111
+ ch.close
112
+ end
113
+ end
114
+
115
+
116
+ context "when queue is declared with a different set of attributes" do
117
+ it "raises an exception" do
118
+ ch = connection.create_channel
119
+
120
+ q = ch.queue("bunny.tests.queues.auto-delete", :auto_delete => true, :durable => false)
121
+ expect {
122
+ # force re-declaration
123
+ ch.queue_declare("bunny.tests.queues.auto-delete", :auto_delete => false, :durable => true)
124
+ }.to raise_error(Bunny::PreconditionFailed)
125
+
126
+ ch.should be_closed
127
+ end
128
+ end
129
+ end