bunny 0.8.0 → 0.9.0.pre1

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