bug_bunny 3.1.4 → 3.1.6
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 +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/bug_bunny/consumer.rb +57 -24
- data/lib/bug_bunny/producer.rb +1 -1
- data/lib/bug_bunny/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7fec9f487076682121e6d8586e44fe9d70f380bd809fb46014265105421a0d8f
|
|
4
|
+
data.tar.gz: e847fc6f1943f9921f2250a46a20bd6f76b20736812fcbf6bfc437ab49a8a30c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 199faaa596f52cc1c192259e8fe3e7da95152d117db9ded079051bebdff985793e63acde11cb8ceed5e0e216d6934ff35056993947609f2818d8429f524a789a
|
|
7
|
+
data.tar.gz: dfefdd78b4597f90dc059ef07d7423dda86d2630cdab409c514941708cc539d174a763d1a6e18c918dee7058d25c0a996aac0bb52f1b440573b42480e723e284
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
## [3.1.6] - 2026-02-27
|
|
3
|
+
|
|
4
|
+
### 🐛 Bug Fixes & Router Improvements
|
|
5
|
+
* **Enhanced Heuristic Router (ID Detection):** Mejoras críticas en `Consumer#router_dispatch` para soportar una gama mucho más amplia de formatos de identificadores y evitar colisiones con namespaces:
|
|
6
|
+
* **Soporte para Swarm/NanoID:** Se amplió la expresión regular de detección de IDs para capturar hashes alfanuméricos de 20 o más caracteres (`[a-zA-Z0-9_-]{20,}`), permitiendo el correcto ruteo de IDs generados por Docker Swarm (25 caracteres) o NanoID.
|
|
7
|
+
* **Escaneo Inverso (Right-to-Left):** Se modificó la búsqueda del ID para que escanee los segmentos de la URL desde el final hacia el principio (`rindex`). Esto evita falsos positivos donde namespaces cortos como `v1` (ej. `api/v1/...`) eran confundidos accidentalmente con un ID.
|
|
8
|
+
* **Fallback Semántico Posicional:** Se introdujo una red de seguridad (fallback) que infiere la posición del ID basándose en el Verbo HTTP. Si el ID no coincide con ningún patrón Regex (ej. es un ID corto como `node-1`), pero el método es `PUT`, `PATCH` o `DELETE`, el enrutador ahora asume inteligentemente que el penúltimo/último segmento corresponde al ID del recurso.
|
|
9
|
+
|
|
10
|
+
## [3.1.5] - 2026-02-25
|
|
11
|
+
|
|
12
|
+
### ✨ New Features & Improvements
|
|
13
|
+
* **Smart Heuristic Router (Namespace Support):** El enrutador interno del consumidor (`Consumer#router_dispatch`) fue reescrito para soportar namespaces profundos y rutas anidadas sin necesidad de configuración manual. Utiliza una heurística basada en Regex para detectar dinámicamente identificadores (Enteros, UUIDs o hashes alfanuméricos largos) dentro de la URL.
|
|
14
|
+
* Esto permite que rutas complejas como `GET api/v1/ecommerce/orders/a1b2c3d4/cancel` resuelvan automáticamente al controlador `Api::V1::Ecommerce::OrdersController`, asignando `id: a1b2c3d4` y `action: cancel`.
|
|
15
|
+
|
|
2
16
|
## [3.1.4] - 2026-02-21
|
|
3
17
|
|
|
4
18
|
### 🚀 Cloud Native & Infrastructure Features
|
data/lib/bug_bunny/consumer.rb
CHANGED
|
@@ -179,44 +179,77 @@ module BugBunny
|
|
|
179
179
|
|
|
180
180
|
# Interpreta la URL y el verbo para decidir qué controlador ejecutar.
|
|
181
181
|
#
|
|
182
|
-
#
|
|
183
|
-
#
|
|
182
|
+
# Implementa un Router Heurístico que soporta namespaces y acciones custom
|
|
183
|
+
# buscando dinámicamente el ID en la ruta mediante Regex y Fallback Semántico.
|
|
184
184
|
#
|
|
185
185
|
# @param method [String] Verbo HTTP (GET, POST, etc).
|
|
186
|
-
# @param path [String] URL virtual del recurso (ej: '
|
|
186
|
+
# @param path [String] URL virtual del recurso (ej: 'foo/bar/algo/13/test').
|
|
187
187
|
# @return [Hash] Estructura con keys {:controller, :action, :id, :params}.
|
|
188
188
|
def router_dispatch(method, path)
|
|
189
|
-
# Usamos URI para separar path de query string
|
|
190
189
|
uri = URI.parse("http://dummy/#{path}")
|
|
191
190
|
segments = uri.path.split('/').reject(&:empty?)
|
|
192
191
|
|
|
193
|
-
# --- FIX: Uso de Rack para soportar params anidados ---
|
|
194
192
|
query_params = uri.query ? Rack::Utils.parse_nested_query(uri.query) : {}
|
|
195
|
-
|
|
196
|
-
# Si estamos en Rails, convertimos a HashWithIndifferentAccess para comodidad
|
|
197
193
|
if defined?(ActiveSupport::HashWithIndifferentAccess)
|
|
198
194
|
query_params = query_params.with_indifferent_access
|
|
199
195
|
end
|
|
200
196
|
|
|
201
|
-
#
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
197
|
+
# 1. Acción Built-in: Health Check Global (/up o /api/up)
|
|
198
|
+
if segments.last == 'up' && method.to_s.upcase == 'GET'
|
|
199
|
+
ctrl = segments.size > 1 ? segments[0...-1].join('/') : 'application'
|
|
200
|
+
return { controller: ctrl, action: 'up', id: nil, params: query_params }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# 2. Búsqueda dinámica del ID (Heurística por Regex)
|
|
204
|
+
# Patrón: Enteros, UUIDs, o Hashes largos (Docker Swarm 25 chars, Mongo 24 chars)
|
|
205
|
+
id_pattern = /^(?:\d+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|[a-zA-Z0-9_-]{20,})$/
|
|
206
|
+
|
|
207
|
+
# FIX: Usamos rindex (de derecha a izquierda) para evitar falsos positivos con namespaces como 'v1'
|
|
208
|
+
id_index = segments.rindex { |s| s.match?(id_pattern) }
|
|
209
|
+
|
|
210
|
+
# 3. Fallback Semántico Posicional
|
|
211
|
+
# Si el regex no detectó el ID (ej: ID corto como "node-1"), pero la semántica HTTP
|
|
212
|
+
# indica que es una operación singular (PUT/DELETE/GET), asumimos que el último segmento es el ID.
|
|
213
|
+
if id_index.nil? && segments.size >= 2
|
|
214
|
+
last_segment = segments.last
|
|
215
|
+
method_up = method.to_s.upcase
|
|
216
|
+
|
|
217
|
+
is_member_verb = %w[PUT PATCH DELETE].include?(method_up)
|
|
218
|
+
# En GET, nos aseguramos que la última palabra no sea una acción estándar de REST
|
|
219
|
+
is_get_member = method_up == 'GET' && !%w[index new edit up action].include?(last_segment)
|
|
220
|
+
|
|
221
|
+
if is_member_verb || is_get_member
|
|
222
|
+
# Si tiene 3 o más segmentos (ej. nodes/node-1/stats), el ID no está al final.
|
|
223
|
+
# Este fallback asume que para IDs raros, el formato clásico es recurso/id
|
|
224
|
+
id_index = segments.size - 1
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# 4. Asignación de variables según escenario
|
|
229
|
+
if id_index
|
|
230
|
+
# ESCENARIO A: Ruta Miembro (ej. nodes/4bv445vgc158hk4twlxmdjo0v/stats)
|
|
231
|
+
controller_name = segments[0...id_index].join('/')
|
|
232
|
+
id = segments[id_index]
|
|
233
|
+
action = segments[id_index + 1] # Puede ser nil si no hay acción extra al final
|
|
234
|
+
else
|
|
235
|
+
# ESCENARIO B: Ruta Colección (ej. api/v1/nodes)
|
|
236
|
+
controller_name = segments.join('/')
|
|
237
|
+
id = nil
|
|
238
|
+
action = nil
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# 5. Inferimos la acción clásica de Rails si no hay una explícita
|
|
242
|
+
unless action
|
|
243
|
+
action = case method.to_s.upcase
|
|
244
|
+
when 'GET' then id ? 'show' : 'index'
|
|
245
|
+
when 'POST' then 'create'
|
|
246
|
+
when 'PUT', 'PATCH' then 'update'
|
|
247
|
+
when 'DELETE' then 'destroy'
|
|
248
|
+
else id ? 'show' : 'index'
|
|
249
|
+
end
|
|
217
250
|
end
|
|
218
251
|
|
|
219
|
-
# Inyectamos el ID en los
|
|
252
|
+
# 6. Inyectamos el ID en los parámetros para fácil acceso en el Controlador
|
|
220
253
|
query_params['id'] = id if id
|
|
221
254
|
|
|
222
255
|
{ controller: controller_name, action: action, id: id, params: query_params }
|
data/lib/bug_bunny/producer.rb
CHANGED
|
@@ -110,7 +110,7 @@ module BugBunny
|
|
|
110
110
|
BugBunny.configuration.logger.info("[BugBunny::Producer] 📤 #{verb} /#{target} | RK: '#{rk}' | ID: #{id}")
|
|
111
111
|
|
|
112
112
|
# DEBUG: Detalle completo de Infraestructura y Payload
|
|
113
|
-
BugBunny.configuration.logger.debug("[BugBunny::Producer] ⚙️
|
|
113
|
+
BugBunny.configuration.logger.debug("[BugBunny::Producer] ⚙️ Exchange #{request.exchange} | Opts: #{final_x_opts}")
|
|
114
114
|
BugBunny.configuration.logger.debug("[BugBunny::Producer] 📦 Payload: #{payload.truncate(300)}") if payload.is_a?(String)
|
|
115
115
|
end
|
|
116
116
|
|
data/lib/bug_bunny/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bug_bunny
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.1.
|
|
4
|
+
version: 3.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- gabix
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bunny
|