Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Fixed `db:drop`, `db:reset`, and `db:test:prepare` failing on Aurora PostgreSQL with `database "<name>" is being accessed by other users`. The same error occurred when running `bin/rails test` after a schema change. The cause was the wrapper's topology and Blue/Green monitors, which kept their own connections open to the database being dropped. The wrapper now stops these monitors before dropping a database and when ActiveRecord clears all its connections ([PR #195](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/195)).
- Fixed forked processes, such as Puma workers with `preload_app!`, Unicorn workers, and Resque jobs, inheriting the parent's background monitors after their threads had stopped, so the cluster topology never refreshed in the child and failover there could not find the new writer. A forked child now starts its own monitors and leaves the parent's monitoring connections open. A forked child also no longer waits on a Secrets Manager fetch that was in progress in the parent when it forked ([PR #196](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/196)).
- Fixed the AWS Secrets Manager plugin not reporting a timed-out secret fetch as a timeout. A fetch that did not finish within 60 seconds failed with a generic `SecretsManagerAuthError` (`Failed to fetch database credentials from AWS Secrets Manager`) instead of `Timed out fetching secret after 60s` ([PR #196](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/196)).
- Fixed Action Cable's PostgreSQL subscription adapter (`adapter: postgresql` in `cable.yml`) refusing to run on the `aws_postgresql` ActiveRecord adapter with `The Active Record database must be PostgreSQL in order to use the PostgreSQL Action Cable storage adapter`, which also stopped Turbo Stream broadcasts ([PR #197](https://github.com/aws/aws-advanced-ruby-driver-wrapper/pull/197)).

## [1.0.0] - 2026-10-05

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative '../postgresql'

module ActiveRecord
module ConnectionAdapters
# Lets Action Cable's PostgreSQL subscription adapter (cable.yml `adapter: postgresql`) run on the
# aws_postgresql adapter. Action Cable refuses any raw connection that is not a PG::Connection, and
# aws_postgresql hands out a WrapperPgConnection, which forwards the calls Action Cable makes
# (exec, escape_identifier, escape_string, wait_for_notify) to the PG::Connection it wraps.
module AwsActionCablePostgreSQLSupport
private

def verify!(pg_conn)
super unless pg_conn.is_a?(AwsAdvancedRubyDriverWrapper::WrapperPgConnection)
end
end
end
end

# Action Cable runs this hook when its server loads, before it loads a subscription adapter, so the
# PostgreSQL one is loaded here to patch it. Applications without Action Cable never run the hook.
ActiveSupport.on_load(:action_cable) do
require 'action_cable/subscription_adapter/postgresql'
ActionCable::SubscriptionAdapter::PostgreSQL.prepend(ActiveRecord::ConnectionAdapters::AwsActionCablePostgreSQLSupport)
end
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
require_relative '../postgresql'
require_relative '../errors'
require_relative 'aws_connection_handler'
require_relative 'aws_action_cable_postgresql_support'

module ActiveRecord
module ConnectionAdapters
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Stand-in for Action Cable's PostgreSQL subscription adapter, which is not a dependency of this gem.
# It keeps the check every supported Action Cable version (7.2 to 8.1) runs on the connection it is given.
module ActionCable
module SubscriptionAdapter
class PostgreSQL
def check(pg_conn)
verify!(pg_conn)
end

private

def verify!(pg_conn)
return if pg_conn.is_a?(PG::Connection)

raise 'The Active Record database must be PostgreSQL in order to use the PostgreSQL Action Cable storage adapter'
end
end
end
end
36 changes: 36 additions & 0 deletions spec/unit/aws_action_cable_postgresql_support_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative '../spec_helper'

# Action Cable is not a dependency of this gem, so its PostgreSQL subscription adapter is replaced by a stand-in.
$LOAD_PATH.unshift(File.expand_path('../fixtures/action_cable_stub', __dir__))
require 'aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter'

RSpec.describe 'Action Cable PostgreSQL subscription adapter with aws_postgresql' do
# Action Cable runs its load hooks when its server loads.
before(:all) { ActiveSupport.run_load_hooks(:action_cable, Object.new) }

let(:adapter) { ActionCable::SubscriptionAdapter::PostgreSQL.new }

it 'accepts the wrapper connection that aws_postgresql hands out as its raw connection' do
expect { adapter.check(AwsAdvancedRubyDriverWrapper::WrapperPgConnection.allocate) }.not_to raise_error
end

it 'still rejects connections that are not PostgreSQL' do
expect { adapter.check(Object.new) }.to raise_error(RuntimeError, /must be PostgreSQL/)
end
end