pgbus 0.11.0 → 0.11.1

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: 44b8e6016eb94d129ba3f90831ee6e3f8eb213c928e61766c35fa4641f0a518b
4
- data.tar.gz: d35475deb1eaaf59e893c7096b10bc85498482f5940fc099e5add48af54aecbd
3
+ metadata.gz: a52dc949281b6f2f1e9c847d38709fcc2723badd12370486faeb68b40ed55c42
4
+ data.tar.gz: 70a75a14bfe2225f63846314cbb60c0942e86b966c14b20e43eec74afc63adef
5
5
  SHA512:
6
- metadata.gz: db2122fe97f2b77dd6812e5e9a5264850b4eb84ff3c6094cc2c0e11a148989fa3ae502664e040da26b1ea1bf11b764c2b1f9659a58f9d4a6b663be54c1027cba
7
- data.tar.gz: 597210a0238131f0a7912b0cf135dc4d89ce66ab830354dca3b3805dbc70a9ccbd2106830dea85b17c68be73fb79868ff9c43d27813e84e6f457dfbe996107d3
6
+ metadata.gz: dc59f389bf2b5e20b2e75a7a2c47301c242ea0b5857a240e5a59db3177effe34cbe694903d4396b07ef3ca67699f578a5d6b6d95f61d4318169ac477f237b526
7
+ data.tar.gz: a5a6a076c6cadb857c8690ef7d1363934c7f73bd76e8d91a87a936a91d05c4146c12bb67b5637204995d0ddef540833a8983ca4dd3d5ef1034a7b88473aa1e61
data/CHANGELOG.md CHANGED
@@ -32,6 +32,8 @@
32
32
 
33
33
  ### Fixed
34
34
 
35
+ - **Migration generators now route to the pgbus database when `connects_to` is configured, even without an explicit `--database` (issue #344).** `rails g pgbus:add_stream_queues` (and every sibling generator via `Generators::MigrationPath`) keyed the separate-database decision purely on the `--database` flag. An app that had already set `config.connects_to = { database: { writing: :pgbus } }` (so its pgbus migrations live in `db/pgbus_migrate/` per database.yml's `migrations_paths:`) still got the migration written to the **primary** DB's `db/migrate/` on a bare invocation — where it then ran against the wrong database — and the "Next steps" output told the operator to run `rails db:migrate` instead of `rails db:migrate:pgbus`. `MigrationPath` now auto-detects the target database from `connects_to` (via the existing `DatabaseTargetDetector`: runtime config → initializer scan → application.rb scan) when `--database` is absent; an explicit `--database` still wins. The detected name drives both the migration path (resolving `migrations_paths` for that database, falling back to the `db/pgbus_migrate` convention) and the `db:migrate:<name>` suffix in every generator's post-install output. An app with no separate database is unaffected. Refs #344.
36
+ - **`extract_ar_connection_hash` no longer forces `host: "localhost"` / `port: 5432` on a socket-based (host-less) database.yml — pgmq's connections now match ActiveRecord's on Unix-socket dev setups (issue #343).** A local database.yml with no `host:` is a Unix-socket connection: ActiveRecord connects via libpq's default socket (`PGHOST` / the default socket dir), but pgbus's AR-config extraction defaulted the absent `host`/`port` to TCP `localhost:5432`, silently diverging from AR and pointing pgmq's dedicated raw connections at a *different* server (or nothing) on any machine where the socket dir isn't `localhost`. Apps on socket-based dev DBs therefore couldn't use the AR-extraction path at all and had to pin an explicit `connection_params` Hash whose only real job was *not* defaulting `host` (cosmos carried an `after_initialize` block for exactly this). The two fallbacks are dropped: `host`/`port` now pass through as-is and `.compact` removes them when absent, so libpq applies its own socket defaults and matches AR. A config that *does* set `host`/`port` is byte-identical to before. Refs #343.
35
37
  - **`config.log_format` no longer breaks `ActiveSupport::TaggedLogging` — tags are preserved instead of dropped, and `logger.tagged` no longer raises (issue #334).** TaggedLogging works by extending the logger's formatter instance with a module that prepends the current tags. Installing a fresh pgbus formatter (`LogFormatter::JSON`/`Text`) stripped that extension, so `logger.tagged("req-42") { ... }` dropped the tag — and, worse, raised `NoMethodError: undefined method 'tagged'` on the pgbus formatter (a deploy-breaker several apps hit, then worked around with a dedicated `$stdout` logger). `log_format=` now re-extends the replacement formatter with `ActiveSupport::TaggedLogging::Formatter` when the previous one carried it, so tagging keeps working. Refs #334.
36
38
  - **The "Dashboard is accessible without authentication" warning is no longer a false positive when a gating `base_controller_class` is set (issue #334).** The warning fired whenever `web_auth` was nil, ignoring that a non-default `base_controller_class` (e.g. an `AdminController` with its own `before_action`) already gates the dashboard — so apps set a redundant `web_auth` lambda purely to silence the log line. The warning now stays quiet when `base_controller_class` is anything other than the default `::ActionController::Base`. Refs #334.
37
39
  - **`retry_on` on an `:until_executed` job no longer dead-letters the job instead of retrying (issue #333).** The uniqueness key is released only on success or DLQ, but ActiveJob's `retry_on` re-enqueues from *inside* `perform_now` (after incrementing `executions`), while the executor still holds the key. That retry re-enqueue hit the job's own still-held key, was rejected as a duplicate (`JobNotUnique` under `on_conflict: :reject`), and the original message dead-lettered — so a job with both `ensures_uniqueness :until_executed` and `retry_on` lost its retry and DLQ'd on the first transient failure. A retry re-enqueue (`executions > 0`) is now recognized as the same logical job re-acquiring its own key and is allowed through; the existing key row correctly stays held until the job finally succeeds or dead-letters. Cross-job uniqueness (a genuine fresh duplicate, `executions == 0`) is still rejected. Proven end-to-end with a DB-gated integration test (fail-once-then-succeed runs to success exactly once, no `JobNotUnique`, no DLQ, key cleaned up). Refs #333.
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus failed events unique index added!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Failed jobs will now be tracked in the dashboard"
34
34
  say ""
35
35
  end
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus job stats table installed!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Stats collection is enabled by default"
34
34
  say " 3. View insights at /pgbus/insights"
35
35
  say ""
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus job stats latency columns installed!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Queue latency and retry metrics are now tracked automatically"
34
34
  say " 3. View latency insights at /pgbus/insights"
35
35
  say ""
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus job stats queue index added!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. The Insights 'latency by queue' aggregation will now use the index"
34
34
  say " instead of sequentially scanning pgbus_job_stats. Install this on"
35
35
  say " heavy-traffic deployments with a large job stats retention window."
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus outbox installed!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Enable in config: config.outbox_enabled = true"
34
34
  say " 3. Restart pgbus: bin/pgbus start"
35
35
  say ""
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus presence installed!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Use in your code:"
34
34
  say " Pgbus.stream(@room).presence.join(member_id: current_user.id.to_s)"
35
35
  say " Pgbus.stream(@room).presence.members"
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus queue states table installed!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Restart pgbus: bin/pgbus start"
34
34
  say ""
35
35
  end
@@ -33,7 +33,7 @@ module Pgbus
33
33
  say "Pgbus recurring jobs installed!", :green
34
34
  say ""
35
35
  say "Next steps:"
36
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
36
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
37
37
  say " 2. Edit config/recurring.yml to define your recurring tasks"
38
38
  say " 3. Restart pgbus: bin/pgbus start"
39
39
  say ""
@@ -35,7 +35,7 @@ module Pgbus
35
35
  say "streams register themselves on their next broadcast after migrating."
36
36
  say ""
37
37
  say "Next steps:"
38
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
38
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
39
39
  say " 2. Restart pgbus: bin/pgbus start"
40
40
  say ""
41
41
  end
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus stream stats table installed!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Opt in by setting `config.streams_stats_enabled = true` in your"
34
34
  say " pgbus initializer (disabled by default — stream event volume can"
35
35
  say " be high, so stats recording is off unless you ask for it)."
@@ -29,7 +29,7 @@ module Pgbus
29
29
  say "Pgbus uniqueness keys table installed!", :green
30
30
  say ""
31
31
  say "Next steps:"
32
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
32
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
33
33
  say " 2. Add `ensures_uniqueness` to your job classes (DSL is auto-included)"
34
34
  say " 3. Restart pgbus: bin/pgbus start"
35
35
  say ""
@@ -99,7 +99,7 @@ module Pgbus
99
99
 
100
100
  say ""
101
101
  say "Next steps:"
102
- say " 1. Run: rails db:migrate#{":#{database_name}" if separate_database?}"
102
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
103
103
  say " 2. Edit config/initializers/pgbus.rb to configure workers"
104
104
  say " 3. Start processing: bin/pgbus start"
105
105
  say ""
@@ -115,8 +115,11 @@ module Pgbus
115
115
  options[:pgmq_schema_mode]
116
116
  end
117
117
 
118
+ # An explicit --database wins; otherwise fall back to a database already
119
+ # configured via connects_to so a bare re-install targets the right DB
120
+ # and its setup hints/output name it (issue #344).
118
121
  def database_name
119
- options[:database]
122
+ effective_database_name
120
123
  end
121
124
  end
122
125
  end
@@ -34,7 +34,7 @@ module Pgbus
34
34
  say " 3. Drop the old pgbus_job_locks table (8 columns, 3 indexes)"
35
35
  say ""
36
36
  say "Next steps:"
37
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
37
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
38
38
  say " 2. Restart pgbus: bin/pgbus start"
39
39
  say ""
40
40
  end
@@ -1,27 +1,93 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pgbus/generators/database_target_detector"
4
+
3
5
  module Pgbus
4
6
  module Generators
5
7
  # Shared migration path logic for all pgbus generators.
6
8
  #
7
- # When --database is passed, uses Rails' built-in db_migrate_path which
8
- # reads migrations_paths from database.yml. This is the standard Rails
9
- # multi-database mechanism and respects custom paths like db/pgbus_migrate/.
9
+ # A separate pgbus database can be selected two ways:
10
+ #
11
+ # 1. --database=pgbus explicitly on the generator invocation, or
12
+ # 2. the host app has already configured Pgbus with a dedicated database
13
+ # (config.connects_to = { database: { writing: :pgbus } }).
10
14
  #
11
- # Falls back to db/migrate/ when no --database is set (single-database mode).
15
+ # When either applies, migrations go to the separate-database path (e.g.
16
+ # db/pgbus_migrate) and the post-install output names the db:migrate:<name>
17
+ # task. When neither applies, everything falls back to db/migrate.
18
+ #
19
+ # Auto-detecting from connects_to (case 2) fixes issue #344: a bare
20
+ # `rails g pgbus:add_*` in an app configured for a separate database used to
21
+ # silently write to db/migrate and run against the WRONG database.
12
22
  module MigrationPath
13
23
  private
14
24
 
15
25
  def pgbus_migrate_path
16
- if separate_database?
26
+ return "db/migrate" unless separate_database?
27
+
28
+ # --database was passed: Rails' db_migrate_path reads options[:database]
29
+ # and resolves migrations_paths from database.yml. When the database was
30
+ # instead auto-detected from connects_to, options[:database] is nil, so
31
+ # db_migrate_path can't see it — resolve the path for the detected
32
+ # database ourselves.
33
+ if options[:database].present?
17
34
  db_migrate_path
18
35
  else
19
- "db/migrate"
36
+ resolve_detected_migrate_path
20
37
  end
21
38
  end
22
39
 
23
40
  def separate_database?
24
- options[:database].present?
41
+ effective_database_name.present?
42
+ end
43
+
44
+ # The database name that migrations should target: an explicit --database
45
+ # wins; otherwise auto-detect from the app's connects_to configuration.
46
+ def effective_database_name
47
+ return @effective_database_name if defined?(@effective_database_name)
48
+
49
+ @effective_database_name =
50
+ if options[:database].present?
51
+ options[:database]
52
+ else
53
+ DatabaseTargetDetector.new(destination_root: destination_root).detect
54
+ end
55
+ end
56
+
57
+ # The `:name` suffix appended to `rails db:migrate` in post-install
58
+ # output. Empty string for single-database mode so the line reads a plain
59
+ # `rails db:migrate`.
60
+ def migrate_command_suffix
61
+ separate_database? ? ":#{effective_database_name}" : ""
62
+ end
63
+
64
+ # Migrations path for an auto-detected separate database. Rails' own
65
+ # db_migrate_path is keyed on options[:database], which is nil here, so
66
+ # look up migrations_paths for the detected database directly and fall
67
+ # back to the db/pgbus_migrate convention if it isn't in database.yml.
68
+ def resolve_detected_migrate_path
69
+ migrations_path_for(effective_database_name) || "db/pgbus_migrate"
70
+ end
71
+
72
+ def migrations_path_for(database_name)
73
+ return nil unless defined?(::ActiveRecord::Base) && defined?(::Rails) && ::Rails.respond_to?(:env)
74
+
75
+ config = ::ActiveRecord::Base.configurations.configs_for(
76
+ env_name: ::Rails.env,
77
+ name: database_name
78
+ )
79
+ Array(config&.migrations_paths).first
80
+ rescue StandardError => e
81
+ # A missing config for `database_name` isn't an error — configs_for
82
+ # returns nil and we fall back to the db/pgbus_migrate convention. But a
83
+ # genuine failure here (malformed database.yml, an AR API change) would
84
+ # otherwise be invisible, so surface it via the generator's own output
85
+ # the way update_generator#resolve_connection does — not Pgbus.logger
86
+ # (unavailable/inappropriate at generate time; pgbus_failed_events is the
87
+ # runtime job-failure table, not a generator diagnostics sink).
88
+ say " ! could not resolve migrations_paths for #{database_name.inspect}: " \
89
+ "#{e.class}: #{e.message} (falling back to db/pgbus_migrate)", :yellow
90
+ nil
25
91
  end
26
92
  end
27
93
  end
@@ -33,7 +33,7 @@ module Pgbus
33
33
  say "automatically receive these settings."
34
34
  say ""
35
35
  say "Next steps:"
36
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
36
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
37
37
  say " 2. Restart pgbus: bin/pgbus start"
38
38
  say ""
39
39
  end
@@ -36,7 +36,7 @@ module Pgbus
36
36
  say "this setting."
37
37
  say ""
38
38
  say "Next steps:"
39
- say " 1. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
39
+ say " 1. Run: rails db:migrate#{migrate_command_suffix}"
40
40
  say " 2. Restart pgbus: bin/pgbus start"
41
41
  say ""
42
42
  end
@@ -31,7 +31,7 @@ module Pgbus
31
31
  say ""
32
32
  say "Next steps:"
33
33
  say " 1. Review the migration in db/#{separate_database? ? "pgbus_migrate" : "migrate"}/"
34
- say " 2. Run: rails db:migrate#{":#{options[:database]}" if separate_database?}"
34
+ say " 2. Run: rails db:migrate#{migrate_command_suffix}"
35
35
  say ""
36
36
  end
37
37
 
@@ -1439,9 +1439,15 @@ module Pgbus
1439
1439
  # Rails 7.1+ db_config.configuration_hash returns the full config
1440
1440
  config_hash = db_config.configuration_hash
1441
1441
 
1442
+ # Do NOT default host/port here. An absent `host:` in database.yml is a
1443
+ # Unix-socket connection; AR connects via libpq's socket default, so pgmq's
1444
+ # raw connections must too. Forcing TCP localhost:5432 diverges from AR on
1445
+ # socket-based configs (issue #343). `.compact` drops the absent keys and
1446
+ # libpq applies its own defaults (PGHOST / default socket dir). A
1447
+ # present-but-nil port is preserved as nil (also dropped by compact).
1442
1448
  base = {
1443
- host: config_hash[:host] || "localhost",
1444
- port: (config_hash[:port] || 5432).to_i,
1449
+ host: config_hash[:host],
1450
+ port: config_hash[:port]&.to_i,
1445
1451
  dbname: config_hash[:database],
1446
1452
  user: config_hash[:username],
1447
1453
  password: config_hash[:password]
data/lib/pgbus/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pgbus
4
- VERSION = "0.11.0"
4
+ VERSION = "0.11.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgbus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson