bug_bunny 4.6.1 → 4.7.0

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/pr.md +42 -0
  3. data/.claude/commands/release.md +41 -0
  4. data/.claude/commands/rubocop.md +22 -0
  5. data/.claude/commands/test.md +28 -0
  6. data/.claude/commands/yard.md +46 -0
  7. data/CHANGELOG.md +37 -15
  8. data/CLAUDE.md +228 -0
  9. data/README.md +154 -221
  10. data/Rakefile +19 -3
  11. data/docs/concepts.md +140 -0
  12. data/docs/howto/controller.md +194 -0
  13. data/docs/howto/middleware_client.md +119 -0
  14. data/docs/howto/middleware_consumer.md +127 -0
  15. data/docs/howto/rails.md +214 -0
  16. data/docs/howto/resource.md +200 -0
  17. data/docs/howto/routing.md +133 -0
  18. data/docs/howto/testing.md +259 -0
  19. data/docs/howto/tracing.md +119 -0
  20. data/lib/bug_bunny/client.rb +41 -18
  21. data/lib/bug_bunny/configuration.rb +63 -0
  22. data/lib/bug_bunny/consumer.rb +51 -37
  23. data/lib/bug_bunny/consumer_middleware.rb +14 -5
  24. data/lib/bug_bunny/controller.rb +29 -4
  25. data/lib/bug_bunny/exception.rb +4 -0
  26. data/lib/bug_bunny/observability.rb +23 -1
  27. data/lib/bug_bunny/resource.rb +31 -21
  28. data/lib/bug_bunny/routing/route.rb +6 -1
  29. data/lib/bug_bunny/routing/route_set.rb +30 -3
  30. data/lib/bug_bunny/session.rb +18 -11
  31. data/lib/bug_bunny/version.rb +1 -1
  32. data/lib/bug_bunny.rb +1 -0
  33. data/mejoras.md +33 -0
  34. data/plan_test.txt +63 -0
  35. data/spec/integration/client_spec.rb +117 -0
  36. data/spec/integration/consumer_middleware_spec.rb +86 -0
  37. data/spec/integration/controller_spec.rb +140 -0
  38. data/spec/integration/error_handling_spec.rb +57 -0
  39. data/spec/integration/infrastructure_spec.rb +52 -0
  40. data/spec/integration/resource_spec.rb +113 -0
  41. data/spec/spec_helper.rb +70 -0
  42. data/spec/support/bunny_mocks.rb +18 -0
  43. data/spec/support/integration_helper.rb +87 -0
  44. data/spec/unit/client_session_pool_spec.rb +159 -0
  45. data/spec/unit/configuration_spec.rb +164 -0
  46. data/spec/unit/consumer_middleware_spec.rb +129 -0
  47. data/spec/unit/consumer_spec.rb +90 -0
  48. data/spec/unit/controller_after_action_spec.rb +155 -0
  49. data/spec/unit/observability_spec.rb +167 -0
  50. data/spec/unit/resource_attributes_spec.rb +69 -0
  51. data/spec/unit/session_spec.rb +98 -0
  52. metadata +36 -3
  53. data/sig/bug_bunny.rbs +0 -4
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'support/bunny_mocks'
5
+
6
+ RSpec.describe BugBunny::Session do
7
+ include BunnyMocks
8
+
9
+ let(:channel) { BunnyMocks::FakeChannel.new(false).tap { |c| c.open = true } }
10
+ let(:connection) { BunnyMocks::FakeConnection.new(true, channel) }
11
+ let(:session) { described_class.new(connection) }
12
+
13
+ describe '#channel' do
14
+ context 'cuando el canal está abierto' do
15
+ it 'retorna el canal existente sin crear uno nuevo (fast path)' do
16
+ first = session.channel
17
+ second = session.channel
18
+ expect(second).to be(first)
19
+ end
20
+ end
21
+
22
+ context 'cuando el canal está cerrado' do
23
+ it 'crea un canal nuevo' do
24
+ session.channel # inicializa
25
+
26
+ new_channel = BunnyMocks::FakeChannel.new(true)
27
+ session.instance_variable_get(:@channel).open = false
28
+ connection.channel_to_return = new_channel
29
+
30
+ expect(session.channel).to be(new_channel)
31
+ end
32
+ end
33
+
34
+ context 'con múltiples threads simultáneos' do
35
+ it 'llama a create_channel! exactamente una vez aunque varios threads compitan' do
36
+ fresh_session = described_class.new(connection)
37
+ create_count = Concurrent::AtomicFixnum.new(0)
38
+
39
+ fresh_session.define_singleton_method(:create_channel!) do
40
+ create_count.increment
41
+ super()
42
+ end
43
+
44
+ threads = 10.times.map { Thread.new { fresh_session.channel } }
45
+ threads.each(&:join)
46
+
47
+ expect(create_count.value).to eq(1)
48
+ end
49
+ end
50
+
51
+ context 'cuando la conexión está cerrada' do
52
+ it 'reconecta transparentemente' do
53
+ closed_conn = BunnyMocks::FakeConnection.new(false, channel)
54
+ s = described_class.new(closed_conn)
55
+
56
+ s.channel
57
+
58
+ expect(closed_conn.open?).to be(true)
59
+ end
60
+
61
+ it 'lanza CommunicationError si la reconexión falla' do
62
+ bad_conn = BunnyMocks::FakeConnection.new(false, channel)
63
+ bad_conn.define_singleton_method(:start) { raise RuntimeError, 'refused' }
64
+
65
+ s = described_class.new(bad_conn)
66
+
67
+ expect { s.channel }.to raise_error(BugBunny::CommunicationError)
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#close' do
73
+ it 'cierra el canal y lo nilifica' do
74
+ session.channel
75
+ session.close
76
+
77
+ expect(session.instance_variable_get(:@channel)).to be_nil
78
+ end
79
+
80
+ it 'es idempotente — no explota si se llama dos veces' do
81
+ session.channel
82
+ session.close
83
+ expect { session.close }.not_to raise_error
84
+ end
85
+
86
+ it 'es thread-safe junto con #channel' do
87
+ errors = []
88
+
89
+ threads = [
90
+ Thread.new { 10.times { session.channel rescue nil } },
91
+ Thread.new { 10.times { session.close rescue nil } }
92
+ ]
93
+ threads.each(&:join)
94
+
95
+ expect(errors).to be_empty
96
+ end
97
+ end
98
+ 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: 4.6.1
4
+ version: 4.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gabix
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-03-31 00:00:00.000000000 Z
11
+ date: 2026-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -229,9 +229,24 @@ executables: []
229
229
  extensions: []
230
230
  extra_rdoc_files: []
231
231
  files:
232
+ - ".claude/commands/pr.md"
233
+ - ".claude/commands/release.md"
234
+ - ".claude/commands/rubocop.md"
235
+ - ".claude/commands/test.md"
236
+ - ".claude/commands/yard.md"
232
237
  - CHANGELOG.md
238
+ - CLAUDE.md
233
239
  - README.md
234
240
  - Rakefile
241
+ - docs/concepts.md
242
+ - docs/howto/controller.md
243
+ - docs/howto/middleware_client.md
244
+ - docs/howto/middleware_consumer.md
245
+ - docs/howto/rails.md
246
+ - docs/howto/resource.md
247
+ - docs/howto/routing.md
248
+ - docs/howto/testing.md
249
+ - docs/howto/tracing.md
235
250
  - initializer_example.rb
236
251
  - lib/bug_bunny.rb
237
252
  - lib/bug_bunny/client.rb
@@ -255,7 +270,25 @@ files:
255
270
  - lib/bug_bunny/version.rb
256
271
  - lib/generators/bug_bunny/install/install_generator.rb
257
272
  - lib/generators/bug_bunny/install/templates/initializer.rb
258
- - sig/bug_bunny.rbs
273
+ - mejoras.md
274
+ - plan_test.txt
275
+ - spec/integration/client_spec.rb
276
+ - spec/integration/consumer_middleware_spec.rb
277
+ - spec/integration/controller_spec.rb
278
+ - spec/integration/error_handling_spec.rb
279
+ - spec/integration/infrastructure_spec.rb
280
+ - spec/integration/resource_spec.rb
281
+ - spec/spec_helper.rb
282
+ - spec/support/bunny_mocks.rb
283
+ - spec/support/integration_helper.rb
284
+ - spec/unit/client_session_pool_spec.rb
285
+ - spec/unit/configuration_spec.rb
286
+ - spec/unit/consumer_middleware_spec.rb
287
+ - spec/unit/consumer_spec.rb
288
+ - spec/unit/controller_after_action_spec.rb
289
+ - spec/unit/observability_spec.rb
290
+ - spec/unit/resource_attributes_spec.rb
291
+ - spec/unit/session_spec.rb
259
292
  - test/integration/infrastructure_test.rb
260
293
  - test/integration/manual_client_test.rb
261
294
  - test/test_helper.rb
data/sig/bug_bunny.rbs DELETED
@@ -1,4 +0,0 @@
1
- module BugBunny
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end