bug_bunny 2.0.0 → 2.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 619fcbcb8024b1952fb21a4764cc9ae3734df38d7e359ec32f5b41fc3009eccd
4
- data.tar.gz: 5c950d6cc2ef61351e937c6f2a7a32e6dc8dee06f4f93dfdae1bed350ad9702a
3
+ metadata.gz: 8fccb3590fd16133119a7e2cea4c05002964846ac5a35e0714925f2d87115a06
4
+ data.tar.gz: 839ab64bb406eebee8e59f99c010c640a033dab15cd0f531e66f0fbc1e201c82
5
5
  SHA512:
6
- metadata.gz: 5ca317931674edfef2bc57eff4ab9df4faea01edfb833ce8978cd74bcd1bf9bb0c5823efe9540039b16ef5dfca8d3800d7fa6a76720e4949e13d3138baeb7f8f
7
- data.tar.gz: cfe9ee5d4d01ae4a786eac02028b623939228da9d695bfbdd0139621600ff4e8ad825ccc5c74178c8d88deb38f47ea05eec2137e58ccad2eb8c7d202bfed6168
6
+ metadata.gz: 4be8016e660aec70394814ffc85ecba71759aeb94df817abac412c201685ebee89c447fdd76b9904dfb5d2bc5f73e208ed0eed2d9bbc016a307c09978254c76e
7
+ data.tar.gz: 741552a099ae0aadb5717cb46fc4ff24c77c9f31f7dae677131dc158f784a75bca1a739bb6cf65eba42bff84fba853d25a2df54ca0d5884a23f679fa72c679b0
data/README.md CHANGED
@@ -1,9 +1,172 @@
1
1
  # BugBunny
2
2
 
3
+ ## Configuration
4
+
5
+ ```ruby
6
+ config/initializers/bug_bunny.rb
7
+ BugBunny.configure do |config|
8
+ config.host = 'Host'
9
+ config.username = 'Username'
10
+ config.password = 'Password'
11
+ config.vhost = '/'
12
+ config.logger = Rails.logger
13
+ config.automatically_recover = false
14
+ config.network_recovery_interval = 5
15
+ config.connection_timeout = 10
16
+ config.read_timeout = 30
17
+ config.write_timeout = 30
18
+ config.heartbeat = 15
19
+ config.continuation_timeout = 15_000
20
+ end
21
+ ```
22
+
3
23
  ## Publish
4
24
 
25
+ ### Rutas
26
+
27
+ ```
28
+ # config/rabbit_rest.yml
29
+ default: &default
30
+ healt_check:
31
+ up: 'healt_check/up'
32
+ manager:
33
+ services:
34
+ index: 'services/index'
35
+ create: 'services/create'
36
+ show: 'services/%<id>s/show'
37
+ update: 'services/%<id>s/update'
38
+ destroy: 'services/%<id>s/destroy'
39
+ swarm:
40
+ info: 'swarm/info'
41
+ version: 'swarm/version'
42
+ swarm: 'swarm/swarm'
43
+ tasks:
44
+ index: 'tasks/index'
45
+
46
+ development:
47
+ <<: *default
48
+
49
+ test:
50
+ <<: *default
51
+
52
+ production:
53
+ <<: *default
54
+
55
+ ```
56
+
57
+ ### Configuration
58
+
59
+ ```ruby
60
+ # config/initializers/bug_bunny.rb
61
+ BUG_BUNNY_ENDPOINTS = Rails.application.config_for(:rabbit_rest)
62
+
63
+ BUNNY_POOL = ConnectionPool.new(size: RABBIT_MAX_THREADS) do
64
+ BugBunny::Rabbit.create_connection(host: RABBIT_HOST, username: RABBIT_USER, password: RABBIT_PASS, vhost: RABBIT_VIRTUAL_HOST)
65
+ end
66
+ ```
67
+
68
+ ### Publisher
69
+
70
+ Creamos cualquier clase que herede de `BugBunny::Publisher`, luego definimos metodos de clase y dentro de cada una de ella su implementacion
71
+
72
+ 1. Mensajes sincronicos
73
+
74
+ ```
75
+ class Rabbit::Publisher::Manager < BugBunny::Publisher
76
+ ROUTING_KEY = :manager
77
+ ROUTES = BUG_BUNNY_ENDPOINTS[:manager][:swarm]
78
+
79
+ def self.info(exchange:, message: nil)
80
+ obj = new(pool: NEW_BUNNY_POOL, exchange_name: exchange, action: self::ROUTES[:info], message: message)
81
+ obj.publish_and_consume!
82
+ end
83
+
84
+ def self.version(exchange:, message: nil)
85
+ obj = new(pool: NEW_BUNNY_POOL, exchange_name: exchange, action: self::ROUTES[:version], message: message)
86
+ obj.publish_and_consume!
87
+ end
88
+ end
89
+ ```
90
+
91
+ 2. Mensajes Asincronicos
92
+
93
+ ```
94
+ class Rabbit::Publisher::Manager < BugBunny::Publisher
95
+ ROUTING_KEY = :manager
96
+ ROUTES = BUG_BUNNY_ENDPOINTS[:manager][:swarm]
97
+
98
+ def self.info(exchange:, message: nil)
99
+ obj = new(pool: NEW_BUNNY_POOL, exchange_name: exchange, action: self::ROUTES[:info], message: message)
100
+ obj.publish!
101
+ end
102
+
103
+ def self.version(exchange:, message: nil)
104
+ obj = new(pool: NEW_BUNNY_POOL, exchange_name: exchange, action: self::ROUTES[:version], message: message)
105
+ obj.publish!
106
+ end
107
+ end
108
+ ```
109
+
110
+ 3. Attributes del objeto BugBunny::Publisher
111
+
112
+ - content_type
113
+ - content_encoding
114
+ - correlation_id
115
+ - reply_to
116
+ - message_id
117
+ - timestamp
118
+ - priority
119
+ - expiration
120
+ - user_id
121
+ - app_id
122
+ - action
123
+ - aguments
124
+ - cluster_id
125
+ - persistent
126
+ - expiration
127
+
5
128
  ## Consumer
6
129
 
130
+ ```
131
+ class Rabbit::Controllers::Application < BugBunny::Controller
132
+ end
133
+
134
+ class Rabbit::Controllers::Swarm < Rabbit::Controllers::Application
135
+ def info
136
+ render status: :ok, json: Api::Docker.info
137
+ end
138
+
139
+ def version
140
+ render status: :ok, json: Api::Docker.version
141
+ end
142
+
143
+ def swarm
144
+ render status: :ok, json: Api::Docker.swarm
145
+ end
146
+ end
147
+
148
+ ```
149
+
150
+ ## Resource
151
+ Solo para recursos que se adaptan al crud de rails estoy utilizando automaticamente la logica de los publicadores. Los atributos solo se ponen si son necesarios, si no la dejas vacia y actua igual que active resource.
152
+
153
+ ```
154
+ class Manager::Application < BugBunny::Resource
155
+ self.resource_path = 'rabbit/publisher/manager'
156
+
157
+ attribute :id # 'ID'
158
+ attribute :version # 'Version'
159
+ attribute :created_at # 'CreatedAt'
160
+ attribute :update_at # 'UpdatedAt'
161
+ attribute :spec # 'Spec'
162
+ end
163
+
164
+ class Manager::Service < Manager::Application
165
+ attribute :endpoint # 'Endpoint'
166
+ end
167
+
168
+ ```
169
+
7
170
  ## Exceptions
8
171
  - Error General:
9
172
  - `BugBunny::Error` hereda de `::StandardError` (Captura cualquier error de la gema.)
@@ -16,5 +179,5 @@
16
179
  - `BugBunny::ResponseError::NotFound`
17
180
  - `BugBunny::ResponseError::NotAcceptable`
18
181
  - `BugBunny::ResponseError::RequestTimeout`
19
- - `BugBunny::ResponseError::UnprocessableEntity`
182
+ - `BugBunny::ResponseError::UnprocessableEntity`: En este el error viene el error details a lo rails.
20
183
  - `BugBunny::ResponseError::InternalServerError`
@@ -3,6 +3,7 @@ module BugBunny
3
3
  # Ayuda a atrapar cualquier error de la gema con un solo 'rescue BugBunny::Error'.
4
4
  class Error < ::StandardError; end
5
5
  class PublishError < Error; end
6
+ class Connection < Error; end
6
7
 
7
8
  module ResponseError
8
9
  class Base < Error; end
@@ -52,7 +52,7 @@ module BugBunny
52
52
  include ActiveModel::Attributes
53
53
 
54
54
  attribute :message
55
- attribute :pool
55
+ attribute :connection
56
56
  attribute :routing_key, :string
57
57
  attribute :persistent, :boolean, default: false
58
58
  attribute :content_type, :string, default: "application/json"
@@ -66,25 +66,19 @@ module BugBunny
66
66
  attribute :expiration, :integer, default: -> { 1.day.in_milliseconds } #ms
67
67
  attribute :exchange_name, :string
68
68
  attribute :exchange_type, :string, default: 'direct'
69
- attr_accessor :type
70
-
69
+ attribute :type, :string
71
70
  attribute :action, :string
72
- attribute :arguments, default: {}
73
71
 
74
72
  def publish!
75
- pool.with do |conn|
76
- app = Rabbit.new(connection: conn)
77
- app.build_exchange(name: exchange_name, type: exchange_type)
78
- app.publish!(message, publish_opts)
79
- end
73
+ app = Rabbit.new(connection: connection)
74
+ app.build_exchange(name: exchange_name, type: exchange_type)
75
+ app.publish!(message, publish_opts)
80
76
  end
81
77
 
82
78
  def publish_and_consume!
83
- pool.with do |conn|
84
- app = Rabbit.new(connection: conn)
85
- app.build_exchange(name: exchange_name, type: exchange_type)
86
- app.publish_and_consume!(message, publish_opts)
87
- end
79
+ app = Rabbit.new(connection: connection)
80
+ app.build_exchange(name: exchange_name, type: exchange_type)
81
+ app.publish_and_consume!(message, publish_opts)
88
82
  end
89
83
 
90
84
  def publish_opts
@@ -101,14 +95,13 @@ module BugBunny
101
95
  expiration: expiration }
102
96
  end
103
97
 
104
- def type
105
- return if action.blank?
106
-
107
- self.type = format(action, arguments)
108
- end
109
-
110
98
  def initialize(attrs = {})
111
99
  super(attrs)
100
+ if attrs[:action].present?
101
+ args = attrs[:arguments] || {}
102
+
103
+ self.type = format(attrs[:action], args)
104
+ end
112
105
  self.routing_key ||= self.class::ROUTING_KEY
113
106
  end
114
107
  end
@@ -137,11 +137,11 @@ module BugBunny
137
137
  Rails.logger.debug("PUBLISHER Options: #{options}")
138
138
  publish!(msg, options)
139
139
 
140
- if response_latch.wait(RABBIT_READ_TIMEOUT)
140
+ if response_latch.wait(RABBIT_CONNECTION_TIMEOUT)
141
141
  subscription.cancel
142
142
  build_response(status: response[:status], body: response[:body])
143
143
  else
144
- raise "Timeout: No response received within #{RABBIT_READ_TIMEOUT} seconds."
144
+ raise "Timeout: No response received within #{RABBIT_CONNECTION_TIMEOUT} seconds."
145
145
  end
146
146
  rescue BugBunny::ResponseError::Base => e
147
147
  subscription&.cancel
@@ -303,6 +303,10 @@ module BugBunny
303
303
  )
304
304
 
305
305
  bunny.tap(&:start)
306
+ rescue Timeout::Error, Bunny::ConnectionError => e
307
+ # Timeout::Error (para el timeout de conexión TCP) se captura separadamente.
308
+ # Bunny::ConnectionError cubre TCPConnectionFailed, AuthenticationFailure, AccessRefused, etc.
309
+ raise BugBunny::Error::Connection, e.message
306
310
  end
307
311
  end
308
312
  end
@@ -21,16 +21,18 @@ module BugBunny
21
21
  end
22
22
 
23
23
  class ExchangeScope
24
- attr_reader :exchange_name, :klass
24
+ attr_reader :exchange_name, :routing_key, :klass
25
25
 
26
- def initialize(klass, exchange_name)
26
+ def initialize(klass, exchange_name, routing_key = nil)
27
27
  @klass = klass
28
28
  @exchange_name = exchange_name
29
+ @routing_key = routing_key
29
30
  end
30
31
 
31
32
  def method_missing(method_name, *args, **kwargs, &block)
32
33
  if @klass.respond_to?(method_name, true)
33
34
  kwargs[:exchange] = @exchange_name
35
+ kwargs[:routing_key] = @routing_key if @routing_key.present?
34
36
  @klass.execute(method_name.to_sym, *args, **kwargs, &block)
35
37
  else
36
38
  super
@@ -103,7 +105,7 @@ module BugBunny
103
105
 
104
106
  return self if persisted? && changes.empty?
105
107
 
106
- obj = self.class.publisher.send(action, exchange: current_exchange, message: changes_to_send)
108
+ obj = self.class.publisher.send(action, exchange: current_exchange, routing_key: current_routing_key, message: changes_to_send)
107
109
 
108
110
  assign_attributes(obj) # refresco el objeto
109
111
  self.persisted = true
@@ -119,7 +121,7 @@ module BugBunny
119
121
  return self unless persisted?
120
122
 
121
123
  # Llamada al PUBLISHER sin el argumento 'box'
122
- self.class.publisher.send(destroy_action.to_sym, exchange: current_exchange, id: id)
124
+ self.class.publisher.send(destroy_action.to_sym, exchange: current_exchange, routing_key: current_routing_key, id: id)
123
125
 
124
126
  self.persisted = false
125
127
  true
@@ -132,20 +134,28 @@ module BugBunny
132
134
  self.class.current_exchange
133
135
  end
134
136
 
135
- def self.for_exchange(exchange_name)
137
+ def current_routing_key
138
+ self.class.current_routing_key
139
+ end
140
+
141
+ def self.for_exchange(exchange_name, routing_key = nil)
136
142
  raise ArgumentError, 'Exchange name must be specified.' if exchange_name.blank?
137
143
 
138
- ExchangeScope.new(self, exchange_name)
144
+ ExchangeScope.new(self, exchange_name, routing_key)
139
145
  end
140
146
 
141
147
  def self.execute(name, *args, **kwargs, &block)
142
148
  original_exchange = Thread.current[:bugbunny_current_exchange]
143
149
  Thread.current[:bugbunny_current_exchange] = kwargs[:exchange]
150
+ original_routing_key = Thread.current[:bugbunny_current_routing_key]
151
+ Thread.current[:bugbunny_current_routing_key] = kwargs[:routing_key]
144
152
  begin
145
153
  kwargs.delete(:exchange)
154
+ kwargs.delete(:routing_key)
146
155
  send(name, *args, **kwargs, &block)
147
156
  ensure
148
157
  Thread.current[:bugbunny_current_exchange] = original_exchange
158
+ Thread.current[:bugbunny_current_routing_key] = original_routing_key
149
159
  end
150
160
  end
151
161
 
@@ -153,12 +163,16 @@ module BugBunny
153
163
  Thread.current[:bugbunny_current_exchange]
154
164
  end
155
165
 
166
+ def self.current_routing_key
167
+ Thread.current[:bugbunny_current_routing_key]
168
+ end
169
+
156
170
  def self.all
157
171
  where
158
172
  end
159
173
 
160
174
  def self.where(query = {})
161
- body = publisher.send(index_action.to_sym, exchange: current_exchange, message: query)
175
+ body = publisher.send(index_action.to_sym, exchange: current_exchange, routing_key: current_routing_key, message: query)
162
176
  instances = []
163
177
 
164
178
  body.each do |obj|
@@ -171,7 +185,7 @@ module BugBunny
171
185
  end
172
186
 
173
187
  def self.find(id)
174
- obj = publisher.send(show_action.to_sym, exchange: current_exchange, id: id)
188
+ obj = publisher.send(show_action.to_sym, exchange: current_exchange, routing_key: current_routing_key, id: id)
175
189
  return if obj.blank?
176
190
 
177
191
  instance = new
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BugBunny
4
- VERSION = "2.0.0"
4
+ VERSION = "2.0.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bug_bunny
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - gabix