Skip to content

Commit cf9b622

Browse files
smudgeclaude
andauthored
fix: avoid eager DB connection when loading Journaled::Outbox::Event (#71)
* fix: avoid eager DB connection when loading Journaled::Outbox::Event Passing a symbol to `attribute` (e.g. `attribute :event_data, :json`) causes Rails 7.2+ to call `ActiveRecord::Type.adapter_name_from` at class load time, which requires an active connection pool to resolve the adapter-specific type. This prevents the class from being autoloaded without a database connection (e.g. during tapioca gem shim generation). Replace with a concrete type object (`ActiveRecord::Type::Json.new`), which bypasses adapter resolution entirely and has identical behavior on PostgreSQL. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fixup: Test load behavior empirically via a meta test * Bump version.rb --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c0aa511 commit cf9b622

6 files changed

Lines changed: 39 additions & 5 deletions

File tree

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
journaled (6.2.6)
4+
journaled (6.2.7)
55
activejob
66
activerecord
77
activesupport

app/models/journaled/outbox/event.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Event < Journaled.outbox_base_class_name.constantize
1616

1717
skip_audit_log
1818

19-
attribute :event_data, :json
19+
attribute :event_data, ActiveRecord::Type::Json.new
2020

2121
validates :event_type, :event_data, :partition_key, :stream_name, presence: true
2222
validate :failed_at_and_failure_reason_must_be_consistent

gemfiles/rails_7_2.gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ..
33
specs:
4-
journaled (6.2.6)
4+
journaled (6.2.7)
55
activejob
66
activerecord
77
activesupport

gemfiles/rails_8_0.gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ..
33
specs:
4-
journaled (6.2.6)
4+
journaled (6.2.7)
55
activejob
66
activerecord
77
activesupport

lib/journaled/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module Journaled
4-
VERSION = "6.2.6"
4+
VERSION = "6.2.7"
55
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
require 'open3'
5+
6+
RSpec.describe 'app/models' do
7+
it 'loads all files without a database connection pool configured' do
8+
env_file = Rails.root.join('config/environment').to_s
9+
gem_root = Rails.root.join('../..').expand_path.to_s
10+
model_files = Dir[File.join(gem_root, 'app/models/**/*.rb')]
11+
12+
file_loads = model_files.map { |f| "load #{f.inspect}" }.join("\n")
13+
14+
# Boot Rails in development mode (lazy loading), remove all connection pools,
15+
# then load each model file. This simulates the conditions under which the bug
16+
# was originally discovered: tapioca loading classes without a DB configured.
17+
# Rails 7.2+ calls ActiveRecord::Type.adapter_name_from at class load time for
18+
# symbol-typed attributes, which raises if no connection pool exists.
19+
script = <<~RUBY
20+
ENV['RAILS_ENV'] = 'development'
21+
require #{env_file.inspect}
22+
23+
handler = ActiveRecord::Base.connection_handler
24+
handler.connection_pool_names.each { |name| handler.remove_connection_pool(name) }
25+
26+
#{file_loads}
27+
28+
puts "#{model_files.size} model files loaded successfully"
29+
RUBY
30+
31+
output, status = Open3.capture2e(RbConfig.ruby, '-e', script)
32+
expect(status.exitstatus).to eq(0), "Model load failed:\n#{output}"
33+
end
34+
end

0 commit comments

Comments
 (0)