logstash-integration-rabbitmq 7.0.0-java

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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/CONTRIBUTORS +27 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE +13 -0
  6. data/NOTICE.TXT +5 -0
  7. data/README.md +98 -0
  8. data/docs/index.asciidoc +29 -0
  9. data/docs/input-rabbitmq.asciidoc +398 -0
  10. data/docs/output-rabbitmq.asciidoc +272 -0
  11. data/lib/logstash/inputs/rabbitmq.rb +317 -0
  12. data/lib/logstash/outputs/rabbitmq.rb +131 -0
  13. data/lib/logstash/plugin_mixins/rabbitmq_connection.rb +234 -0
  14. data/lib/logstash_registry.rb +7 -0
  15. data/logstash-integration-rabbitmq.gemspec +53 -0
  16. data/spec/fixtures/README.md +150 -0
  17. data/spec/fixtures/client/cert.pem +69 -0
  18. data/spec/fixtures/client/key.pem +27 -0
  19. data/spec/fixtures/client/keycert.p12 +0 -0
  20. data/spec/fixtures/client/req.pem +15 -0
  21. data/spec/fixtures/client_untrusted/cert.pem +19 -0
  22. data/spec/fixtures/client_untrusted/key.pem +28 -0
  23. data/spec/fixtures/client_untrusted/keycert.p12 +0 -0
  24. data/spec/fixtures/server/cert.pem +69 -0
  25. data/spec/fixtures/server/key.pem +27 -0
  26. data/spec/fixtures/server/key_password +1 -0
  27. data/spec/fixtures/server/keycert.p12 +0 -0
  28. data/spec/fixtures/server/rabbitmq.config +10 -0
  29. data/spec/fixtures/server/req.pem +15 -0
  30. data/spec/fixtures/testca/cacert.cer +0 -0
  31. data/spec/fixtures/testca/cacert.pem +17 -0
  32. data/spec/fixtures/testca/certs/01.pem +18 -0
  33. data/spec/fixtures/testca/certs/02.pem +18 -0
  34. data/spec/fixtures/testca/certs/05.pem +69 -0
  35. data/spec/fixtures/testca/certs/06.pem +69 -0
  36. data/spec/fixtures/testca/index.txt +4 -0
  37. data/spec/fixtures/testca/index.txt.attr +1 -0
  38. data/spec/fixtures/testca/index.txt.attr.old +1 -0
  39. data/spec/fixtures/testca/index.txt.old +3 -0
  40. data/spec/fixtures/testca/openssl.cnf +53 -0
  41. data/spec/fixtures/testca/private/cakey.pem +27 -0
  42. data/spec/fixtures/testca/serial +1 -0
  43. data/spec/fixtures/testca/serial.old +1 -0
  44. data/spec/inputs/rabbitmq_spec.rb +279 -0
  45. data/spec/outputs/rabbitmq_spec.rb +232 -0
  46. data/spec/plugin_mixins/rabbitmq_connection_spec.rb +175 -0
  47. metadata +256 -0
@@ -0,0 +1,272 @@
1
+ :plugin: rabbitmq
2
+ :type: output
3
+ :default_codec: json
4
+
5
+ ///////////////////////////////////////////
6
+ START - GENERATED VARIABLES, DO NOT EDIT!
7
+ ///////////////////////////////////////////
8
+ :version: %VERSION%
9
+ :release_date: %RELEASE_DATE%
10
+ :changelog_url: %CHANGELOG_URL%
11
+ :include_path: ../../../../logstash/docs/include
12
+ ///////////////////////////////////////////
13
+ END - GENERATED VARIABLES, DO NOT EDIT!
14
+ ///////////////////////////////////////////
15
+
16
+ [id="plugins-{type}s-{plugin}"]
17
+
18
+ === Rabbitmq output plugin
19
+
20
+ include::{include_path}/plugin_header.asciidoc[]
21
+
22
+ ==== Description
23
+
24
+ Push events to a RabbitMQ exchange. Requires RabbitMQ 2.x
25
+ or later version (3.x is recommended).
26
+
27
+ Relevant links:
28
+
29
+ * http://www.rabbitmq.com/[RabbitMQ]
30
+ * http://rubymarchhare.info[March Hare]
31
+
32
+ [id="plugins-{type}s-{plugin}-options"]
33
+ ==== Rabbitmq Output Configuration Options
34
+
35
+ This plugin supports the following configuration options plus the <<plugins-{type}s-{plugin}-common-options>> described later.
36
+
37
+ [cols="<,<,<",options="header",]
38
+ |=======================================================================
39
+ |Setting |Input type|Required
40
+ | <<plugins-{type}s-{plugin}-arguments>> |<<array,array>>|No
41
+ | <<plugins-{type}s-{plugin}-automatic_recovery>> |<<boolean,boolean>>|No
42
+ | <<plugins-{type}s-{plugin}-connect_retry_interval>> |<<number,number>>|No
43
+ | <<plugins-{type}s-{plugin}-connection_timeout>> |<<number,number>>|No
44
+ | <<plugins-{type}s-{plugin}-durable>> |<<boolean,boolean>>|No
45
+ | <<plugins-{type}s-{plugin}-exchange>> |<<string,string>>|Yes
46
+ | <<plugins-{type}s-{plugin}-exchange_type>> |<<string,string>>, one of `["fanout", "direct", "topic", "x-consistent-hash", "x-modulus-hash"]`|Yes
47
+ | <<plugins-{type}s-{plugin}-heartbeat>> |<<number,number>>|No
48
+ | <<plugins-{type}s-{plugin}-host>> |<<string,string>>|Yes
49
+ | <<plugins-{type}s-{plugin}-key>> |<<string,string>>|No
50
+ | <<plugins-{type}s-{plugin}-message_properties>> |<<hash,hash>>|No
51
+ | <<plugins-{type}s-{plugin}-passive>> |<<boolean,boolean>>|No
52
+ | <<plugins-{type}s-{plugin}-password>> |<<password,password>>|No
53
+ | <<plugins-{type}s-{plugin}-persistent>> |<<boolean,boolean>>|No
54
+ | <<plugins-{type}s-{plugin}-port>> |<<number,number>>|No
55
+ | <<plugins-{type}s-{plugin}-ssl>> |<<boolean,boolean>>|No
56
+ | <<plugins-{type}s-{plugin}-ssl_certificate_password>> |<<string,string>>|No
57
+ | <<plugins-{type}s-{plugin}-ssl_certificate_path>> |a valid filesystem path|No
58
+ | <<plugins-{type}s-{plugin}-ssl_version>> |<<string,string>>|No
59
+ | <<plugins-{type}s-{plugin}-user>> |<<string,string>>|No
60
+ | <<plugins-{type}s-{plugin}-vhost>> |<<string,string>>|No
61
+ |=======================================================================
62
+
63
+ Also see <<plugins-{type}s-{plugin}-common-options>> for a list of options supported by all
64
+ output plugins.
65
+
66
+ &nbsp;
67
+
68
+ [id="plugins-{type}s-{plugin}-arguments"]
69
+ ===== `arguments`
70
+
71
+ * Value type is <<array,array>>
72
+ * Default value is `{}`
73
+
74
+ Extra queue arguments as an array.
75
+ To make a RabbitMQ queue mirrored, use: `{"x-ha-policy" => "all"}`
76
+
77
+ [id="plugins-{type}s-{plugin}-automatic_recovery"]
78
+ ===== `automatic_recovery`
79
+
80
+ * Value type is <<boolean,boolean>>
81
+ * Default value is `true`
82
+
83
+ Set this to automatically recover from a broken connection. You almost certainly don't want to override this!!!
84
+
85
+ [id="plugins-{type}s-{plugin}-connect_retry_interval"]
86
+ ===== `connect_retry_interval`
87
+
88
+ * Value type is <<number,number>>
89
+ * Default value is `1`
90
+
91
+ Time in seconds to wait before retrying a connection
92
+
93
+ [id="plugins-{type}s-{plugin}-connection_timeout"]
94
+ ===== `connection_timeout`
95
+
96
+ * Value type is <<number,number>>
97
+ * There is no default value for this setting.
98
+
99
+ The default connection timeout in milliseconds. If not specified the timeout is infinite.
100
+
101
+ [id="plugins-{type}s-{plugin}-durable"]
102
+ ===== `durable`
103
+
104
+ * Value type is <<boolean,boolean>>
105
+ * Default value is `true`
106
+
107
+ Is this exchange durable? (aka; Should it survive a broker restart?)
108
+
109
+ [id="plugins-{type}s-{plugin}-exchange"]
110
+ ===== `exchange`
111
+
112
+ * This is a required setting.
113
+ * Value type is <<string,string>>
114
+ * There is no default value for this setting.
115
+
116
+ The name of the exchange
117
+
118
+ [id="plugins-{type}s-{plugin}-exchange_type"]
119
+ ===== `exchange_type`
120
+
121
+ * This is a required setting.
122
+ * Value can be any of: `fanout`, `direct`, `topic`, `x-consistent-hash`, `x-modulus-hash`
123
+ * There is no default value for this setting.
124
+
125
+ The exchange type (fanout, topic, direct)
126
+
127
+ [id="plugins-{type}s-{plugin}-heartbeat"]
128
+ ===== `heartbeat`
129
+
130
+ * Value type is <<number,number>>
131
+ * There is no default value for this setting.
132
+
133
+ Heartbeat delay in seconds. If unspecified no heartbeats will be sent
134
+
135
+ [id="plugins-{type}s-{plugin}-host"]
136
+ ===== `host`
137
+
138
+ * This is a required setting.
139
+ * Value type is <<string,string>>
140
+ * There is no default value for this setting.
141
+
142
+ Common functionality for the rabbitmq input/output
143
+ RabbitMQ server address(es)
144
+ host can either be a single host, or a list of hosts
145
+ i.e.
146
+ host => "localhost"
147
+ or
148
+ host => ["host01", "host02]
149
+
150
+ if multiple hosts are provided on the initial connection and any subsequent
151
+ recovery attempts of the hosts is chosen at random and connected to.
152
+ Note that only one host connection is active at a time.
153
+
154
+ [id="plugins-{type}s-{plugin}-key"]
155
+ ===== `key`
156
+
157
+ * Value type is <<string,string>>
158
+ * Default value is `"logstash"`
159
+
160
+ The default codec for this plugin is JSON. You can override this to suit your particular needs however.
161
+ Key to route to by default. Defaults to 'logstash'
162
+
163
+ * Routing keys are ignored on fanout exchanges.
164
+
165
+ [id="plugins-{type}s-{plugin}-message_properties"]
166
+ ===== `message_properties`
167
+
168
+ * Value type is <<hash,hash>>
169
+ * Default value is `{}`
170
+
171
+ Add properties to be set per-message here, such as 'content_type', 'priority'
172
+
173
+ Example:
174
+ [source,ruby]
175
+ message_properties => {
176
+ "content_type" => "application/json"
177
+ "priority" => 1
178
+ }
179
+
180
+
181
+ [id="plugins-{type}s-{plugin}-passive"]
182
+ ===== `passive`
183
+
184
+ * Value type is <<boolean,boolean>>
185
+ * Default value is `false`
186
+
187
+ Passive queue creation? Useful for checking queue existance without modifying server state
188
+
189
+ [id="plugins-{type}s-{plugin}-password"]
190
+ ===== `password`
191
+
192
+ * Value type is <<password,password>>
193
+ * Default value is `"guest"`
194
+
195
+ RabbitMQ password
196
+
197
+ [id="plugins-{type}s-{plugin}-persistent"]
198
+ ===== `persistent`
199
+
200
+ * Value type is <<boolean,boolean>>
201
+ * Default value is `true`
202
+
203
+ Should RabbitMQ persist messages to disk?
204
+
205
+ [id="plugins-{type}s-{plugin}-port"]
206
+ ===== `port`
207
+
208
+ * Value type is <<number,number>>
209
+ * Default value is `5672`
210
+
211
+ RabbitMQ port to connect on
212
+
213
+ [id="plugins-{type}s-{plugin}-ssl"]
214
+ ===== `ssl`
215
+
216
+ * Value type is <<boolean,boolean>>
217
+ * There is no default value for this setting.
218
+
219
+ Enable or disable SSL.
220
+ Note that by default remote certificate verification is off.
221
+ Specify ssl_certificate_path and ssl_certificate_password if you need
222
+ certificate verification
223
+
224
+ [id="plugins-{type}s-{plugin}-ssl_certificate_password"]
225
+ ===== `ssl_certificate_password`
226
+
227
+ * Value type is <<string,string>>
228
+ * There is no default value for this setting.
229
+
230
+ Password for the encrypted PKCS12 (.p12) certificate file specified in ssl_certificate_path
231
+
232
+ [id="plugins-{type}s-{plugin}-ssl_certificate_path"]
233
+ ===== `ssl_certificate_path`
234
+
235
+ * Value type is <<path,path>>
236
+ * There is no default value for this setting.
237
+
238
+ Path to an SSL certificate in PKCS12 (.p12) format used for verifying the remote host
239
+
240
+ [id="plugins-{type}s-{plugin}-ssl_version"]
241
+ ===== `ssl_version`
242
+
243
+ * Value type is <<string,string>>
244
+ * Default value is `"TLSv1.2"`
245
+
246
+ Version of the SSL protocol to use.
247
+
248
+ [id="plugins-{type}s-{plugin}-user"]
249
+ ===== `user`
250
+
251
+ * Value type is <<string,string>>
252
+ * Default value is `"guest"`
253
+
254
+ RabbitMQ username
255
+
256
+ [id="plugins-{type}s-{plugin}-vhost"]
257
+ ===== `vhost`
258
+
259
+ * Value type is <<string,string>>
260
+ * Default value is `"/"`
261
+
262
+ The vhost (virtual host) to use. If you don't know what this
263
+ is, leave the default. With the exception of the default
264
+ vhost ("/"), names of vhosts should not begin with a forward
265
+ slash.
266
+
267
+
268
+
269
+ [id="plugins-{type}s-{plugin}-common-options"]
270
+ include::{include_path}/{type}.asciidoc[]
271
+
272
+ :default_codec!:
@@ -0,0 +1,317 @@
1
+ # encoding: utf-8
2
+ require_relative '../plugin_mixins/rabbitmq_connection'
3
+ require 'logstash/inputs/threadable'
4
+ require 'logstash/event'
5
+ java_import java.util.concurrent.ArrayBlockingQueue
6
+ java_import java.util.concurrent.TimeUnit
7
+
8
+ module LogStash
9
+ module Inputs
10
+ # Pull events from a http://www.rabbitmq.com/[RabbitMQ] queue.
11
+ #
12
+ # The default settings will create an entirely transient queue and listen for all messages by default.
13
+ # If you need durability or any other advanced settings, please set the appropriate options
14
+ #
15
+ # This plugin uses the http://rubymarchhare.info/[March Hare] library
16
+ # for interacting with the RabbitMQ server. Most configuration options
17
+ # map directly to standard RabbitMQ and AMQP concepts. The
18
+ # https://www.rabbitmq.com/amqp-0-9-1-reference.html[AMQP 0-9-1 reference guide]
19
+ # and other parts of the RabbitMQ documentation are useful for deeper
20
+ # understanding.
21
+ #
22
+ # The properties of messages received will be stored in the
23
+ # `[@metadata][rabbitmq_properties]` field if the `@metadata_enabled` setting is checked.
24
+ # Note that storing metadata may degrade performance.
25
+ # The following properties may be available (in most cases dependent on whether
26
+ # they were set by the sender):
27
+ #
28
+ # * app-id
29
+ # * cluster-id
30
+ # * consumer-tag
31
+ # * content-encoding
32
+ # * content-type
33
+ # * correlation-id
34
+ # * delivery-mode
35
+ # * exchange
36
+ # * expiration
37
+ # * message-id
38
+ # * priority
39
+ # * redeliver
40
+ # * reply-to
41
+ # * routing-key
42
+ # * timestamp
43
+ # * type
44
+ # * user-id
45
+ #
46
+ # For example, to get the RabbitMQ message's timestamp property
47
+ # into the Logstash event's `@timestamp` field, use the date
48
+ # filter to parse the `[@metadata][rabbitmq_properties][timestamp]`
49
+ # field:
50
+ # [source,ruby]
51
+ # filter {
52
+ # if [@metadata][rabbitmq_properties][timestamp] {
53
+ # date {
54
+ # match => ["[@metadata][rabbitmq_properties][timestamp]", "UNIX"]
55
+ # }
56
+ # }
57
+ # }
58
+ #
59
+ # Additionally, any message headers will be saved in the
60
+ # `[@metadata][rabbitmq_headers]` field.
61
+ class RabbitMQ < LogStash::Inputs::Threadable
62
+ include ::LogStash::PluginMixins::RabbitMQConnection
63
+
64
+ # The properties to extract from each message and store in a
65
+ # @metadata field.
66
+ #
67
+ # Technically the exchange, redeliver, and routing-key
68
+ # properties belong to the envelope and not the message but we
69
+ # ignore that distinction here. However, we extract the
70
+ # headers separately via get_headers even though the header
71
+ # table technically is a message property.
72
+ #
73
+ # Freezing all strings so that code modifying the event's
74
+ # @metadata field can't touch them.
75
+ #
76
+ # If updating this list, remember to update the documentation
77
+ # above too.
78
+ MESSAGE_PROPERTIES = [
79
+ "app-id",
80
+ "cluster-id",
81
+ "consumer-tag",
82
+ "content-encoding",
83
+ "content-type",
84
+ "correlation-id",
85
+ "delivery-mode",
86
+ "exchange",
87
+ "expiration",
88
+ "message-id",
89
+ "priority",
90
+ "redeliver",
91
+ "reply-to",
92
+ "routing-key",
93
+ "timestamp",
94
+ "type",
95
+ "user-id",
96
+ ].map { |s| s.freeze }.freeze
97
+
98
+ INTERNAL_QUEUE_POISON=[]
99
+
100
+ config_name "rabbitmq"
101
+
102
+ # The default codec for this plugin is JSON. You can override this to suit your particular needs however.
103
+ default :codec, "json"
104
+
105
+ # The name of the queue Logstash will consume events from. If
106
+ # left empty, a transient queue with an randomly chosen name
107
+ # will be created.
108
+ config :queue, :validate => :string, :default => ""
109
+
110
+ # Is this queue durable? (aka; Should it survive a broker restart?)
111
+ config :durable, :validate => :boolean, :default => false
112
+
113
+ # Should the queue be deleted on the broker when the last consumer
114
+ # disconnects? Set this option to `false` if you want the queue to remain
115
+ # on the broker, queueing up messages until a consumer comes along to
116
+ # consume them.
117
+ config :auto_delete, :validate => :boolean, :default => false
118
+
119
+ # Is the queue exclusive? Exclusive queues can only be used by the connection
120
+ # that declared them and will be deleted when it is closed (e.g. due to a Logstash
121
+ # restart).
122
+ config :exclusive, :validate => :boolean, :default => false
123
+
124
+ # Extra queue arguments as an array.
125
+ # To make a RabbitMQ queue mirrored, use: `{"x-ha-policy" => "all"}`
126
+ config :arguments, :validate => :array, :default => {}
127
+
128
+ # Prefetch count. If acknowledgements are enabled with the `ack`
129
+ # option, specifies the number of outstanding unacknowledged
130
+ # messages allowed.
131
+ config :prefetch_count, :validate => :number, :default => 256
132
+
133
+ # Enable message acknowledgements. With acknowledgements
134
+ # messages fetched by Logstash but not yet sent into the
135
+ # Logstash pipeline will be requeued by the server if Logstash
136
+ # shuts down. Acknowledgements will however hurt the message
137
+ # throughput.
138
+ #
139
+ # This will only send an ack back every `prefetch_count` messages.
140
+ # Working in batches provides a performance boost here.
141
+ config :ack, :validate => :boolean, :default => true
142
+
143
+ # If true the queue will be passively declared, meaning it must
144
+ # already exist on the server. To have Logstash create the queue
145
+ # if necessary leave this option as false. If actively declaring
146
+ # a queue that already exists, the queue options for this plugin
147
+ # (durable etc) must match those of the existing queue.
148
+ config :passive, :validate => :boolean, :default => false
149
+
150
+ # The name of the exchange to bind the queue to. Specify `exchange_type`
151
+ # as well to declare the exchange if it does not exist
152
+ config :exchange, :validate => :string
153
+
154
+ # The type of the exchange to bind to. Specifying this will cause this plugin
155
+ # to declare the exchange if it does not exist.
156
+ config :exchange_type, :validate => :string
157
+
158
+ # The routing key to use when binding a queue to the exchange.
159
+ # This is only relevant for direct or topic exchanges.
160
+ #
161
+ # * Routing keys are ignored on fanout exchanges.
162
+ # * Wildcards are not valid on direct exchanges.
163
+ config :key, :validate => :string, :default => "logstash"
164
+
165
+ # Amount of time in seconds to wait after a failed subscription request
166
+ # before retrying. Subscribes can fail if the server goes away and then comes back.
167
+ config :subscription_retry_interval_seconds, :validate => :number, :required => true, :default => 5
168
+
169
+ # Enable the storage of message headers and properties in `@metadata`. This may impact performance
170
+ config :metadata_enabled, :validate => :boolean, :default => false
171
+
172
+ def register
173
+ @internal_queue = java.util.concurrent.ArrayBlockingQueue.new(@prefetch_count*2)
174
+ end
175
+
176
+ def run(output_queue)
177
+ setup!
178
+ @output_queue = output_queue
179
+ consume!
180
+ end
181
+
182
+ def setup!
183
+ connect!
184
+ declare_queue!
185
+ bind_exchange!
186
+ @hare_info.channel.prefetch = @prefetch_count
187
+ rescue => e
188
+ @logger.warn("Error while setting up connection for rabbitmq input! Will retry.",
189
+ :message => e.message,
190
+ :class => e.class.name,
191
+ :location => e.backtrace.first)
192
+ sleep_for_retry
193
+ retry
194
+ end
195
+
196
+ def bind_exchange!
197
+ if @exchange
198
+ if @exchange_type # Only declare the exchange if @exchange_type is set!
199
+ @logger.info? && @logger.info("Declaring exchange '#{@exchange}' with type #{@exchange_type}")
200
+ @hare_info.exchange = declare_exchange!(@hare_info.channel, @exchange, @exchange_type, @durable)
201
+ end
202
+ @hare_info.queue.bind(@exchange, :routing_key => @key)
203
+ end
204
+ end
205
+
206
+ def declare_queue!
207
+ @hare_info.queue = declare_queue()
208
+ end
209
+
210
+ def declare_queue
211
+ @hare_info.channel.queue(@queue,
212
+ :durable => @durable,
213
+ :auto_delete => @auto_delete,
214
+ :exclusive => @exclusive,
215
+ :passive => @passive,
216
+ :arguments => @arguments)
217
+ end
218
+
219
+ def consume!
220
+ @consumer = @hare_info.queue.build_consumer(:on_cancellation => Proc.new { on_cancellation }) do |metadata, data|
221
+ @internal_queue.put [metadata, data]
222
+ end
223
+
224
+ begin
225
+ @hare_info.queue.subscribe_with(@consumer, :manual_ack => @ack)
226
+ rescue MarchHare::Exception => e
227
+ @logger.warn("Could not subscribe to queue! Will retry in #{@subscription_retry_interval_seconds} seconds", :queue => @queue)
228
+
229
+ sleep @subscription_retry_interval_seconds
230
+ retry
231
+ end
232
+
233
+ internal_queue_consume!
234
+ end
235
+
236
+ def internal_queue_consume!
237
+ i=0
238
+ last_delivery_tag=nil
239
+ while true
240
+ payload = @internal_queue.poll(10, TimeUnit::MILLISECONDS)
241
+ if !payload # Nothing in the queue
242
+ if last_delivery_tag # And we have unacked stuff
243
+ @hare_info.channel.ack(last_delivery_tag, true) if @ack
244
+ i=0
245
+ last_delivery_tag = nil
246
+ end
247
+ next
248
+ end
249
+
250
+ break if payload == INTERNAL_QUEUE_POISON
251
+
252
+ metadata, data = payload
253
+ @codec.decode(data) do |event|
254
+ decorate(event)
255
+ if @metadata_enabled
256
+ event.set("[@metadata][rabbitmq_headers]", get_headers(metadata))
257
+ event.set("[@metadata][rabbitmq_properties]", get_properties(metadata))
258
+ end
259
+ @output_queue << event if event
260
+ end
261
+
262
+ i += 1
263
+
264
+ if i >= @prefetch_count
265
+ @hare_info.channel.ack(metadata.delivery_tag, true) if @ack
266
+ i = 0
267
+ last_delivery_tag = nil
268
+ else
269
+ last_delivery_tag = metadata.delivery_tag
270
+ end
271
+ end
272
+ end
273
+
274
+ def stop
275
+ @internal_queue.put(INTERNAL_QUEUE_POISON)
276
+ shutdown_consumer
277
+ close_connection
278
+ end
279
+
280
+ def shutdown_consumer
281
+ return unless @consumer
282
+ @hare_info.channel.basic_cancel(@consumer.consumer_tag)
283
+ until @consumer.terminated?
284
+ @logger.info("Waiting for rabbitmq consumer to terminate before stopping!", :params => self.params)
285
+ sleep 1
286
+ end
287
+ end
288
+
289
+ def on_cancellation
290
+ if !stop? # If this isn't already part of a regular stop
291
+ @logger.info("Received basic.cancel from #{rabbitmq_settings[:host]}, shutting down.")
292
+ stop
293
+ end
294
+ end
295
+
296
+ private
297
+ def get_headers(metadata)
298
+ metadata.headers || {}
299
+ end
300
+
301
+ private
302
+ def get_properties(metadata)
303
+ MESSAGE_PROPERTIES.reduce({}) do |acc, name|
304
+ # The method names obviously can't contain hyphens.
305
+ value = metadata.send(name.gsub("-", "_"))
306
+ if value
307
+ # The AMQP 0.9.1 timestamp field only has second resolution
308
+ # so storing milliseconds serves no purpose and might give
309
+ # the incorrect impression of a higher resolution.
310
+ acc[name] = name != "timestamp" ? value : value.getTime / 1000
311
+ end
312
+ acc
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end