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 +4 -4
- data/CHANGELOG.md +4 -1
- data/Rakefile +56 -0
- data/db/postgresql_structure.sql +76 -0
- data/lib/active_record_proxy_adapters/primary_replica_proxy.rb +22 -18
- data/lib/active_record_proxy_adapters/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70b1c4f2efd94125b178e043fa1162ab6d8d8edb7a9041eb10b8244c606b3c59
|
4
|
+
data.tar.gz: fb74c76ed0dc0865c9756c3188a92dd248ce58ef4832811704c15a59b728991e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
69
|
-
|
68
|
+
def replica_pool_unavailable?
|
69
|
+
!replica_pool
|
70
70
|
end
|
71
71
|
|
72
72
|
def replica_pool
|
73
|
-
|
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)
|
111
|
-
connection = if role == writing_role
|
112
|
-
|
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
|
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.
|
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-
|
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
|