bug_bunny 4.10.2 → 4.10.3

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: '08e0d33ac09d046d3de52d3d7f75b7b87df8d6e96f495ab37c7433fe9f4add33'
4
- data.tar.gz: '09373953a7dc292c97363e3514f9e3db1b9b041527a9e26e09e52089abfda0b9'
3
+ metadata.gz: 31a6f6e9b83b1a82216f344a101ca0a99daebb5fd9e44bf5abc9c9e9753f4011
4
+ data.tar.gz: f101254aad9d8bbd66a359438a1efe970acd58e4b853841bcda72966c2472c8c
5
5
  SHA512:
6
- metadata.gz: 34799b71420bb76ca71439e80d5b27a5d2ed38f424b16ba914b85566c5277279d3f4e1743caa4f2e8d932d125ceb019479add38df49573ab42880ef103cf1c34
7
- data.tar.gz: 7b8cceae4b29ff12e9e42fc51ee3b68ec5a1ae92122a91f35c6bb132f09edf1b5171785ef6494d3580e86da715218f1602f2ef8071a2e9b77b0e0123c28795ff
6
+ metadata.gz: 6b8a42f884ae9c8075dab9e4052658a5c0828cae904800fe222fd058cdaf3cd1307bba6478ca7824e273a517484d71da0416fd3b7c38bb08a9a0845e39dacb90
7
+ data.tar.gz: 6de916fae62566f01142b557b6e6c4ed4cf44d58298d9ff3c174e8d38b4422238487dacd29f273d7b3ea356d30f8c08a5c5a872f9ed08f6cacb8a540511a933a
data/README.md CHANGED
@@ -228,6 +228,57 @@ Las claves sensibles (`password`, `token`, `secret`, `api_key`, `authorization`,
228
228
 
229
229
  ---
230
230
 
231
+ ## Error Handling
232
+
233
+ BugBunny maps RabbitMQ responses to a semantic exception hierarchy, similar to how HTTP clients handle status codes.
234
+
235
+ ### Exception Hierarchy
236
+
237
+ ```
238
+ BugBunny::Error
239
+ ├── ClientError (4xx)
240
+ │ ├── BadRequest (400)
241
+ │ ├── NotFound (404)
242
+ │ ├── NotAcceptable (406)
243
+ │ ├── RequestTimeout (408)
244
+ │ ├── Conflict (409)
245
+ │ └── UnprocessableEntity (422)
246
+ └── ServerError (5xx)
247
+ ├── InternalServerError (500+)
248
+ └── RemoteError (500)
249
+ ```
250
+
251
+ ### Remote Exception Propagation
252
+
253
+ When a controller raises an unhandled exception, BugBunny serializes it and sends it back to the caller as a 500 response. The client-side middleware reconstructs it as a `BugBunny::RemoteError` with full access to the original exception details:
254
+
255
+ ```ruby
256
+ begin
257
+ node = RemoteNode.find('node-123')
258
+ rescue BugBunny::RemoteError => e
259
+ e.original_class # => "TypeError"
260
+ e.original_message # => "nil can't be coerced into Integer"
261
+ e.original_backtrace # => Array<String> from the remote service
262
+ rescue BugBunny::NotFound
263
+ # Resource doesn't exist
264
+ rescue BugBunny::RequestTimeout
265
+ # Consumer didn't respond in time
266
+ end
267
+ ```
268
+
269
+ ### Validation Errors
270
+
271
+ `Resource#save` returns `false` on validation failure and loads remote errors into the model:
272
+
273
+ ```ruby
274
+ order = RemoteOrder.new(total: -1)
275
+ unless order.save
276
+ order.errors.full_messages # => ["total must be greater than 0"]
277
+ end
278
+ ```
279
+
280
+ ---
281
+
231
282
  ## Documentation
232
283
 
233
284
  - [Concepts](docs/concepts.md) — What BugBunny is, AMQP in 5 minutes, RPC vs fire-and-forget
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BugBunny
4
- VERSION = '4.10.2'
4
+ VERSION = '4.10.3'
5
5
  end
data/lib/bug_bunny.rb CHANGED
@@ -83,7 +83,12 @@ module BugBunny
83
83
  # @raise [Bunny::TCPConnectionFailed] Si no se puede conectar al servidor.
84
84
  def self.create_connection(**options)
85
85
  conn_options = merge_connection_options(options)
86
- Bunny.new(conn_options).tap(&:start)
86
+ Bunny.new(conn_options).tap do |conn|
87
+ conn.after_recovery_completed do
88
+ safe_log(:info, 'bug_bunny.connection_recovered', host: conn_options[:host])
89
+ end
90
+ conn.start
91
+ end
87
92
  end
88
93
 
89
94
  # Cierra la conexión global si existe.
data/skill/SKILL.md CHANGED
@@ -238,6 +238,10 @@ No registrar consumer middlewares durante la ejecución de `call()`. El stack to
238
238
  **Causa:** Fallo de validación en el servicio remoto.
239
239
  **Resolución:** `resource.save` devuelve `false`. Acceder a `resource.errors` o `rescue` con `e.error_messages`.
240
240
 
241
+ ### BugBunny::RemoteError (500)
242
+ **Causa:** Excepción no manejada en el controller remoto. Se serializa y propaga al cliente RPC con clase, mensaje y backtrace originales.
243
+ **Resolución:** `rescue BugBunny::RemoteError => e` y acceder a `e.original_class`, `e.original_message`, `e.original_backtrace`. Revisar logs del consumer (`event=controller.unhandled_exception`).
244
+
241
245
  ### BugBunny::CommunicationError
242
246
  **Causa:** Fallo de conexión o reconexión agotada.
243
247
  **Resolución:** Verificar conectividad a RabbitMQ. Revisar `max_reconnect_attempts` y logs de reconexión.
@@ -86,18 +86,36 @@ end
86
86
 
87
87
  ### BugBunny::RemoteError (500)
88
88
  **Causa:** Excepción no manejada en el controller remoto. El error se serializa y propaga al cliente RPC.
89
+
90
+ **Flujo completo:**
91
+ 1. El controller remoto lanza una excepción (ej: `TypeError`).
92
+ 2. `BugBunny::Controller#handle_exception` la captura y serializa con `RemoteError.serialize(exception)` → `{ class:, message:, backtrace: }` (máx 25 líneas).
93
+ 3. El consumer responde con status 500 y el campo `bug_bunny_exception` en el body.
94
+ 4. El middleware `RaiseError` del cliente detecta `bug_bunny_exception`, reconstituye un `BugBunny::RemoteError` y lo lanza localmente.
95
+
89
96
  **Acceso a detalles:**
90
97
  ```ruby
98
+ # Con Client directo
99
+ begin
100
+ client.request('users/42', method: :get)
101
+ rescue BugBunny::RemoteError => e
102
+ e.original_class # => "TypeError"
103
+ e.original_message # => "nil can't be coerced into Integer"
104
+ e.original_backtrace # => Array<String> (backtrace del servicio remoto)
105
+ e.to_s # => "BugBunny::RemoteError(TypeError): nil can't be coerced into Integer"
106
+ end
107
+
108
+ # Con Resource ORM
91
109
  begin
92
- client.request('users/42')
110
+ RemoteNode.find('node-123')
93
111
  rescue BugBunny::RemoteError => e
94
- e.original_class # String: clase original (ej: "TypeError")
95
- e.original_message # String: mensaje original
96
- e.original_backtrace # Array<String>: backtrace original
112
+ Rails.logger.error("Remote #{e.original_class}: #{e.original_message}")
97
113
  end
98
114
  ```
99
- **Serialización:** El controller captura excepciones con `rescue_from` → `handle_exception` → serializa con clase, mensaje y primeras 25 líneas del backtrace.
100
- **Propagación:** El middleware `RaiseError` del cliente reconstituye `RemoteError` y la lanza localmente.
115
+
116
+ **Compatibilidad:** Si la respuesta 500 no contiene `bug_bunny_exception` (ej: servicio remoto con versión anterior de BugBunny), se lanza `BugBunny::InternalServerError` en su lugar.
117
+
118
+ **Herencia:** `RemoteError < ServerError < Error < StandardError`. Se puede capturar con `rescue BugBunny::ServerError` para atrapar tanto `RemoteError` como `InternalServerError`.
101
119
 
102
120
  ## Formato de Mensajes de Error
103
121
 
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: 4.10.2
4
+ version: 4.10.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - gabix
@@ -303,7 +303,7 @@ metadata:
303
303
  homepage_uri: https://github.com/gedera/bug_bunny
304
304
  source_code_uri: https://github.com/gedera/bug_bunny
305
305
  changelog_uri: https://github.com/gedera/bug_bunny/blob/main/CHANGELOG.md
306
- documentation_uri: https://github.com/gedera/bug_bunny/blob/v4.10.2/skill
306
+ documentation_uri: https://github.com/gedera/bug_bunny/blob/v4.10.3/skill
307
307
  post_install_message:
308
308
  rdoc_options: []
309
309
  require_paths: