flu-rails 8.0.4 → 8.0.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: 5fadf301a677ec0ec47d67f9eb8159aac7dfab535c268030331ce4d54c391e58
4
- data.tar.gz: 90c8b9dc6c71fa9f01630b1e183114132ec1d63735cdc2cb62c5974750f3ff49
3
+ metadata.gz: 24d179705111c94185f7421297a692e1f962feeef2a9c2132a04e744d70a6503
4
+ data.tar.gz: 93526441dcfaea7cc3a5be4795c5e86cdb9a4acdbaf95b825e530259b3c89d64
5
5
  SHA512:
6
- metadata.gz: 2a8f50d7eb2796ce8408f3a1ca36b68d55020d8858134fc136cef7be6fcb7978c316e99298a2d394ef0f0555602c1a955b3ff497b0a72e9b1f49ddf23ec4e1b8
7
- data.tar.gz: dbc5b57979a4ebe601b8df0c26822c7dfa127c44f7292b97b654aff0363d04266552a60c2bda0d0ea00b2865421e47677d4f66592bf8c9e36bf6820f1ea290e8
6
+ metadata.gz: bd84b67b67c9f209fbab6c5309d719719e3d9f19df12e1d7816acc6690c084dad052e8590cc39b85cfcc9477b6c187d1ec352a3a8e55a932c5f51d22c062e458
7
+ data.tar.gz: e7e0eab197a600c06a10c1bb6ec801499cfe3d55327e94232b565830b5ee6fa69c4a5bf7c19ab3082f0492917d83e6c36581ce53600d5cbf9ef0259df1b620b1
data/CHANGELOG.md CHANGED
@@ -5,6 +5,52 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ### [8.0.5] - 2026-08-03
9
+
10
+ **Fixed**
11
+
12
+ * `QueueRepository#find_all` no longer lists queues across every vhost on the broker. It called `list_queues` without a vhost, which lists every vhost's queues -- on a broker shared with other applications, that meant every other application's queues too, not just this one's.
13
+ * Sanitize the event name before building the routing key.
14
+ * [Breaking change?] Publish only Flu's own events from `flu_publish_events!`. It called `run_callbacks(:commit)`, which runs every `after_commit` callback registered on the record (including the host application's own (mailers, jobs, cache invalidation)) rather than just the one `track_entity_changes` installs. It now calls `flu_commit_changes` directly, the same way the real `after_commit` callback does.
15
+ * Guard the railtie require on `Rails::Railtie` rather than on `Rails`. Gems such as `rails-html-sanitizer` define an empty `Rails` namespace, which `is_testing_environment?` already accounted for a few lines below -- the railtie require itself did not, and raised `NameError: uninitialized constant Rails::Railtie` in that case.
16
+ * Stop assuming `ActionDispatch` is loaded when serializing an event. `Event#to_json` referenced `ActionDispatch::Http::UploadedFile` unconditionally to special-case uploaded files, on every value it serialized. A plain script that builds and serializes an event without the rest of Rails loaded raised `NameError: uninitialized constant Flu::Event::ActionDispatch` on the very first field.
17
+ * Track Single Table Inheritance subclasses. ActiveRecord hands the callbacks registered by `track_entity_changes` down to subclasses, but the class-level instance variables holding their settings were not inherited, so every save of an STI subclass of a tracked model raised `NoMethodError` on `nil`. `flu_is_tracked`, `flu_user_metadata_lambdas`, `flu_ignored_model_changes` and `flu_overriden_emitter_lambda` are now declared with `class_attribute`, which a subclass inherits until it sets its own value.
18
+ * Always clear the per-request tracking state, even when an action raises. The request id and the entity metadata are stored in thread-local storage and were cleared from an `after_action`, which does not run when the action raises. Since application servers reuse their threads, a failed request left its id behind for the next request served by that same thread, whose entity changes were then attributed to a request that had already died. `track_requests` now installs a single `around_action` that clears both from an `ensure` block.
19
+
20
+ **Added**
21
+
22
+ * `rabbitmq_vhost` configuration option (default `"/"`), used by both `EventPublisher`'s AMQP connection and `QueueRepository`'s management API calls, to operate on a vhost other than the default.
23
+ * `Flu::Error`, the base class of every error this gem raises on its own, and `Flu::NotConnectedError`.
24
+
25
+ **Changed**
26
+
27
+ * `EventFactory` no longer serializes an event to JSON before logging it, unless debug logging is actually enabled.
28
+ * Publishing through a publisher that holds no connection now raises `Flu::NotConnectedError`, naming what to call and the option that turns the automatic connection off, instead of a `NoMethodError` on `nil`.
29
+ * A `request` event is now built once every other `after_action` has run, so its `duration` covers them too. An action that raises still publishes nothing.
30
+ * `EventPublisher` opens one Bunny channel per thread instead of sharing a single one.
31
+ * `EventPublisher#connected?` now reports on the connection alone. The exchange is declared per thread, so it is no longer a single object whose absence says anything about the publisher as a whole.
32
+
33
+ **Performance**
34
+
35
+ * Optimize `deep_camelize` to use `each_with_object` and `ActiveSupport::Inflector#camelize` to improve performance and reduce memory consumption.
36
+ * Add `# frozen_string_literal: true` to all ruby files to reduce string allocations.
37
+
38
+ **Tests**
39
+
40
+ * Cover `rabbitmq_vhost` against a real broker: `EventPublisher#connect` fails rather than silently falling back to the default vhost when it points at one that does not exist, and `QueueRepository#find_all` scoped to a dedicated vhost does not see a queue declared on another one -- proving the cross-vhost leak above was real.
41
+ * Cover `duration`, which had no test at all: it is the elapsed wall-clock time since `request_start_time`, and a real controller request emits one that is a small, non-negative `Float`.
42
+ * Cover `Event#to_routing_key`: dots are stripped from the name, spaces are left untouched, a name that would push the routing key past 255 characters is truncated with a warning through `Flu.logger`, and none of this raises when `Flu.logger` was never set. Cover the same against a real broker: a name with dots is delivered under a single routing-key segment, and a 300-character name that used to make Bunny raise is published and delivered instead.
43
+ * Cover that `flu_publish_events!` does not run a host application's own `after_commit` callback, registered on the record's singleton class, exactly the way `run_callbacks(:commit)` used to run it too.
44
+ * Cover loading `flu-rails` with an empty `Rails` namespace defined, through the same kind of subprocess as the `ActionDispatch` example above.
45
+ * Cover that building an entity change, request or manual event does not serialize it when the logger's level is above `DEBUG`.
46
+ * Cover `Event#to_json` without `ActionDispatch` loaded, through a subprocess that never requires actionpack -- the main suite always has it loaded, so this is the only honest way to exercise the guard.
47
+ * Cover which channel a thread publishes on, against a real broker: each thread gets its own, reuses it across publications, and picks up a fresh one after the connection was closed under it.
48
+ * Cover `entity_metadata`, which had no test at all: its lambda is evaluated before the action runs, and its result is cleared afterwards.
49
+ * Cover what a raising action leaves behind in the thread-local tracking state.
50
+ * Add `simplecov` as a development dependency to track and report code coverage.
51
+ * Add support for the `RABBITMQ_VERSION` environment variable in `docker-compose.yml` to allow testing locally against different versions of RabbitMQ.
52
+ * Configure GitHub Actions CI to run the test suite against a matrix of RabbitMQ versions (3.12, 3.13, and 4.0).
53
+
8
54
  ### [8.0.4] - 2026-08-01
9
55
 
10
56
  **Security**
data/README.md CHANGED
@@ -16,7 +16,7 @@ For now, events are generated from:
16
16
  Add the gem to your project's Gemfile:
17
17
 
18
18
  ```ruby
19
- gem "flu-rails"
19
+ gem "flu-rails", "8.0.5"
20
20
  ```
21
21
 
22
22
  Then, create an initializer into your Rails app (`config/initializers/flu-rails.rb`)
@@ -43,6 +43,7 @@ Each configuration is detailed below.
43
43
  * RabbitMQ: no specific version is required by `flu-rails` itself. The broker is reached through
44
44
  `bunny` 3.x and `rabbitmq_http_api_client` 3.x, which target the
45
45
  [currently supported RabbitMQ release series](https://www.rabbitmq.com/release-information).
46
+ It is actively tested against RabbitMQ 3.12, 3.13, and 4.x.
46
47
 
47
48
  ## Usage
48
49
 
@@ -187,6 +188,14 @@ your machine, start a broker first:
187
188
  $ bundle exec rspec
188
189
  ```
189
190
 
191
+ You can optionally specify the RabbitMQ version to use by providing the `RABBITMQ_VERSION` environment variable (defaults to `4-management-alpine`):
192
+
193
+ ```
194
+ $ RABBITMQ_VERSION=3.13-management-alpine docker compose up -d rabbitmq
195
+ ```
196
+
197
+ Our continuous integration pipeline (via GitHub Actions) systematically runs the integration test suite against a matrix of RabbitMQ versions (3.12, 3.13, and 4.x) to ensure seamless backward and forward compatibility.
198
+
190
199
  Without one, those examples are reported as skipped and the rest of the suite still runs. Set
191
200
  `FLU_REQUIRE_RABBITMQ` to turn that skip into a failure — this is what the CI workflow does, so that
192
201
  a build cannot report success without having reached RabbitMQ:
@@ -304,8 +313,8 @@ scoped RubyGems credential.
304
313
  3. Tag the commit and push the tag:
305
314
 
306
315
  ```
307
- $ git tag -a v8.0.4 -m "Version 8.0.4"
308
- $ git push origin v8.0.4
316
+ $ git tag -a v8.0.5 -m "Version 8.0.5"
317
+ $ git push origin v8.0.5
309
318
  ```
310
319
 
311
320
  The workflow then checks that the tag matches `Flu::VERSION`, runs the tests, builds the gem
data/flu-rails.gemspec CHANGED
@@ -35,5 +35,6 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency "ostruct", "~> 0.6"
36
36
  spec.add_development_dependency "rake", ">= 13.0"
37
37
  spec.add_development_dependency "rspec", "~> 3.13"
38
+ spec.add_development_dependency "simplecov"
38
39
  spec.add_development_dependency "sqlite3", "~> 2.9"
39
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/inflections"
2
4
  require "active_support/core_ext/time/zones"
3
5
  require "random/formatter"
@@ -69,19 +71,17 @@ module Flu
69
71
  end
70
72
  end
71
73
 
72
- before_action do
74
+ prepend_around_action do |_controller, action|
73
75
  flu_define_request_id
74
- @request_start_time = Time.zone.now
75
- end
76
- prepend_before_action do
77
76
  flu_define_request_entity_metadata
78
- end
79
- prepend_after_action do
80
- flu_track_request
81
- flu_remove_request_entity_metadata
82
- end
83
- after_action do
84
- flu_remove_request_id
77
+ @request_start_time = Time.zone.now
78
+ begin
79
+ action.call
80
+ flu_track_request
81
+ ensure
82
+ flu_remove_request_entity_metadata
83
+ flu_remove_request_id
84
+ end
85
85
  end
86
86
  end
87
87
  end
@@ -1,9 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/object/try"
2
4
 
3
5
  module Flu
4
6
  class ActiveRecordExtender
5
7
  def self.extend_models(event_factory, event_publisher)
6
8
  ActiveRecord::Base.class_eval do
9
+ unless singleton_class.method_defined?(:flu_is_tracked)
10
+ class_attribute :flu_is_tracked, instance_accessor: false, default: false
11
+ class_attribute :flu_user_metadata_lambdas, instance_accessor: false, default: {}.freeze
12
+ class_attribute :flu_ignored_model_changes, instance_accessor: false, default: [].freeze
13
+ class_attribute :flu_overriden_emitter_lambda, instance_accessor: false, default: nil
14
+ end
15
+
7
16
  define_singleton_method(:track_entity_changes) do |options = {}|
8
17
  self.flu_is_tracked = true
9
18
  self.flu_user_metadata_lambdas = options.fetch(:user_metadata, {})
@@ -17,38 +26,6 @@ module Flu
17
26
  after_rollback { flu_rollback_changes }
18
27
  end
19
28
 
20
- def self.flu_ignored_model_changes=(ignored_model_changes)
21
- @flu_ignored_model_changes = ignored_model_changes
22
- end
23
-
24
- def self.flu_ignored_model_changes
25
- @flu_ignored_model_changes
26
- end
27
-
28
- def self.flu_overriden_emitter_lambda=(overriden_emitter_lambda)
29
- @flu_overriden_emitter_lambda = overriden_emitter_lambda
30
- end
31
-
32
- def self.flu_overriden_emitter_lambda
33
- @flu_overriden_emitter_lambda
34
- end
35
-
36
- def self.flu_user_metadata_lambdas=(user_metadata_lambdas)
37
- @flu_user_metadata_lambdas = user_metadata_lambdas
38
- end
39
-
40
- def self.flu_user_metadata_lambdas
41
- @flu_user_metadata_lambdas
42
- end
43
-
44
- def self.flu_is_tracked=(is_tracked)
45
- @flu_is_tracked = is_tracked
46
- end
47
-
48
- def self.flu_is_tracked
49
- @flu_is_tracked || false
50
- end
51
-
52
29
  def self.flu_association_columns
53
30
  @flu_association_columns ||= reflect_on_all_associations(:belongs_to).flat_map do |association|
54
31
  column_names = [association.foreign_key]
@@ -61,8 +38,15 @@ module Flu
61
38
  @flu_changes ||= []
62
39
  end
63
40
 
64
- def flu_publish_events!
65
- run_callbacks(:commit)
41
+ # Defined with 'define_method' rather than 'def', for the same reason as the tracking
42
+ # helpers in 'ActionControllerExtender#extend_controllers': a bare 'def' opens a new scope
43
+ # and would not close over 'event_factory' and 'event_publisher'.
44
+ #
45
+ # Without them, publishing manually had no way to call 'flu_commit_changes' directly,
46
+ # and used 'run_callbacks(:commit)' instead, which runs *every* 'after_commit' callback on the record,
47
+ # including the hoste application's own (mailers, jobs, cache invalidation), not just Flu's.
48
+ define_method(:flu_publish_events!) do
49
+ flu_commit_changes(event_factory, event_publisher)
66
50
  end
67
51
 
68
52
  def flu_add_manual_event(name, data)
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flu
2
4
  class Configuration
3
5
  attr_accessor :development_environments,
4
6
  :rejected_user_agents,
5
7
  :logger,
6
8
  :rabbitmq_host,
9
+ :rabbitmq_vhost,
7
10
  :rabbitmq_management_scheme,
8
11
  :rabbitmq_management_port,
9
12
  :rabbitmq_port,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "active_record_extender"
2
4
  require_relative "action_controller_extender"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flu
2
4
  module Dummy
3
5
  class InMemoryEventPublisher < Flu::EventPublisher
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flu
4
+ class Error < StandardError
5
+ end
6
+
7
+ class NotConnectedError < Error
8
+ end
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
 
3
5
  module Flu
@@ -22,8 +24,11 @@ module Flu
22
24
  @data = data || {}
23
25
  end
24
26
 
27
+ ROUTING_KEY_MAX_LENGTH = 255
28
+
25
29
  def to_routing_key
26
- "#{@meta[:status]}.#{@meta[:emitter]}.#{@meta[:kind]}.#{@meta[:name]}"
30
+ prefix = "#{@meta[:status]}.#{@meta[:emitter]}.#{@meta[:kind]}."
31
+ "#{prefix}#{routing_key_name(prefix.length)}"
27
32
  end
28
33
 
29
34
  def to_json(options=nil)
@@ -67,12 +72,22 @@ module Flu
67
72
 
68
73
  private
69
74
 
75
+ def routing_key_name(prefix_length)
76
+ name = @meta[:name].to_s.delete(".")
77
+ budget = [ROUTING_KEY_MAX_LENGTH - prefix_length, 0].max
78
+ return name if name.length <= budget
79
+
80
+ Flu.logger&.warn("flu-rails: event name '#{@meta[:name]}' was truncated to #{budget} " \
81
+ "characters to keep its routing key within Bunny's #{ROUTING_KEY_MAX_LENGTH}-character limit.")
82
+ name[0, budget]
83
+ end
84
+
70
85
  def map_complex_object(object)
71
86
  if object.is_a?(Array)
72
87
  map_array(object)
73
88
  elsif object.is_a?(Hash)
74
89
  map_hash(object)
75
- elsif object.is_a?(ActionDispatch::Http::UploadedFile)
90
+ elsif defined?(ActionDispatch::Http::UploadedFile) && object.is_a?(ActionDispatch::Http::UploadedFile)
76
91
  map_file(object)
77
92
  else
78
93
  object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "securerandom"
2
4
  require "active_support/core_ext/object/blank"
3
5
  require "active_support/core_ext/string/inflections"
@@ -20,7 +22,7 @@ module Flu
20
22
  raise ArgumentError, "data must have an controller_name" if !data.has_key?(:controller_name) || data[:controller_name].empty?
21
23
  name = "request to #{data[:action_name]} #{data[:controller_name]}"
22
24
  event = build_event(name, :request, data)
23
- @logger.debug("Track action: #{JSON.pretty_generate(event)}")
25
+ @logger.debug { "Track action: #{event.to_json}" }
24
26
  event
25
27
  end
26
28
 
@@ -31,7 +33,7 @@ module Flu
31
33
  raise ArgumentError, "data must have an entity_name" if !data.has_key?(:entity_name) || data[:entity_name].empty?
32
34
  name = "#{data[:action_name]} #{data[:entity_name]}"
33
35
  event = build_event(name, :entity_change, data)
34
- @logger.debug("Track change: " + JSON.pretty_generate(event))
36
+ @logger.debug { "Track change: #{event.to_json}" }
35
37
  event
36
38
  end
37
39
 
@@ -40,7 +42,7 @@ module Flu
40
42
  raise ArgumentError, "data must be a hash" if !data.is_a?(Hash)
41
43
  raise ArgumentError, "name must not be nil or empty" if name.nil? || name.empty?
42
44
  event = build_event(name.to_s, :manual, data)
43
- @logger.debug("Track manual: " + JSON.pretty_generate(event))
45
+ @logger.debug { "Track manual: #{event.to_json}" }
44
46
  event
45
47
  end
46
48
 
@@ -91,25 +93,16 @@ module Flu
91
93
  def deep_camelize(value)
92
94
  case value
93
95
  when Array
94
- value.map { |v| deep_camelize v }
96
+ value.map { |v| deep_camelize(v) }
95
97
  when Hash
96
- value.reduce({}) do |camelized_hash, (k,v)|
97
- camelized_hash[camelize(sanitize(k.to_s), false)] = deep_camelize v
98
- camelized_hash
98
+ value.each_with_object({}) do |(k, v), camelized_hash|
99
+ camelized_hash[sanitize(k.to_s).camelize(:lower)] = deep_camelize(v)
99
100
  end
100
101
  else
101
102
  sanitize(value)
102
103
  end
103
104
  end
104
105
 
105
- def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
106
- if first_letter_in_uppercase
107
- lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
108
- else
109
- (lower_case_and_underscored_word[0] || "") + camelize(lower_case_and_underscored_word)[1..-1]
110
- end
111
- end
112
-
113
106
  def extract_associations_from(entity, association_columns)
114
107
  association_columns.reduce({}) do |associations, column_name|
115
108
  associations[column_name] = entity[column_name]
@@ -1,19 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bunny"
4
+ require_relative "errors"
2
5
  require_relative "event"
3
6
 
4
7
 
5
8
  module Flu
6
9
  class EventPublisher
10
+ NOT_CONNECTED_MESSAGE = "no connection to RabbitMQ: 'connect' was never called, or " \
11
+ "'disconnect' was. The railtie calls it at boot unless " \
12
+ "'auto_connect_to_exchange' is false."
13
+
7
14
  def initialize(configuration)
8
15
  @logger = configuration.logger
9
16
  @configuration = configuration
17
+ @exchange_key = :"flu_exchange_#{object_id}" # Channels are cached per thread
10
18
  end
11
19
 
12
20
  def publish(event, persistent=true)
13
21
  routing_key = event.to_routing_key
14
- @logger.debug("Publishing event with id '#{event.id}' with routing key: #{routing_key}")
15
- @exchange.publish(event.to_json, routing_key: routing_key, persistent: persistent)
16
- @logger.debug("Event published.")
22
+ @logger.debug { "Publishing event with id '#{event.id}' with routing key: #{routing_key}" }
23
+ exchange.publish(event.to_json, routing_key: routing_key, persistent: persistent)
24
+ @logger.debug { "Event published." }
17
25
  end
18
26
 
19
27
  def connect
@@ -32,43 +40,57 @@ module Flu
32
40
  end
33
41
 
34
42
  def connected?
35
- if @connection.nil? || @exchange.nil?
36
- false
37
- else
38
- @connection.open?
39
- end
43
+ !@connection.nil? && @connection.open?
40
44
  end
41
45
 
42
- # Closing the connection closes the channel opened on it, and stops the heartbeat and recovery
43
- # threads Bunny runs alongside it.
44
- # The guard is on the connection alone, not on 'connected?': a connection that was opened before
45
- # the exchange could be declared still has to be closed.
46
+ # Closing the connection closes every channel opened on it, and stops the heartbeat and
47
+ # recovery threads Bunny runs alongside it.
48
+ # The guard is on the connection alone: a connection that was opened before the exchange could
49
+ # be declared still has to be closed.
46
50
  def disconnect
47
51
  if !@connection.nil? && @connection.open?
48
- @connection.close
52
+ @connection.close
49
53
  end
50
54
  @connection = nil
51
- @channel = nil
52
- @exchange = nil
55
+ Thread.current[@exchange_key] = nil
53
56
  end
54
57
 
55
58
  private
56
59
 
60
+ # One channel per thread rather than one for the whole publisher.
61
+ # Bunny serialises every publication on the channel's own mutex.
62
+ #
63
+ # No bookkeeping of the channels handed out is needed.
64
+ # Closing the connection closes all of them, so a thread holding a closed channel simply opens a new one on its next publication:
65
+ # 'disconnect' and a reconnection are both covered without reaching into other threads.
66
+ # Only the absence of a connection is reported here. A connection that exists but is closed or
67
+ # recovering is Bunny's story to tell, and its own error says more about it than this one could.
68
+ def exchange
69
+ cached = Thread.current[@exchange_key]
70
+ return cached if cached && cached.channel.open?
71
+ raise NotConnectedError, NOT_CONNECTED_MESSAGE if @connection.nil?
72
+ Thread.current[@exchange_key] = declare_exchange
73
+ end
74
+
75
+ def declare_exchange
76
+ channel = @connection.create_channel
77
+ channel.topic(@configuration.rabbitmq_exchange_name,
78
+ durable: @configuration.rabbitmq_exchange_durable)
79
+ end
80
+
57
81
  def connect_to_exchange
58
82
  options = {
59
83
  host: @configuration.rabbitmq_host,
84
+ vhost: @configuration.rabbitmq_vhost,
60
85
  port: @configuration.rabbitmq_port&.to_i,
61
86
  user: @configuration.rabbitmq_user,
62
87
  password: @configuration.rabbitmq_password,
63
88
  automatically_recover: true
64
89
  }.merge(@configuration.bunny_options || {})
65
-
90
+
66
91
  @connection = Bunny.new(options)
67
92
  @connection.start
68
- @channel = @connection.create_channel
69
- @exchange = @channel.send(:topic,
70
- @configuration.rabbitmq_exchange_name,
71
- durable: @configuration.rabbitmq_exchange_durable)
93
+ Thread.current[@exchange_key] = declare_exchange
72
94
  end
73
95
  end
74
96
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rabbitmq/http/client"
2
4
 
3
5
  module Flu
@@ -9,23 +11,23 @@ module Flu
9
11
  end
10
12
 
11
13
  def find_all
12
- @management_client.list_queues
14
+ @management_client.list_queues(@configuration.rabbitmq_vhost)
13
15
  end
14
16
 
15
17
  def find_queue(name)
16
- @management_client.queue_info("/", name)
18
+ @management_client.queue_info(@configuration.rabbitmq_vhost, name)
17
19
  end
18
20
 
19
21
  def find_bindings_for_queue(name)
20
- @management_client.list_queue_bindings("/", name)
22
+ @management_client.list_queue_bindings(@configuration.rabbitmq_vhost, name)
21
23
  end
22
24
 
23
25
  def purge_queue(name)
24
- @management_client.purge_queue("/", name)
26
+ @management_client.purge_queue(@configuration.rabbitmq_vhost, name)
25
27
  end
26
28
 
27
29
  def delete_queue(name)
28
- @management_client.delete_queue("/", name)
30
+ @management_client.delete_queue(@configuration.rabbitmq_vhost, name)
29
31
  end
30
32
 
31
33
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flu
2
4
  class Railtie < Rails::Railtie
3
5
  railtie_name :flu
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flu
2
4
  module Util
3
5
  class ExportService
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flu
2
- VERSION = "8.0.4"
4
+ VERSION = "8.0.5"
3
5
  end
data/lib/flu-rails.rb CHANGED
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "logger"
2
4
  require "json"
3
5
  require "active_support/core_ext/module/introspection"
4
6
  require_relative "flu-rails/version"
7
+ require_relative "flu-rails/errors"
5
8
  require_relative "flu-rails/event"
6
9
  require_relative "flu-rails/event_factory"
7
10
  require_relative "flu-rails/queue_repository"
@@ -10,7 +13,7 @@ require_relative "flu-rails/core_ext"
10
13
  require_relative "flu-rails/event_publisher"
11
14
  require_relative "flu-rails/util"
12
15
  require_relative "flu-rails/dummy/in_memory_event_publisher"
13
- require_relative "flu-rails/railtie" if defined?(Rails)
16
+ require_relative "flu-rails/railtie" if defined?(Rails::Railtie)
14
17
 
15
18
  module Flu
16
19
  def self.configure
@@ -87,6 +90,7 @@ module Flu
87
90
  config.rejected_user_agents = []
88
91
  config.logger = ::Logger.new(STDOUT)
89
92
  config.rabbitmq_host = "localhost"
93
+ config.rabbitmq_vhost = "/"
90
94
  config.rabbitmq_port = 5672
91
95
  config.rabbitmq_management_scheme = "http"
92
96
  config.rabbitmq_management_port = 15672
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flu-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.4
4
+ version: 8.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loïc Vigneron
@@ -152,6 +152,20 @@ dependencies:
152
152
  - - "~>"
153
153
  - !ruby/object:Gem::Version
154
154
  version: '3.13'
155
+ - !ruby/object:Gem::Dependency
156
+ name: simplecov
157
+ requirement: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
155
169
  - !ruby/object:Gem::Dependency
156
170
  name: sqlite3
157
171
  requirement: !ruby/object:Gem::Requirement
@@ -185,6 +199,7 @@ files:
185
199
  - lib/flu-rails/configuration.rb
186
200
  - lib/flu-rails/core_ext.rb
187
201
  - lib/flu-rails/dummy/in_memory_event_publisher.rb
202
+ - lib/flu-rails/errors.rb
188
203
  - lib/flu-rails/event.rb
189
204
  - lib/flu-rails/event_factory.rb
190
205
  - lib/flu-rails/event_publisher.rb