active_record_proxy_adapters 0.1.2 → 0.1.3

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: 2b23e66bd5df6d979b9efad29a52139552950f29774935cc91fffdbc87805a4c
4
- data.tar.gz: 5b3206ee7420635f2f76432a1bbe728e161a9ea434db42da22ac5290ae561e3d
3
+ metadata.gz: 70b1c4f2efd94125b178e043fa1162ab6d8d8edb7a9041eb10b8244c606b3c59
4
+ data.tar.gz: fb74c76ed0dc0865c9756c3188a92dd248ce58ef4832811704c15a59b728991e
5
5
  SHA512:
6
- metadata.gz: cb98f62ce8a62ef0d71364491d1686186c527adc0c6a8612fd5ee118710fe9360166f14ae06b348856548c8b507ef90edf413113e93a9afa56c82e84c267df1e
7
- data.tar.gz: 75f30a3ce9473415be91a51acc9fc39a5aacc31b6623943a007b3fb0c41e330752c6f6b470ee759d141b6c84feb96d3b24a015939bb0b053d82ac50a22adb447
6
+ metadata.gz: 3730cca00342dd7f44944305bfdd53f158da2bc8d09b39883645a2b1a581297904dce121c10de5bc351e30b999b1bcd59457bd3309280074fb36d716a22bdcae
7
+ data.tar.gz: 07d42f0c57bdd203a260a7d55010159318db260f95ed5483049e8a6ac771908df7696d05692a3043f0a54d77f4e2623c6aa08b7ddda2db5a79e634224db78b12
data/CHANGELOG.md CHANGED
@@ -1,8 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ - Fix replica connection pool getter when database configurations have multiple replicas
4
+ - Retrieve replica pool without checking out a connection
5
+
3
6
  ## [0.1.2] - 2024-12-16
4
7
 
5
- Fix CTE regex matcher (4b1d10b)
8
+ - Fix CTE regex matcher (4b1d10b)
6
9
 
7
10
  ## [0.1.1] - 2024-11-27
8
11
 
data/Rakefile CHANGED
@@ -11,6 +11,62 @@ RuboCop::RakeTask.new
11
11
 
12
12
  task default: %i[spec rubocop]
13
13
 
14
+ desc "Prepares the database environment for use"
15
+ task :environment do
16
+ $LOAD_PATH << File.expand_path("lib", __dir__)
17
+ require "active_record_proxy_adapters"
18
+ require "active_record_proxy_adapters/connection_handling"
19
+ ActiveRecord::Base.extend ActiveRecordProxyAdapters::ConnectionHandling
20
+ require_relative "spec/test_helper"
21
+
22
+ TestHelper.setup_active_record_config
23
+
24
+ $stdout.puts "Environment loaded: #{TestHelper.env_name}"
25
+ end
26
+
27
+ namespace :db do # rubocop:disable Metrics/BlockLength
28
+ desc "Drops all databases"
29
+ task drop: %i[drop:postgresql]
30
+
31
+ namespace :drop do
32
+ desc "Drops the postgresql database"
33
+ task postgresql: :environment do
34
+ TestHelper.drop_database
35
+ end
36
+ end
37
+
38
+ desc "Creates all databases"
39
+ task create: %i[create:postgresql]
40
+
41
+ namespace :create do
42
+ desc "Creates the postgresql database"
43
+ task postgresql: :environment do
44
+ TestHelper.create_database
45
+ end
46
+ end
47
+
48
+ namespace :schema do
49
+ desc "Loads all schemas onto their respective databases"
50
+ task load: %i[load:postgresql]
51
+
52
+ namespace :load do
53
+ desc "Loads the schema into the postgresql database from schema_path. Default is db/postgresql_structure.sql"
54
+ task :postgresql, [:schema_path] => :environment do |_task, args|
55
+ args.with_defaults(schema_path: "db/postgresql_structure.sql")
56
+ TestHelper.load_schema(args.schema_path)
57
+ end
58
+ end
59
+ end
60
+
61
+ desc "Creates a all databases and loads their schemas"
62
+ task setup: %i[create schema:load]
63
+
64
+ namespace :setup do
65
+ desc "Creates the postgresql database and loads the schema"
66
+ task postgresql: %i[create:postgresql schema:load:postgresql]
67
+ end
68
+ end
69
+
14
70
  namespace :coverage do
15
71
  desc "Collates all result sets generated by the different test runners"
16
72
  task :report do
@@ -0,0 +1,76 @@
1
+ SET statement_timeout = 0;
2
+ SET lock_timeout = 0;
3
+ SET idle_in_transaction_session_timeout = 0;
4
+ SET client_encoding = 'UTF8';
5
+ SET standard_conforming_strings = on;
6
+ SELECT pg_catalog.set_config('search_path', '', false);
7
+ SET check_function_bodies = false;
8
+ SET xmloption = content;
9
+ SET client_min_messages = warning;
10
+ SET row_security = off;
11
+
12
+ --
13
+ -- Name: public; Type: SCHEMA; Schema: -; Owner: -
14
+ --
15
+
16
+ -- *not* creating schema, since initdb creates it
17
+
18
+
19
+ SET default_tablespace = '';
20
+
21
+ SET default_table_access_method = heap;
22
+
23
+ --
24
+ -- Name: users; Type: TABLE; Schema: public; Owner: -
25
+ --
26
+
27
+ CREATE TABLE public.users (
28
+ id integer NOT NULL,
29
+ name text NOT NULL,
30
+ email text NOT NULL,
31
+ created_at timestamp without time zone DEFAULT now() NOT NULL,
32
+ updated_at timestamp without time zone DEFAULT now() NOT NULL
33
+ );
34
+
35
+
36
+ --
37
+ -- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: -
38
+ --
39
+
40
+ CREATE SEQUENCE public.users_id_seq
41
+ AS integer
42
+ START WITH 1
43
+ INCREMENT BY 1
44
+ NO MINVALUE
45
+ NO MAXVALUE
46
+ CACHE 1;
47
+
48
+
49
+ --
50
+ -- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
51
+ --
52
+
53
+ ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id;
54
+
55
+
56
+ --
57
+ -- Name: users id; Type: DEFAULT; Schema: public; Owner: -
58
+ --
59
+
60
+ ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);
61
+
62
+
63
+ --
64
+ -- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: -
65
+ --
66
+
67
+ ALTER TABLE ONLY public.users
68
+ ADD CONSTRAINT users_pkey PRIMARY KEY (id);
69
+
70
+
71
+ --
72
+ -- PostgreSQL database dump complete
73
+ --
74
+
75
+ SET search_path TO "$user", public;
76
+
@@ -62,15 +62,19 @@ module ActiveRecordProxyAdapters
62
62
 
63
63
  attr_reader :primary_connection, :last_write_at, :active_record_context
64
64
 
65
- delegate :connected_to_stack, 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
- def connection_class
69
- active_record_context.connection_class_for(primary_connection)
68
+ def replica_pool_unavailable?
69
+ !replica_pool
70
70
  end
71
71
 
72
72
  def replica_pool
73
- ActiveRecord::Base.connected_to(role: reading_role) { ActiveRecord::Base.connection_pool }
73
+ connection_handler.retrieve_connection_pool(connection_class.name, role: reading_role)
74
+ end
75
+
76
+ def connection_class
77
+ active_record_context.connection_class_for(primary_connection)
74
78
  end
75
79
 
76
80
  def coerce_query_to_string(sql_or_arel)
@@ -107,21 +111,12 @@ module ActiveRecordProxyAdapters
107
111
  [reading_role, writing_role].include?(role) ? role : nil
108
112
  end
109
113
 
110
- def connection_for(role, sql_string) # rubocop:disable Metrics/MethodLength
111
- connection = if role == writing_role
112
- primary_connection
113
- else
114
- begin
115
- replica_pool.checkout(checkout_timeout)
116
- # rescue NoDatabaseError to avoid crashing when running db:create rake task
117
- # rescue ConnectionNotEstablished to handle connectivity issues in the replica
118
- # (for example, replication delay)
119
- rescue ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished
120
- primary_connection
121
- end
122
- end
114
+ def connection_for(role, sql_string)
115
+ connection = primary_connection if role == writing_role || replica_pool_unavailable?
116
+ connection ||= checkout_replica_connection
123
117
 
124
118
  result = yield(connection)
119
+
125
120
  update_primary_latest_write_timestamp if !replica_connection?(connection) && write_statement?(sql_string)
126
121
 
127
122
  result
@@ -130,7 +125,16 @@ module ActiveRecordProxyAdapters
130
125
  end
131
126
 
132
127
  def replica_connection?(connection)
133
- connection != primary_connection
128
+ connection && connection != primary_connection
129
+ end
130
+
131
+ def checkout_replica_connection
132
+ replica_pool.checkout(checkout_timeout)
133
+ # rescue NoDatabaseError to avoid crashing when running db:create rake task
134
+ # rescue ConnectionNotEstablished to handle connectivity issues in the replica
135
+ # (for example, replication delay)
136
+ rescue ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished
137
+ primary_connection
134
138
  end
135
139
 
136
140
  # @return [TrueClass] if there has been a write within the last {#proxy_delay} seconds
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordProxyAdapters
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.3"
5
5
  end
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.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Cruz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-17 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
@@ -68,6 +68,7 @@ files:
68
68
  - LICENSE.txt
69
69
  - README.md
70
70
  - Rakefile
71
+ - db/postgresql_structure.sql
71
72
  - docker-compose.yml
72
73
  - docker/postgres_replica/cmd.sh
73
74
  - lib/active_record/connection_adapters/postgresql_proxy_adapter.rb