rt-tackle 0.9 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b51e7b8dd21855f3c3a88d9da4be12c54a715d69
4
- data.tar.gz: b4efab4ce923c03a8891099568192400ca085db4
3
+ metadata.gz: de0f2580c2937c203f50d01d0a8e7a66c8ad4cbe
4
+ data.tar.gz: 249a5fabc8c8dc812a69d8541ae3ab7c8e046d3e
5
5
  SHA512:
6
- metadata.gz: 37f17e2b31c9b00c927dd3611ddc24b95b82e348f8ae33534b29df4bdc275507cc63b04df991ba26b42ae13f58f366e00e4771c06d8b3cc684b92e5d86623c69
7
- data.tar.gz: 3e6743290efe3377fe2842c9930ffe86b5322e3ac7247d24860560cb5efaed2914936bdfb32c603ca888c94107a989e4d673d61def947ee95b94c3112711dc92
6
+ metadata.gz: 784cb5cfec47ace9f60d6ddabdb5b7d117f31e76cba8c38b6960b318ca73cca851ec39f5d84c16f64df9485db5b63b24db467c83f89e155e80aab007a8712b3b
7
+ data.tar.gz: 099fac7e24bc267a4c6556e1706c46fde7d823a007215b66e5842d077add917b48d8830d2b75aa50d0efb69a946b31fa1a7e11bdc765db90e3f3a7b5ac40ddc8
data/README.md CHANGED
@@ -125,69 +125,6 @@ Tackle.consume(options) do |message|
125
125
  end
126
126
  ```
127
127
 
128
- ### [DEPRECATED] Subscribe to an exchange
129
-
130
- **Deprecation notice:** For newer projects please use `Tackle.consume`.
131
-
132
- To consume messages from an exchange, do the following:
133
-
134
- ```ruby
135
- require "tackle"
136
-
137
- options = {
138
- :url => "amqp://localhost",
139
- :exchange => "test-exchange",
140
- :routing_key => "test-messages",
141
- :queue => "test-queue"
142
- }
143
-
144
- Tackle.subscribe(options) do |message|
145
- puts message
146
- end
147
- ```
148
-
149
- By default, tackle will retry any message that fails to be consumed. To
150
- configure the retry limit and the delay in which the messages will be retried,
151
- do the following:
152
-
153
- ```ruby
154
- require "tackle"
155
-
156
- options = {
157
- :url => "amqp://localhost",
158
- :exchange => "test-exchange",
159
- :routing_key => "test-messages",
160
- :queue => "test-queue",
161
- :retry_limit => 8,
162
- :retry_delay => 30
163
- }
164
-
165
- Tackle.subscribe(options) do |message|
166
- puts message
167
- end
168
- ```
169
-
170
- Tackle uses the `STDOUT` by default to trace the state of incoming messages. You
171
- can pass a dedicated logger to the `subscribe` method to redirect the output:
172
-
173
- ```ruby
174
- require "tackle"
175
-
176
- options = {
177
- :url => "amqp://localhost",
178
- :exchange => "test-exchange",
179
- :routing_key => "test-messages",
180
- :queue => "test-queue",
181
- :retry_limit => 8,
182
- :retry_delay => 30,
183
- :logger => Logger.new("subscribe.log")
184
- }
185
-
186
- Tackle.subscribe(options) do |message|
187
- puts message
188
- end
189
- ```
190
-
191
128
  ## Development
192
129
 
193
130
  After checking out the repo, run `bin/setup` to install dependencies. Then,
@@ -0,0 +1,41 @@
1
+ module Tackle
2
+ class Connection
3
+ attr_reader :channel
4
+
5
+ def initialize(amqp_url, exception_handler, logger)
6
+ @amqp_url = amqp_url
7
+ @exception_handler = exception_handler
8
+ @logger = logger
9
+
10
+ connect
11
+ end
12
+
13
+ def connect
14
+ @logger.info("Connecting to RabbitMQ")
15
+
16
+ @connection = Bunny.new(@amqp_url)
17
+ @connection.start
18
+
19
+ @logger.info("Connected to RabbitMQ")
20
+
21
+ @channel = @connection.create_channel
22
+ @channel.prefetch(1)
23
+ @channel.on_uncaught_exception(&@exception_handler)
24
+
25
+ @logger.info("Connected to channel")
26
+ rescue StandardError => ex
27
+ @logger.error("Error while connecting to RabbitMQ message='#{ex}'")
28
+
29
+ raise ex
30
+ end
31
+
32
+ def close
33
+ @channel.close
34
+ @logger.info("Closed channel")
35
+
36
+ @connection.close
37
+ @logger.info("Closed connection to RabbitMQ")
38
+ end
39
+
40
+ end
41
+ end
@@ -1,6 +1,5 @@
1
1
  module Tackle
2
2
  require_relative "consumer/params"
3
- require_relative "consumer/connection"
4
3
  require_relative "consumer/message"
5
4
  require_relative "consumer/exchange"
6
5
 
@@ -19,7 +18,7 @@ module Tackle
19
18
  end
20
19
 
21
20
  def setup_rabbit_connections
22
- @connection = Connection.new(@params.amqp_url, @params.exception_handler, @logger)
21
+ @connection = Tackle::Connection.new(@params.amqp_url, @params.exception_handler, @logger)
23
22
 
24
23
  @exchange = Exchange.new(@params.service, @params.routing_key, @connection, @logger)
25
24
  @main_queue = MainQueue.new(@exchange, @connection, @logger)
@@ -1,49 +1,25 @@
1
1
  module Tackle
2
2
  class Publisher
3
- include Tackle::TackleLogger
4
3
 
5
- def initialize(exchange_name, routing_key, url, logger)
4
+ def initialize(url, exchange_name, routing_key, logger)
5
+ @url = url
6
6
  @exchange_name = exchange_name
7
7
  @routing_key = routing_key
8
- @url = url
9
8
  @logger = logger
10
9
  end
11
10
 
12
11
  def publish(message)
13
- tackle_log("Publishing message started exchange='#{@exchange_name}' routing_key='#{@routing_key}'")
14
-
15
- with_rabbit_connection do |conn|
16
- channel = conn.create_channel
17
- tackle_log("Created a communication channel")
18
-
19
- exchange = channel.direct(@exchange_name, :durable => true)
20
- tackle_log("Declared the exchange")
21
-
22
- exchange.publish(message, :routing_key => @routing_key, :persistent => true)
23
- end
24
-
25
- tackle_log("Publishing message finished exchange='#{@exchange_name}' routing_key='#{@routing_key}'")
26
- end
27
-
28
- private
29
-
30
- def with_rabbit_connection
31
- tackle_log("Establishing rabbit connection")
12
+ connection = Tackle::Connection.new(@url, nil, @logger)
32
13
 
33
- conn = Bunny.new(@url)
34
- conn.start
14
+ @logger.info("Declaring exchange='#{@exchange_name}'")
15
+ exchange = connection.channel.direct(@exchange_name, :durable => true)
16
+ @logger.info("Declared exchange='#{@exchange_name}'")
35
17
 
36
- yield(conn)
37
-
38
- tackle_log("Established rabbit connection")
39
- rescue StandardError => ex
40
- tackle_log("An exception occured while sending the message exception='#{ex.class.name}' message='#{ex.message}'")
41
-
42
- raise ex
18
+ @logger.info("Publishing message exchange='#{@exchange_name}' routing_key='#{@routing_key}'")
19
+ exchange.publish(message, :routing_key => @routing_key, :persistent => true)
20
+ @logger.info("Publishing message finished exchange='#{@exchange_name}' routing_key='#{@routing_key}'")
43
21
  ensure
44
- tackle_log("Clossing rabbit connection")
45
-
46
- conn.close if conn
22
+ connection.close
47
23
  end
48
24
 
49
25
  end
@@ -1,3 +1,3 @@
1
1
  module Tackle
2
- VERSION = "0.9"
2
+ VERSION = "1.0"
3
3
  end
data/lib/tackle.rb CHANGED
@@ -1,54 +1,27 @@
1
1
  require "tackle/version"
2
+ require "bunny"
3
+ require "logger"
2
4
 
3
5
  module Tackle
4
- require "tackle/worker"
6
+ require "tackle/connection"
5
7
  require "tackle/publisher"
6
8
  require "tackle/consumer"
7
9
 
8
- def self.consume(params = {}, &block)
10
+ module_function
11
+
12
+ def consume(params = {}, &block)
9
13
  params = Tackle::Consumer::Params.new(params)
10
14
  consumer = Tackle::Consumer.new(params)
11
15
 
12
16
  consumer.subscribe(&block)
13
17
  end
14
18
 
15
- # deprecated
16
- def self.subscribe(options = {}, &block)
17
- # required
18
- exchange_name = options.fetch(:exchange)
19
- routing_key = options.fetch(:routing_key)
20
- queue_name = options.fetch(:queue)
21
-
22
- # optional
23
- amqp_url = options[:url]
24
- retry_limit = options[:retry_limit]
25
- retry_delay = options[:retry_delay]
26
- logger = options[:logger]
27
- on_uncaught_exception = options[:on_uncaught_exception]
28
-
29
- worker = Tackle::Worker.new(exchange_name,
30
- routing_key,
31
- queue_name,
32
- :url => amqp_url,
33
- :retry_limit => retry_limit,
34
- :retry_delay => retry_delay,
35
- :logger => logger,
36
- :on_uncaught_exception => on_uncaught_exception)
37
-
38
- worker.subscribe(&block)
39
- end
40
-
41
- def self.publish(message, options = {})
42
- # required
43
- exchange_name = options.fetch(:exchange)
44
- routing_key = options.fetch(:routing_key)
45
-
46
- # optional
47
- amqp_url = options[:url] || "amqp://localhost:5672"
48
- logger = options[:logger] || Logger.new(STDOUT)
49
-
50
- publisher = Tackle::Publisher.new(exchange_name, routing_key, amqp_url, logger)
19
+ def publish(message, options = {})
20
+ url = options.fetch(:url)
21
+ exchange = options.fetch(:exchange)
22
+ routing_key = options.fetch(:routing_key)
23
+ logger = options.fetch(:logger, Logger.new(STDOUT))
51
24
 
52
- publisher.publish(message)
25
+ Tackle::Publisher.new(url, exchange, routing_key, logger).publish(message)
53
26
  end
54
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rt-tackle
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.9'
4
+ version: '1.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rendered Text
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-07 00:00:00.000000000 Z
11
+ date: 2016-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -96,8 +96,8 @@ files:
96
96
  - bin/setup
97
97
  - docs/consumer.png
98
98
  - lib/tackle.rb
99
+ - lib/tackle/connection.rb
99
100
  - lib/tackle/consumer.rb
100
- - lib/tackle/consumer/connection.rb
101
101
  - lib/tackle/consumer/dead_queue.rb
102
102
  - lib/tackle/consumer/delay_queue.rb
103
103
  - lib/tackle/consumer/exchange.rb
@@ -105,12 +105,8 @@ files:
105
105
  - lib/tackle/consumer/message.rb
106
106
  - lib/tackle/consumer/params.rb
107
107
  - lib/tackle/consumer/queue.rb
108
- - lib/tackle/delayed_retry.rb
109
108
  - lib/tackle/publisher.rb
110
- - lib/tackle/rabbit.rb
111
- - lib/tackle/tackle_logger.rb
112
109
  - lib/tackle/version.rb
113
- - lib/tackle/worker.rb
114
110
  - reset_rabbit.sh
115
111
  - tackle.gemspec
116
112
  homepage: https://semaphoreci.com
@@ -1,43 +0,0 @@
1
- module Tackle
2
- class Consumer
3
- class Connection
4
- attr_reader :channel
5
-
6
- def initialize(amqp_url, exception_handler, logger)
7
- @amqp_url = amqp_url
8
- @exception_handler = exception_handler
9
- @logger = logger
10
-
11
- connect
12
- end
13
-
14
- def connect
15
- @logger.info("Connecting to RabbitMQ")
16
-
17
- @connection = Bunny.new(@amqp_url)
18
- @connection.start
19
-
20
- @logger.info("Connected to RabbitMQ")
21
-
22
- @channel = @connection.create_channel
23
- @channel.prefetch(1)
24
- @channel.on_uncaught_exception(&@exception_handler)
25
-
26
- @logger.info("Connected to channel")
27
- rescue StandardError => ex
28
- @logger.error("Error while connecting to RabbitMQ message='#{ex}'")
29
-
30
- raise ex
31
- end
32
-
33
- def close
34
- @channel.close
35
- @logger.info("Closed channel")
36
-
37
- @connection.close
38
- @logger.info("Closed connection to RabbitMQ")
39
- end
40
-
41
- end
42
- end
43
- end
@@ -1,36 +0,0 @@
1
- require "tackle/tackle_logger"
2
-
3
- module Tackle
4
-
5
- class DelayedRetry
6
- include Tackle::TackleLogger
7
-
8
- def initialize(dead_letter_queue, properties, payload, retry_limit, logger)
9
- @dead_letter_queue = dead_letter_queue
10
- @properties = properties
11
- @payload = payload
12
- @retry_limit = retry_limit
13
- @logger = logger
14
- end
15
-
16
- def schedule_retry
17
- if retry_count < @retry_limit
18
- tackle_log("Adding message to retry queue for retry #{retry_count + 1}/#{@retry_limit}")
19
- @dead_letter_queue.publish(@payload, :headers => {:retry_count => retry_count + 1})
20
- else
21
- tackle_log("Reached #{retry_count} retries. Discarding message.")
22
- end
23
- end
24
-
25
- private
26
-
27
- def retry_count
28
- if @properties.headers && @properties.headers["retry_count"]
29
- @properties.headers["retry_count"]
30
- else
31
- 0
32
- end
33
- end
34
-
35
- end
36
- end
data/lib/tackle/rabbit.rb DELETED
@@ -1,87 +0,0 @@
1
- require "bunny"
2
- require "tackle/tackle_logger"
3
-
4
- module Tackle
5
-
6
- class Rabbit
7
- include Tackle::TackleLogger
8
-
9
- attr_reader :channel, :dead_letter_queue, :queue, :exchange
10
-
11
- def initialize(exchange_name, routing_key, queue_name, amqp_url, retry_delay, logger)
12
- @exchange_name = exchange_name
13
- @routing_key = routing_key
14
- @queue_name = queue_name
15
- @amqp_url = amqp_url
16
- @retry_delay = retry_delay
17
- @logger = logger
18
- end
19
-
20
- def connect
21
- @conn = Bunny.new(@amqp_url)
22
- @conn.start
23
- tackle_log("Connected to RabbitMQ")
24
-
25
- @channel = @conn.create_channel
26
- @channel.prefetch(1)
27
-
28
- tackle_log("Connected to channel")
29
- connect_queue
30
- connect_dead_letter_queue
31
- rescue StandardError => ex
32
- tackle_log("An exception occured while connecting to the server message='#{ex.message}'")
33
-
34
- raise ex
35
- end
36
-
37
- def on_uncaught_exception(blk)
38
- @channel.on_uncaught_exception(&blk)
39
- end
40
-
41
- def close
42
- @channel.close
43
- tackle_log("Closed channel")
44
- @conn.close
45
- tackle_log("Closed connection to RabbitMQ")
46
- end
47
-
48
- def dead_letter_exchange_name
49
- "#{@exchange_name}.dead_letter_exchange"
50
- end
51
-
52
- def dead_letter_queue_name
53
- "#{@queue_name}_dead_letters"
54
- end
55
-
56
- private
57
-
58
- def connect_queue
59
- @exchange = @channel.direct(@exchange_name, :durable => true)
60
- tackle_log("Connected to exchange '#{@exchange_name}'")
61
-
62
- @queue = @channel.queue(@queue_name, :durable => true).bind(@exchange, :routing_key => @routing_key)
63
-
64
- tackle_log("Connected to queue '#{@queue_name}' with routing key '#{@routing_key}'")
65
- end
66
-
67
- def connect_dead_letter_queue
68
- tackle_log("Connected to dead letter exchange '#{dead_letter_exchange_name}'")
69
-
70
- dead_letter_exchange = @channel.fanout(dead_letter_exchange_name)
71
-
72
- queue_options = {
73
- :durable => true,
74
- :arguments => {
75
- "x-dead-letter-exchange" => @exchange_name,
76
- "x-dead-letter-routing-key" => @routing_key,
77
- "x-message-ttl" => @retry_delay
78
- }
79
- }
80
-
81
- @dead_letter_queue = @channel.queue(dead_letter_queue_name, queue_options).bind(dead_letter_exchange, :routing_key => @routing_key)
82
-
83
- tackle_log("Connected to dead letter queue '#{dead_letter_queue_name}'")
84
- end
85
-
86
- end
87
- end
@@ -1,13 +0,0 @@
1
- module Tackle
2
-
3
- module TackleLogger
4
-
5
- def tackle_log(message)
6
- pid = Process.pid
7
-
8
- whole_message = "tackle - pid=#{pid} message=#{message}"
9
-
10
- @logger.info(whole_message)
11
- end
12
- end
13
- end
data/lib/tackle/worker.rb DELETED
@@ -1,86 +0,0 @@
1
- require "tackle/rabbit"
2
- require "tackle/delayed_retry"
3
-
4
- module Tackle
5
- class Worker
6
- include Tackle::TackleLogger
7
-
8
- attr_reader :rabbit
9
-
10
- # Initializes now worker
11
- #
12
- # @param [String] exchange_name Name of the exchange queue is connected to.
13
- # @param [String] routing_key Routing key for binding queue to exchange
14
- # @param [String] queue_name Name of the queue worker is processing.
15
- # @param [Hash] options Worker options for RabbitMQ connection, retries and logger.
16
- #
17
- # @option options [String] :url AMQP connection url. Defaults to 'localhost'
18
- # @option options [Integer] :retry_limit Number of times message processing should be retried in case of an exception.
19
- # @option options [Integer] :retry_delay Delay between processing retries. Dafaults to 30 seconds. Cannot be changed without deleting or renameing a queue.
20
- # @option options [Logger] :logger Logger instance. Defaults to standard output.
21
- #
22
- # @api public
23
- def initialize(exchange_name, routing_key, queue_name, options = {})
24
- @queue_name = queue_name
25
- @amqp_url = options[:url] || "amqp://localhost:5672"
26
- @retry_limit = options[:retry_limit] || 8
27
- @retry_delay = (options[:retry_delay] || 30) * 1000 #ms
28
- @logger = options[:logger] || Logger.new(STDOUT)
29
-
30
- @rabbit = Tackle::Rabbit.new(exchange_name,
31
- routing_key,
32
- @queue_name,
33
- @amqp_url,
34
- @retry_delay,
35
- @logger)
36
-
37
- @rabbit.connect
38
- @rabbit.on_uncaught_exception(options[:on_uncaught_exception]) if options[:on_uncaught_exception]
39
- end
40
-
41
- # Subscribes for message deliveries
42
- #
43
- # @param [Block] Accepts a block that accepts message
44
- #
45
- # @api public
46
- def subscribe(&block)
47
- tackle_log("Subscribing to queue '#{@queue_name}'...")
48
- rabbit.queue.subscribe(:manual_ack => true,
49
- :block => true) do |delivery_info, properties, payload|
50
-
51
- tackle_log("Received message. Processing...")
52
- process_message(delivery_info, properties, payload, block)
53
- tackle_log("Done with processing message.")
54
-
55
- end
56
- rescue Interrupt => _
57
- rabbit.close
58
- rescue StandardError => ex
59
- tackle_log("An exception occured message='#{ex.message}'")
60
-
61
- raise ex
62
- end
63
-
64
- def process_message(delivery_info, properties, payload, block)
65
- begin
66
- tackle_log("Calling message processor...")
67
- block.call(payload)
68
- @rabbit.channel.ack(delivery_info.delivery_tag)
69
- tackle_log("Successfully processed message")
70
- rescue Exception => ex
71
- tackle_log("Failed to process message. Received exception '#{ex}'")
72
- try_again = Tackle::DelayedRetry.new(@rabbit.dead_letter_queue,
73
- properties,
74
- payload,
75
- @retry_limit,
76
- @logger)
77
- try_again.schedule_retry
78
- tackle_log("Sending negative acknowledgement to source queue...")
79
- @rabbit.channel.nack(delivery_info.delivery_tag)
80
- tackle_log("Negative acknowledgement sent")
81
-
82
- raise ex
83
- end
84
- end
85
- end
86
- end