bug_bunny 3.1.4 → 3.1.5

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: 28bb35f1140309e9527c44f108cba3b58b85aae52c7253d17f35f7b35e248661
4
- data.tar.gz: f3b30d3b77b1c242c3e8c8fc9576d8143b2587b60da83a0d633604eaca464ebd
3
+ metadata.gz: a96d4e81fd57e9a1a524aa479bbb85d6fe3a99bd654da95014f633d2fb0cb2d2
4
+ data.tar.gz: cb49f5e1789c1737572fb98b2d21428cf02c129c33e3049de1a0de4f6270a9d3
5
5
  SHA512:
6
- metadata.gz: a069a81c26762bedc55cb8c0be70ac6ff2154d70d4b54f10d7650ddc27160cf400c4c8b680e50e0fd3529f39447ccfcb83864ae7d99396ee7ce62ef5d84da6fd
7
- data.tar.gz: d8e5130f3d6830023f85516a2dec1db036c49cc0963af8f92255987c32b6e721e2785ed54c4d2b9ac94931c5b3e1073c1b1a549265aabb39839f0b95348deaaa
6
+ metadata.gz: ea0ae037590a852734607ad7e46fabff4cfab87aef068a724da42d506fc79ccda376d0db85f0d4ebd1f516ac2aef963fcdd18604a6d808efb3e4e2de0ca32391
7
+ data.tar.gz: 6930cc1f181bc7d6968cb4fe3ed82f25cb59650522f45c5ad5e6f9328cc33125bc41d197de35f05f16e1126014ea7ada86cb2d6a348e7c4e0b6a4c8e56a61a7a
data/CHANGELOG.md CHANGED
@@ -1,4 +1,10 @@
1
1
  # Changelog
2
+ ## [3.1.5] - 2026-02-25
3
+
4
+ ### ✨ New Features & Improvements
5
+ * **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.
6
+ * 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`.
7
+
2
8
  ## [3.1.4] - 2026-02-21
3
9
 
4
10
  ### 🚀 Cloud Native & Infrastructure Features
@@ -179,44 +179,58 @@ module BugBunny
179
179
 
180
180
  # Interpreta la URL y el verbo para decidir qué controlador ejecutar.
181
181
  #
182
- # Utiliza `Rack::Utils.parse_nested_query` para soportar parámetros anidados
183
- # como `q[service]=rabbit`.
182
+ # Implementa un Router Heurístico que soporta namespaces y acciones custom
183
+ # buscando dinámicamente el ID en la ruta.
184
184
  #
185
185
  # @param method [String] Verbo HTTP (GET, POST, etc).
186
- # @param path [String] URL virtual del recurso (ej: 'users/1?active=true').
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
- # Lógica de Ruteo Convencional
202
- controller_name = segments[0]
203
- id = segments[1]
204
-
205
- action = case method.to_s.upcase
206
- when 'GET' then id ? 'show' : 'index'
207
- when 'POST' then 'create'
208
- when 'PUT', 'PATCH' then 'update'
209
- when 'DELETE' then 'destroy'
210
- else id || 'index'
211
- end
212
-
213
- # Soporte para rutas miembro custom (POST users/1/promote)
214
- if segments.size >= 3
215
- id = segments[1]
216
- action = segments[2]
197
+ # 1. Acción Built-in: Health Check Global (/up o /api/up)
198
+ if segments.last == 'up' && method.to_s.upcase == 'GET'
199
+ # Si la ruta es solo 'up', usamos un controlador genérico 'application'
200
+ ctrl = segments.size > 1 ? segments[0...-1].join('/') : 'application'
201
+ return { controller: ctrl, action: 'up', id: nil, params: query_params }
202
+ end
203
+
204
+ # 2. Búsqueda dinámica del ID (Heurística)
205
+ # Patrón: Números enteros, UUIDs, o hashes alfanuméricos largos (MongoDB/Snowflake)
206
+ 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}|[0-9a-fA-F]{24})$/
207
+ id_index = segments.find_index { |s| s.match?(id_pattern) }
208
+
209
+ if id_index
210
+ # ESCENARIO A: Ruta Miembro (ej. foo/bar/algo/13/test)
211
+ # Todo lo que está antes del ID es el namespace/controlador
212
+ controller_name = segments[0...id_index].join('/') # "foo/bar/algo"
213
+ id = segments[id_index] # "13"
214
+ action = segments[id_index + 1] # "test" (puede ser nil)
215
+ else
216
+ # ESCENARIO B: Ruta Colección (ej. foo/bar/algo o api/v1/users)
217
+ controller_name = segments.join('/')
218
+ id = nil
219
+ action = nil
220
+ end
221
+
222
+ # 3. Inferimos la acción si no hay una explícita en la ruta
223
+ unless action
224
+ action = case method.to_s.upcase
225
+ when 'GET' then id ? 'show' : 'index'
226
+ when 'POST' then 'create'
227
+ when 'PUT', 'PATCH' then 'update'
228
+ when 'DELETE' then 'destroy'
229
+ else id ? 'show' : 'index'
230
+ end
217
231
  end
218
232
 
219
- # Inyectamos el ID en los params si existe en la ruta
233
+ # 4. Inyectamos el ID en los parámetros para que el Controller lo tenga fácil
220
234
  query_params['id'] = id if id
221
235
 
222
236
  { controller: controller_name, action: action, id: id, params: query_params }
@@ -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] ⚙️ Exchange Opts: #{final_x_opts}")
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BugBunny
4
- VERSION = "3.1.4"
4
+ VERSION = "3.1.5"
5
5
  end
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
4
+ version: 3.1.5
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-21 00:00:00.000000000 Z
11
+ date: 2026-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny