active_record_proxy_adapters 0.1.5 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b80e3ab832bc332967c0f4840f9f35563725497e61a48339c46e4f65a15b2458
4
- data.tar.gz: fc85aed94e09aa25bd15e46102ae318f9b790bc2bb67a24243c2340952ff4fa2
3
+ metadata.gz: 5312effcf68a3305eb5e7804440112433f5b6837d6b71e7d122145eac4741619
4
+ data.tar.gz: 50586657daa02e76dfffebbe1faf8df5093198471faf847cec97cd16634c0c17
5
5
  SHA512:
6
- metadata.gz: 5a81cf2441d0f1548311474fbaa3326b9d2fbccc0b25c481408f0f99ce6634710dc589e0aed60f63ca55e5debe2635eb4cd6a75c2a0cf444fb7929292dc02dac
7
- data.tar.gz: c4bd34a35fa68b8257a5839b99055efdd11d18ce436afea98fd695475c4dae7cfda7ecc26fc2aed61f0981258c65684f22185c6d8fddc143ceb06b400b9219b1
6
+ metadata.gz: 707b80a3618328639126d13f3f76bb8123105019b3e30c75f15c66a66a88d49aa5de4301fe70b25ff5356ef37e54ebff896f4cab0160cadbb79d08ae9cf0dc4e
7
+ data.tar.gz: 6b84984e33cf87abe9a12f5553bccffc32e2a9563a0c859c488cdae4be4c3a019ffce01242648620c67bb85a16dc61d982f0be8ecba83943f01c718e067743dc
data/CHANGELOG.md CHANGED
@@ -1,37 +1,26 @@
1
1
  ## [Unreleased]
2
2
 
3
- - Handle PendingMigrationConnection introduced by Rails 7.2 and backported to Rails 7.1
4
- - Stick to same connection throughout request span
5
-
6
- ## [0.2.1] - 2025-01-02
7
-
8
- - Fix replica connection pool getter when specific connection name is not found https://github.com/Nasdaq/active_record_proxy_adapters/commit/847e150dd21c5bc619745ee1d9d8fcaa9b8f2eea
9
-
10
3
  ## [0.2.0] - 2024-12-24
11
4
 
12
- - Add custom log subscriber to tag queries based on the adapter being used https://github.com/Nasdaq/active_record_proxy_adapters/commit/68b8c1f4191388eb957bf12e0f84289da667e940
13
-
14
- ## [0.1.4] - 2025-01-02
15
-
16
- - Fix replica connection pool getter when specific connection name is not found https://github.com/Nasdaq/active_record_proxy_adapters/commit/88b32a282b54d420e652f638656dbcf063ac8796
5
+ - Add custom log subscriber to tag queries based on the adapter being used (68b8c1f4191388eb957bf12e0f84289da667e940)
17
6
 
18
7
  ## [0.1.3] - 2024-12-24
19
8
 
20
- - Fix replica connection pool getter when database configurations have multiple replicas https://github.com/Nasdaq/active_record_proxy_adapters/commit/ea5a33997da45ac073f166b3fbd2d12426053cd6
21
- - Retrieve replica pool without checking out a connection https://github.com/Nasdaq/active_record_proxy_adapters/commit/6470ef58e851082ae1f7a860ecdb5b451ef903c8
9
+ - Fix replica connection pool getter when database configurations have multiple replicas (ea5a33997da45ac073f166b3fbd2d12426053cd6)
10
+ - Retrieve replica pool without checking out a connection (6470ef58e851082ae1f7a860ecdb5b451ef903c8)
22
11
 
23
12
  ## [0.1.2] - 2024-12-16
24
13
 
25
- - Fix CTE regex matcher https://github.com/Nasdaq/active_record_proxy_adapters/commit/4b1d10bfd952fb1f5b102de8cc1a5bd05d25f5e9
14
+ - Fix CTE regex matcher (4b1d10bfd952fb1f5b102de8cc1a5bd05d25f5e9)
26
15
 
27
16
  ## [0.1.1] - 2024-11-27
28
17
 
29
- - Enable RubyGems MFA https://github.com/Nasdaq/active_record_proxy_adapters/commit/2a71b1f4354fb966cc0aa68231ca5837814e07ee
18
+ - Enable RubyGems MFA (2a71b1f4354fb966cc0aa68231ca5837814e07ee)
30
19
 
31
20
  ## [0.1.0] - 2024-11-19
32
21
 
33
- - Add PostgreSQLProxyAdapter https://github.com/Nasdaq/active_record_proxy_adapters/commit/2b3bb9f7359139519b32af3018ceb07fed8c6b33
22
+ - Add PostgreSQLProxyAdapter (2b3bb9f7359139519b32af3018ceb07fed8c6b33)
34
23
 
35
24
  ## [0.1.0.rc2] - 2024-10-28
36
25
 
37
- - Add PostgreSQLProxyAdapter https://github.com/Nasdaq/active_record_proxy_adapters/commit/2b3bb9f7359139519b32af3018ceb07fed8c6b33
26
+ - Add PostgreSQLProxyAdapter (2b3bb9f7359139519b32af3018ceb07fed8c6b33)
data/Dockerfile CHANGED
@@ -8,7 +8,7 @@ RUN apk --update add \
8
8
  build-base \
9
9
  git \
10
10
  postgresql-dev \
11
- postgresql17-client
11
+ postgresql-client
12
12
  RUN gem install bundler -v 2.5.13
13
13
 
14
14
  COPY . /app
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # ActiveRecordProxyAdapters
2
2
 
3
- [![Run Test Suite](https://github.com/Nasdaq/active_record_proxy_adapters/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/Nasdaq/active_record_proxy_adapters/actions/workflows/test.yml)
4
-
5
3
  A set of ActiveRecord adapters that leverage Rails native multiple database setup to allow automatic connection switching from _one_ primary pool to _one_ replica pool at the database statement level.
6
4
 
7
5
  ## Installation
@@ -1,7 +1,6 @@
1
1
  SET statement_timeout = 0;
2
2
  SET lock_timeout = 0;
3
3
  SET idle_in_transaction_session_timeout = 0;
4
- SET transaction_timeout = 0;
5
4
  SET client_encoding = 'UTF8';
6
5
  SET standard_conforming_strings = on;
7
6
  SELECT pg_catalog.set_config('search_path', '', false);
@@ -10,18 +9,16 @@ SET xmloption = content;
10
9
  SET client_min_messages = warning;
11
10
  SET row_security = off;
12
11
 
13
- SET default_tablespace = '';
14
-
15
- SET default_table_access_method = heap;
16
-
17
12
  --
18
- -- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -
13
+ -- Name: public; Type: SCHEMA; Schema: -; Owner: -
19
14
  --
20
15
 
21
- CREATE TABLE public.schema_migrations (
22
- version character varying(255) NOT NULL
23
- );
16
+ -- *not* creating schema, since initdb creates it
17
+
18
+
19
+ SET default_tablespace = '';
24
20
 
21
+ SET default_table_access_method = heap;
25
22
 
26
23
  --
27
24
  -- Name: users; Type: TABLE; Schema: public; Owner: -
@@ -71,13 +68,6 @@ ALTER TABLE ONLY public.users
71
68
  ADD CONSTRAINT users_pkey PRIMARY KEY (id);
72
69
 
73
70
 
74
- --
75
- -- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -
76
- --
77
-
78
- CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version);
79
-
80
-
81
71
  --
82
72
  -- PostgreSQL database dump complete
83
73
  --
data/docker-compose.yml CHANGED
@@ -50,6 +50,7 @@ services:
50
50
  - POSTGRES_LOG_STATEMENT=${POSTGRES_LOG_STATEMENT:-}
51
51
  - REPLICA_USER=replicator
52
52
  - REPLICA_PASSWORD=replicator
53
+ container_name: postgres_primary
53
54
  environment:
54
55
  POSTGRES_DB: postgres
55
56
  POSTGRES_USER: postgres_primary_test
@@ -5,8 +5,10 @@ require "active_support/core_ext/integer/time"
5
5
  module ActiveRecordProxyAdapters
6
6
  # Provides a global configuration object to configure how the proxy should behave.
7
7
  class Configuration
8
- PROXY_DELAY = 2.seconds.freeze
9
- CHECKOUT_TIMEOUT = 2.seconds.freeze
8
+ PROXY_DELAY = 2.seconds.freeze
9
+ CHECKOUT_TIMEOUT = 2.seconds.freeze
10
+ LOG_SUBSCRIBER_PRIMARY_PREFIX = proc { |event| "#{event.payload[:connection].class::ADAPTER_NAME} Primary" }.freeze
11
+ LOG_SUBSCRIBER_REPLICA_PREFIX = proc { |event| "#{event.payload[:connection].class::ADAPTER_NAME} Replica" }.freeze
10
12
 
11
13
  # @return [ActiveSupport::Duration] How long the proxy should reroute all read requests to the primary database
12
14
  # since the latest write. Defaults to PROXY_DELAY.
@@ -15,9 +17,25 @@ module ActiveRecordProxyAdapters
15
17
  # Defaults to CHECKOUT_TIMEOUT.
16
18
  attr_accessor :checkout_timeout
17
19
 
20
+ # @return [Proc] Prefix for the log subscriber when the primary database is used.
21
+ attr_reader :log_subscriber_primary_prefix
22
+
23
+ # @return [Proc] Prefix for the log subscriber when the replica database is used.
24
+ attr_reader :log_subscriber_replica_prefix
25
+
18
26
  def initialize
19
- self.proxy_delay = PROXY_DELAY
20
- self.checkout_timeout = CHECKOUT_TIMEOUT
27
+ self.proxy_delay = PROXY_DELAY
28
+ self.checkout_timeout = CHECKOUT_TIMEOUT
29
+ self.log_subscriber_primary_prefix = LOG_SUBSCRIBER_PRIMARY_PREFIX
30
+ self.log_subscriber_replica_prefix = LOG_SUBSCRIBER_REPLICA_PREFIX
31
+ end
32
+
33
+ def log_subscriber_primary_prefix=(prefix)
34
+ @log_subscriber_primary_prefix = prefix.is_a?(Proc) ? prefix : proc { prefix.to_s }
35
+ end
36
+
37
+ def log_subscriber_replica_prefix=(prefix)
38
+ @log_subscriber_replica_prefix = prefix.is_a?(Proc) ? prefix : proc { prefix.to_s }
21
39
  end
22
40
  end
23
41
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordProxyAdapters
4
+ class LogSubscriber < ActiveRecord::LogSubscriber # rubocop:disable Style/Documentation
5
+ attach_to :active_record
6
+
7
+ IGNORE_PAYLOAD_NAMES = %w[SCHEMA EXPLAIN].freeze
8
+
9
+ def sql(event)
10
+ payload = event.payload
11
+ name = payload[:name]
12
+ unless IGNORE_PAYLOAD_NAMES.include?(name)
13
+ name = [database_instance_prefix_for(event), name].compact.join(" ")
14
+ payload[:name] = name
15
+ end
16
+ super
17
+ end
18
+
19
+ protected
20
+
21
+ def database_instance_prefix_for(event)
22
+ connection = event.payload[:connection]
23
+ config = connection.instance_variable_get(:@config)
24
+ prefix = if config[:replica] || config["replica"]
25
+ log_subscriber_replica_prefix
26
+ else
27
+ log_subscriber_primary_prefix
28
+ end
29
+
30
+ "[#{prefix.call(event)}]"
31
+ end
32
+
33
+ private
34
+
35
+ delegate :log_subscriber_primary_prefix, :log_subscriber_replica_prefix, to: :config
36
+
37
+ def config
38
+ ActiveRecordProxyAdapters.config
39
+ end
40
+ end
41
+ end
@@ -62,7 +62,7 @@ module ActiveRecordProxyAdapters
62
62
 
63
63
  attr_reader :primary_connection, :last_write_at, :active_record_context
64
64
 
65
- delegate :connection_handler, to: :connection_class
65
+ delegate :connection_handler, :connected_to_stack, to: :connection_class
66
66
  delegate :reading_role, :writing_role, to: :active_record_context
67
67
 
68
68
  def replica_pool_unavailable?
@@ -70,18 +70,9 @@ module ActiveRecordProxyAdapters
70
70
  end
71
71
 
72
72
  def replica_pool
73
- # use default handler if the connection pool for specific class is not found
74
- specific_replica_pool || default_replica_pool
75
- end
76
-
77
- def specific_replica_pool
78
73
  connection_handler.retrieve_connection_pool(connection_class.name, role: reading_role)
79
74
  end
80
75
 
81
- def default_replica_pool
82
- connection_handler.retrieve_connection_pool(ActiveRecord::Base.name, role: reading_role)
83
- end
84
-
85
76
  def connection_class
86
77
  active_record_context.connection_class_for(primary_connection)
87
78
  end
@@ -120,25 +111,11 @@ module ActiveRecordProxyAdapters
120
111
  [reading_role, writing_role].include?(role) ? role : nil
121
112
  end
122
113
 
123
- def connected_to_stack
124
- return connection_class.connected_to_stack if connection_class.respond_to?(:connected_to_stack)
125
-
126
- # handle Rails 7.2+ pending migrations Connection
127
- return [{ role: writing_role }] if pending_migration_connection?
128
-
129
- []
130
- end
131
-
132
- def pending_migration_connection?
133
- active_record_context.active_record_v7_1_or_greater? &&
134
- connection_class.name == "ActiveRecord::PendingMigrationConnection"
135
- end
136
-
137
114
  def connection_for(role, sql_string)
138
115
  connection = primary_connection if role == writing_role || replica_pool_unavailable?
139
116
  connection ||= checkout_replica_connection
140
117
 
141
- result = connected_to(role:) { yield connection }
118
+ result = yield(connection)
142
119
 
143
120
  update_primary_latest_write_timestamp if !replica_connection?(connection) && write_statement?(sql_string)
144
121
 
@@ -147,12 +124,6 @@ module ActiveRecordProxyAdapters
147
124
  replica_connection?(connection) && replica_pool.checkin(connection)
148
125
  end
149
126
 
150
- def connected_to(role:, &block)
151
- return block.call unless connection_class.respond_to?(:connected_to)
152
-
153
- connection_class.connected_to(role:, &block)
154
- end
155
-
156
127
  def replica_connection?(connection)
157
128
  connection && connection != primary_connection
158
129
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordProxyAdapters
4
- VERSION = "0.1.5"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -1,4 +1,4 @@
1
- FROM docker.io/postgres:17-alpine
1
+ FROM docker.io/postgres:14-alpine
2
2
 
3
3
  ARG REPLICA_USER=replicator
4
4
  ARG REPLICA_PASSWORD=replicator
@@ -1,4 +1,4 @@
1
- FROM docker.io/postgres:17-alpine
1
+ FROM docker.io/postgres:14-alpine
2
2
 
3
3
  ENV PRIMARY_DATABASE_HOST=localhost
4
4
  ENV PRIMARY_DATABASE_PORT=5432
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_proxy_adapters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Cruz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-04 00:00:00.000000000 Z
11
+ date: 2024-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -77,6 +77,7 @@ files:
77
77
  - lib/active_record_proxy_adapters/configuration.rb
78
78
  - lib/active_record_proxy_adapters/connection_handling.rb
79
79
  - lib/active_record_proxy_adapters/hijackable.rb
80
+ - lib/active_record_proxy_adapters/log_subscriber.rb
80
81
  - lib/active_record_proxy_adapters/postgresql_proxy.rb
81
82
  - lib/active_record_proxy_adapters/primary_replica_proxy.rb
82
83
  - lib/active_record_proxy_adapters/railtie.rb