rabbitmq 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/ext/rabbitmq/Rakefile +14 -9
  4. data/lib/rabbitmq/connection/channel_manager.rb +61 -0
  5. data/lib/rabbitmq/connection/event_manager.rb +55 -0
  6. data/lib/rabbitmq/connection/transport.rb +157 -0
  7. data/lib/rabbitmq/ffi.rb +4 -356
  8. data/lib/rabbitmq/ffi/ext.rb +12 -299
  9. data/lib/rabbitmq/ffi/ext/basic_properties.rb +57 -0
  10. data/lib/rabbitmq/ffi/ext/bytes.rb +29 -0
  11. data/lib/rabbitmq/ffi/ext/connection_info.rb +12 -0
  12. data/lib/rabbitmq/ffi/ext/field_value.rb +49 -0
  13. data/lib/rabbitmq/ffi/ext/frame.rb +43 -0
  14. data/lib/rabbitmq/ffi/ext/frame_payload_properties.rb +12 -0
  15. data/lib/rabbitmq/ffi/ext/method.rb +49 -0
  16. data/lib/rabbitmq/ffi/ext/table.rb +51 -0
  17. data/lib/rabbitmq/ffi/ext/timeval.rb +18 -0
  18. data/lib/rabbitmq/ffi/gen.rb +65 -0
  19. data/lib/rabbitmq/ffi/gen/access_request.rb +49 -0
  20. data/lib/rabbitmq/ffi/gen/access_request_ok.rb +29 -0
  21. data/lib/rabbitmq/ffi/gen/basic_ack.rb +36 -0
  22. data/lib/rabbitmq/ffi/gen/basic_cancel.rb +37 -0
  23. data/lib/rabbitmq/ffi/gen/basic_cancel_ok.rb +30 -0
  24. data/lib/rabbitmq/ffi/gen/basic_consume.rb +57 -0
  25. data/lib/rabbitmq/ffi/gen/basic_consume_ok.rb +30 -0
  26. data/lib/rabbitmq/ffi/gen/basic_deliver.rb +48 -0
  27. data/lib/rabbitmq/ffi/gen/basic_get.rb +40 -0
  28. data/lib/rabbitmq/ffi/gen/basic_get_empty.rb +30 -0
  29. data/lib/rabbitmq/ffi/gen/basic_get_ok.rb +47 -0
  30. data/lib/rabbitmq/ffi/gen/basic_nack.rb +39 -0
  31. data/lib/rabbitmq/ffi/gen/basic_publish.rb +47 -0
  32. data/lib/rabbitmq/ffi/gen/basic_qos.rb +39 -0
  33. data/lib/rabbitmq/ffi/gen/basic_qos_ok.rb +28 -0
  34. data/lib/rabbitmq/ffi/gen/basic_recover.rb +29 -0
  35. data/lib/rabbitmq/ffi/gen/basic_recover_async.rb +29 -0
  36. data/lib/rabbitmq/ffi/gen/basic_recover_ok.rb +28 -0
  37. data/lib/rabbitmq/ffi/gen/basic_reject.rb +36 -0
  38. data/lib/rabbitmq/ffi/gen/basic_return.rb +45 -0
  39. data/lib/rabbitmq/ffi/gen/channel_close.rb +45 -0
  40. data/lib/rabbitmq/ffi/gen/channel_close_ok.rb +28 -0
  41. data/lib/rabbitmq/ffi/gen/channel_flow.rb +29 -0
  42. data/lib/rabbitmq/ffi/gen/channel_flow_ok.rb +29 -0
  43. data/lib/rabbitmq/ffi/gen/channel_open.rb +30 -0
  44. data/lib/rabbitmq/ffi/gen/channel_open_ok.rb +30 -0
  45. data/lib/rabbitmq/ffi/gen/confirm_select.rb +29 -0
  46. data/lib/rabbitmq/ffi/gen/confirm_select_ok.rb +28 -0
  47. data/lib/rabbitmq/ffi/gen/connection_blocked.rb +30 -0
  48. data/lib/rabbitmq/ffi/gen/connection_close.rb +45 -0
  49. data/lib/rabbitmq/ffi/gen/connection_close_ok.rb +28 -0
  50. data/lib/rabbitmq/ffi/gen/connection_open.rb +41 -0
  51. data/lib/rabbitmq/ffi/gen/connection_open_ok.rb +30 -0
  52. data/lib/rabbitmq/ffi/gen/connection_secure.rb +30 -0
  53. data/lib/rabbitmq/ffi/gen/connection_secure_ok.rb +30 -0
  54. data/lib/rabbitmq/ffi/gen/connection_start.rb +48 -0
  55. data/lib/rabbitmq/ffi/gen/connection_start_ok.rb +46 -0
  56. data/lib/rabbitmq/ffi/gen/connection_tune.rb +39 -0
  57. data/lib/rabbitmq/ffi/gen/connection_tune_ok.rb +39 -0
  58. data/lib/rabbitmq/ffi/gen/connection_unblocked.rb +28 -0
  59. data/lib/rabbitmq/ffi/gen/exchange_bind.rb +52 -0
  60. data/lib/rabbitmq/ffi/gen/exchange_bind_ok.rb +28 -0
  61. data/lib/rabbitmq/ffi/gen/exchange_declare.rb +60 -0
  62. data/lib/rabbitmq/ffi/gen/exchange_declare_ok.rb +28 -0
  63. data/lib/rabbitmq/ffi/gen/exchange_delete.rb +43 -0
  64. data/lib/rabbitmq/ffi/gen/exchange_delete_ok.rb +28 -0
  65. data/lib/rabbitmq/ffi/gen/exchange_unbind.rb +52 -0
  66. data/lib/rabbitmq/ffi/gen/exchange_unbind_ok.rb +28 -0
  67. data/lib/rabbitmq/ffi/gen/queue_bind.rb +52 -0
  68. data/lib/rabbitmq/ffi/gen/queue_bind_ok.rb +28 -0
  69. data/lib/rabbitmq/ffi/gen/queue_declare.rb +56 -0
  70. data/lib/rabbitmq/ffi/gen/queue_declare_ok.rb +40 -0
  71. data/lib/rabbitmq/ffi/gen/queue_delete.rb +46 -0
  72. data/lib/rabbitmq/ffi/gen/queue_delete_ok.rb +29 -0
  73. data/lib/rabbitmq/ffi/gen/queue_purge.rb +40 -0
  74. data/lib/rabbitmq/ffi/gen/queue_purge_ok.rb +29 -0
  75. data/lib/rabbitmq/ffi/gen/queue_unbind.rb +49 -0
  76. data/lib/rabbitmq/ffi/gen/queue_unbind_ok.rb +28 -0
  77. data/lib/rabbitmq/ffi/gen/tx_commit.rb +28 -0
  78. data/lib/rabbitmq/ffi/gen/tx_commit_ok.rb +28 -0
  79. data/lib/rabbitmq/ffi/gen/tx_rollback.rb +28 -0
  80. data/lib/rabbitmq/ffi/gen/tx_rollback_ok.rb +28 -0
  81. data/lib/rabbitmq/ffi/gen/tx_select.rb +28 -0
  82. data/lib/rabbitmq/ffi/gen/tx_select_ok.rb +28 -0
  83. metadata +79 -2
@@ -1,300 +1,13 @@
1
1
 
2
- module RabbitMQ
3
- module FFI
4
-
5
- class Timeval
6
- def self.from(seconds)
7
- obj = new
8
- obj[:tv_sec] = seconds.to_i
9
- obj[:tv_usec] = (seconds * 1_000_000).to_i
10
- obj
11
- end
12
-
13
- @zero = self.from(0)
14
- class << self; attr_reader :zero; end
15
- end
16
-
17
- class ConnectionInfo
18
- def to_h
19
- members.map { |k| [k, self[k]] }.to_h
20
- end
21
- end
22
-
23
- class Bytes
24
- def to_s(free=false)
25
- size = self[:len]
26
- s = size == 0 ? "" : self[:bytes].read_bytes(size)
27
- free! if free
28
- s
29
- end
30
-
31
- def free!
32
- FFI.free(self[:bytes])
33
- clear
34
- end
35
-
36
- def self.from_s(str)
37
- size = str.bytesize
38
- bytes = FFI.amqp_bytes_malloc(size)
39
-
40
- bytes[:bytes].write_string(str)
41
- bytes[:len] = size
42
- bytes
43
- end
44
- end
45
-
46
- class FieldValue
47
- private def value_member(kind)
48
- case kind
49
- when :utf8; :bytes
50
- when :timestamp; :u64
51
- else kind
52
- end
53
- end
54
-
55
- def to_value(free=false)
56
- kind = self[:kind]
57
- value = self[:value][value_member(kind)]
58
- result = case kind
59
- when :bytes; value.to_s(free)
60
- when :utf8; value.to_s(free).force_encoding(Encoding::UTF_8)
61
- when :timestamp; Time.at(value / 1000.0)
62
- when :table; value.to_h(free)
63
- when :array; value.to_array_not_yet_implemented!
64
- when :decimal; value.to_value_not_yet_implemented!
65
- else value
66
- end
67
-
68
- clear if free
69
- result
70
- end
71
-
72
- def free!
73
- kind = self[:kind]
74
- value = self[:value][value_member(kind)]
75
- value.free! if value.respond_to? :free!
76
- clear
77
- end
78
-
79
- def self.from(value)
80
- obj = new
81
- obj[:kind], obj[:value] = case value
82
- when String; [:bytes, FieldValueValue.new(Bytes.from_s(value).pointer)]
83
- else raise NotImplementedError
84
- end
85
- obj
86
- end
87
- end
88
-
89
- class Table
90
- include Enumerable
91
-
92
- def each(*a, &b)
93
- entry_ptr = self[:entries]
94
- entries = self[:num_entries].times.map do |i|
95
- FFI::TableEntry.new(entry_ptr + i * FFI::TableEntry.size)
96
- end
97
- entries.each(*a, &b)
98
- end
99
-
100
- def to_h(free=false)
101
- result = self.map do |entry|
102
- [entry[:key].to_s(free), entry[:value].to_value(free)]
103
- end.to_h
104
-
105
- clear if free
106
- result
107
- end
108
-
109
- def free!
110
- self.each do
111
- entry[:key].free!
112
- entry[:value].free!
113
- end
114
- FFI.free(self[:entries])
115
- clear
116
- end
117
-
118
- def self.from(params)
119
- size = params.size
120
- entry_ptr = Util.mem_ptr(size * FFI::TableEntry.size, release: false)
121
- params.each_with_index do |param, idx|
122
- entry = FFI::TableEntry.new(entry_ptr + idx * FFI::TableEntry.size)
123
- entry[:key] = FFI::Bytes.from_s(param.first.to_s)
124
- entry[:value] = FFI::FieldValue.from(param.last)
125
- end
126
-
127
- obj = new
128
- obj[:num_entries] = size
129
- obj[:entries] = entry_ptr
130
- obj
131
- end
132
- end
133
-
134
- class Method
135
- MethodClasses = FFI::MethodNumber.symbols.map do |name|
136
- const_name = name.to_s.gsub(/((?:\A\w)|(?:_\w))/) { |x| x[-1].upcase }
137
- [name, FFI.const_get(const_name)]
138
- end.to_h.freeze
139
-
140
- MethodNames = MethodClasses.to_a.map(&:reverse).to_h.freeze
141
-
142
- def to_h(free=false)
143
- { method: self[:id],
144
- properties: self.decoded.to_h(free) }
145
- end
146
-
147
- def decoded
148
- MethodClasses.fetch(self[:id]).new(self[:decoded])
149
- end
150
-
151
- def self.lookup(kls)
152
- MethodNames.fetch(kls)
153
- end
154
-
155
- def self.lookup_class(name)
156
- MethodClasses.fetch(name)
157
- end
158
-
159
- def self.from(decoded)
160
- obj = new
161
- obj[:id] = lookup(decoded.class)
162
- obj[:decoded] = decoded.pointer
163
- obj
164
- end
165
-
166
- def self.has_content?(type)
167
- case type
168
- when :basic_publish; true
169
- when :basic_return; true
170
- when :basic_deliver; true
171
- when :basic_get_ok; true
172
- else false
173
- end
174
- end
175
- end
176
-
177
- module MethodClassMixin
178
- def apply(**params)
179
- params.each do |key, value|
180
- next if value.nil? || !writable_key?(key)
181
- case value
182
- when String; value = FFI::Bytes.from_s(value)
183
- when Hash; value = FFI::Table.from(value)
184
- end
185
- key_applied_hook(key)
186
- self[key] = value
187
- end
188
- self
189
- end
190
-
191
- def to_h(free=false)
192
- result = {}
193
- self.members.each do |key| [key, self[key]]
194
- next unless readable_key?(key)
195
- value = self[key]
196
- case value
197
- when FFI::Bytes; value = value.to_s(free)
198
- when FFI::Table; value = value.to_h(free)
199
- end
200
- result[key] = value
201
- end
202
-
203
- # TODO: handle the inverse case of this transformation in apply method
204
- if (method_id = result.delete(:method_id))
205
- method_num = (result.delete(:class_id) << 16) + method_id
206
- result[:method] = FFI::MethodNumber[method_num]
207
- end
208
-
209
- clear if free
210
- result
211
- end
212
-
213
- def free!
214
- self.values.each do |item|
215
- item.free! if item.respond_to? :free!
216
- end
217
- clear
218
- end
219
-
220
- def key_applied_hook(key)
221
- # do nothing here
222
- end
223
-
224
- def readable_key?(key)
225
- key != :dummy
226
- end
227
-
228
- def writable_key?(key)
229
- key != :dummy
230
- end
231
- end
232
-
233
- Method::MethodClasses.each { |_, kls| kls.send(:include, MethodClassMixin) }
234
-
235
- BasicProperties.send(:include, MethodClassMixin)
236
-
237
- class BasicProperties
238
- def key_applied_hook(key)
239
- flag_bit = FLAGS[key]
240
- return unless flag_bit
241
- self[:_flags] = (self[:_flags] | flag_bit)
242
- end
243
-
244
- def readable_key?(key)
245
- return false if key == :_flags
246
- flag_bit = FLAGS[key]
247
- return true unless flag_bit
248
- return (flag_bit & self[:_flags]) != 0
249
- end
250
-
251
- def writable_key?(key)
252
- true
253
- end
254
- end
255
-
256
- class FramePayloadProperties
257
- def decoded
258
- BasicProperties.new(self[:decoded])
259
- end
260
- end
261
-
262
- class Frame
263
- def payload
264
- member = case self[:frame_type]
265
- when :method; :method
266
- when :header; :properties
267
- when :body; :body_fragment
268
- else; raise NotImplementedError, "frame type: #{self[:frame_type]}"
269
- end
270
- self[:payload][member]
271
- end
272
-
273
- def as_method_to_h(free=false)
274
- # TODO: raise correct error class with enough info for appropriate action
275
- raise "Wrong frame type for method frame of event: #{self[:frame_type]}" \
276
- unless self[:frame_type] == :method
277
-
278
- payload.to_h(free).merge(channel: self[:channel])
279
- end
280
-
281
- def as_header_to_h(free=false)
282
- # TODO: raise correct error class with enough info for appropriate action
283
- raise "Wrong frame type for header frame of multiframe event: #{self[:frame_type]}" \
284
- unless self[:frame_type] == :header
285
-
286
- properties = self[:payload][:properties]
287
- { header: properties.decoded.to_h(free), body_size: properties[:body_size] }
288
- end
289
-
290
- def as_body_to_s(free=false)
291
- # TODO: raise correct error class with enough info for appropriate action
292
- raise "Wrong frame type for body frame of multiframe event: #{self[:frame_type]}" \
293
- unless self[:frame_type] == :body
294
-
295
- self[:payload][:body_fragment].to_s(free)
296
- end
297
- end
298
-
299
- end
300
- end
2
+ require_relative 'ext/timeval'
3
+ require_relative 'ext/bytes'
4
+
5
+ require_relative 'ext/connection_info'
6
+ require_relative 'ext/field_value'
7
+ require_relative 'ext/table'
8
+
9
+ require_relative 'ext/method'
10
+ require_relative 'ext/basic_properties'
11
+ require_relative 'ext/frame_payload_properties'
12
+
13
+ require_relative 'ext/frame'
@@ -0,0 +1,57 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class BasicProperties
6
+ def apply(**params)
7
+ params.each do |key, value|
8
+ next if value.nil?
9
+ case value
10
+ when String; value = FFI::Bytes.from_s(value)
11
+ when Hash; value = FFI::Table.from(value)
12
+ end
13
+ set_flag_for_key(key)
14
+ self[key] = value
15
+ end
16
+ self
17
+ end
18
+
19
+ def to_h(free=false)
20
+ result = {}
21
+ self.members.each do |key| [key, self[key]]
22
+ next unless flag_for_key?(key)
23
+ value = self[key]
24
+ case value
25
+ when FFI::Bytes; value = value.to_s(free)
26
+ when FFI::Table; value = value.to_h(free)
27
+ end
28
+ result[key] = value
29
+ end
30
+
31
+ clear if free
32
+ result
33
+ end
34
+
35
+ def free!
36
+ self.values.each do |item|
37
+ item.free! if item.respond_to? :free!
38
+ end
39
+ clear
40
+ end
41
+
42
+ def set_flag_for_key(key)
43
+ flag_bit = FLAGS[key]
44
+ return unless flag_bit
45
+ self[:_flags] = (self[:_flags] | flag_bit)
46
+ end
47
+
48
+ def flag_for_key?(key)
49
+ return false if key == :_flags
50
+ flag_bit = FLAGS[key]
51
+ return true unless flag_bit
52
+ return (flag_bit & self[:_flags]) != 0
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,29 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class Bytes
6
+ def to_s(free=false)
7
+ size = self[:len]
8
+ s = size == 0 ? "" : self[:bytes].read_bytes(size)
9
+ free! if free
10
+ s
11
+ end
12
+
13
+ def free!
14
+ FFI.free(self[:bytes])
15
+ clear
16
+ end
17
+
18
+ def self.from_s(str)
19
+ size = str.bytesize
20
+ bytes = FFI.amqp_bytes_malloc(size)
21
+
22
+ bytes[:bytes].write_string(str)
23
+ bytes[:len] = size
24
+ bytes
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class ConnectionInfo
6
+ def to_h
7
+ members.zip(values).to_h
8
+ end
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,49 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class FieldValue
6
+ private def value_member(kind)
7
+ case kind
8
+ when :utf8; :bytes
9
+ when :timestamp; :u64
10
+ else kind
11
+ end
12
+ end
13
+
14
+ def to_value(free=false)
15
+ kind = self[:kind]
16
+ value = self[:value][value_member(kind)]
17
+ result = case kind
18
+ when :bytes; value.to_s(free)
19
+ when :utf8; value.to_s(free).force_encoding(Encoding::UTF_8)
20
+ when :timestamp; Time.at(value / 1000.0)
21
+ when :table; value.to_h(free)
22
+ when :array; value.to_array_not_yet_implemented!
23
+ when :decimal; value.to_value_not_yet_implemented!
24
+ else value
25
+ end
26
+
27
+ clear if free
28
+ result
29
+ end
30
+
31
+ def free!
32
+ kind = self[:kind]
33
+ value = self[:value][value_member(kind)]
34
+ value.free! if value.respond_to? :free!
35
+ clear
36
+ end
37
+
38
+ def self.from(value)
39
+ obj = new
40
+ obj[:kind], obj[:value] = case value
41
+ when String; [:bytes, FieldValueValue.new(Bytes.from_s(value).pointer)]
42
+ else raise NotImplementedError
43
+ end
44
+ obj
45
+ end
46
+ end
47
+
48
+ end
49
+ end