janus-ar 8.0.0 → 8.1.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 +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +142 -125
- data/README.md +153 -131
- data/janus-ar.gemspec +38 -36
- data/lib/janus-ar/active_record/connection_adapters/janus_mysql2_adapter.rb +32 -149
- data/lib/janus-ar/active_record/connection_adapters/janus_trilogy_adapter.rb +32 -149
- data/lib/janus-ar/adapter_extensions.rb +112 -0
- data/lib/janus-ar/client.rb +6 -6
- data/lib/janus-ar/context.rb +79 -80
- data/lib/janus-ar/db_console_config.rb +17 -17
- data/lib/janus-ar/logging/logger.rb +15 -15
- data/lib/janus-ar/logging/subscriber.rb +27 -27
- data/lib/janus-ar/query_director.rb +87 -54
- data/lib/janus-ar/railtie.rb +15 -0
- data/lib/janus-ar/version.rb +17 -17
- data/lib/janus-ar.rb +24 -22
- metadata +10 -30
- data/.bundle/config +0 -5
- data/.github/dependabot.yml +0 -7
- data/.github/workflows/ci.yml +0 -60
- data/.github/workflows/publish.yml +0 -25
- data/.gitignore +0 -2
- data/.rspec +0 -3
- data/.rubocop.yml +0 -26
- data/assets/.gitkeep +0 -1
- data/assets/janus-logo.png +0 -0
- data/bin/release.sh +0 -3
- data/spec/lib/janus-ar/active_record/connection_adapters/janus_mysql_adapter_spec.rb +0 -82
- data/spec/lib/janus-ar/active_record/connection_adapters/janus_trilogy_adapter_spec.rb +0 -82
- data/spec/lib/janus-ar/client_spec.rb +0 -7
- data/spec/lib/janus-ar/context_spec.rb +0 -46
- data/spec/lib/janus-ar/logging/logger_spec.rb +0 -31
- data/spec/lib/janus-ar/query_director_spec.rb +0 -59
- data/spec/shared_examples/a_mysql_like_server.rb +0 -85
- data/spec/spec_helper.rb +0 -46
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cd05e24e1306fce67609a9e991fddad6c4d7014ce58f696a01eb64317838e837
|
|
4
|
+
data.tar.gz: d07db4e1d21a6363ed9f0f1ea41736b1d71d1ae0fd6c419f34f15e5f74e8825f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9bc3a5029f1b51374051a2c6f8ccc743192780bae4eaaafe18ea6578d9fb77826760ae95a6714bb5ea8f3cd128ef51a3247d39416ae78b8af7b5554ee652ab64
|
|
7
|
+
data.tar.gz: 0fc71666876765b84cc70ddc4ffc016cd175ae8594fb68dd0a442b047a27aced86e5597ebb1fcf3cebc10d00e81081f8ff63122fcacc4eefa680a89c0fdc4ca2
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,125 +1,142 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
janus-ar (
|
|
5
|
-
activerecord (>= 8.0, < 9.0)
|
|
6
|
-
|
|
7
|
-
GEM
|
|
8
|
-
remote:
|
|
9
|
-
specs:
|
|
10
|
-
activemodel (8.
|
|
11
|
-
activesupport (= 8.
|
|
12
|
-
activerecord (8.
|
|
13
|
-
activemodel (= 8.
|
|
14
|
-
activesupport (= 8.
|
|
15
|
-
timeout (>= 0.4.0)
|
|
16
|
-
activesupport (8.
|
|
17
|
-
base64
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
logger (>= 1.4.2)
|
|
25
|
-
minitest (>= 5.1)
|
|
26
|
-
securerandom (>= 0.3)
|
|
27
|
-
tzinfo (~> 2.0, >= 2.0.5)
|
|
28
|
-
uri (>= 0.13.1)
|
|
29
|
-
ast (2.4.
|
|
30
|
-
base64 (0.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
json (2.
|
|
41
|
-
language_server-protocol (3.17.0.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
rspec-
|
|
70
|
-
rspec-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
rubocop-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
janus-ar (8.1.0)
|
|
5
|
+
activerecord (>= 8.0, < 9.0)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
activemodel (8.1.3.1)
|
|
11
|
+
activesupport (= 8.1.3.1)
|
|
12
|
+
activerecord (8.1.3.1)
|
|
13
|
+
activemodel (= 8.1.3.1)
|
|
14
|
+
activesupport (= 8.1.3.1)
|
|
15
|
+
timeout (>= 0.4.0)
|
|
16
|
+
activesupport (8.1.3.1)
|
|
17
|
+
base64
|
|
18
|
+
bigdecimal
|
|
19
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
20
|
+
connection_pool (>= 2.2.5)
|
|
21
|
+
drb
|
|
22
|
+
i18n (>= 1.6, < 2)
|
|
23
|
+
json
|
|
24
|
+
logger (>= 1.4.2)
|
|
25
|
+
minitest (>= 5.1)
|
|
26
|
+
securerandom (>= 0.3)
|
|
27
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
28
|
+
uri (>= 0.13.1)
|
|
29
|
+
ast (2.4.3)
|
|
30
|
+
base64 (0.3.0)
|
|
31
|
+
bigdecimal (4.1.2)
|
|
32
|
+
coderay (1.1.3)
|
|
33
|
+
concurrent-ruby (1.3.8)
|
|
34
|
+
connection_pool (3.0.2)
|
|
35
|
+
diff-lcs (1.6.2)
|
|
36
|
+
drb (2.2.3)
|
|
37
|
+
i18n (1.15.2)
|
|
38
|
+
concurrent-ruby (~> 1.0)
|
|
39
|
+
io-console (0.8.2)
|
|
40
|
+
json (2.21.2)
|
|
41
|
+
language_server-protocol (3.17.0.6)
|
|
42
|
+
lint_roller (1.1.0)
|
|
43
|
+
logger (1.7.0)
|
|
44
|
+
method_source (1.1.0)
|
|
45
|
+
minitest (6.0.6)
|
|
46
|
+
drb (~> 2.0)
|
|
47
|
+
prism (~> 1.5)
|
|
48
|
+
mysql2 (0.5.7)
|
|
49
|
+
bigdecimal
|
|
50
|
+
parallel (1.28.0)
|
|
51
|
+
parser (3.3.12.0)
|
|
52
|
+
ast (~> 2.4.1)
|
|
53
|
+
racc
|
|
54
|
+
prism (1.9.0)
|
|
55
|
+
pry (0.16.0)
|
|
56
|
+
coderay (~> 1.1)
|
|
57
|
+
method_source (~> 1.0)
|
|
58
|
+
reline (>= 0.6.0)
|
|
59
|
+
racc (1.8.1)
|
|
60
|
+
rack (3.2.7)
|
|
61
|
+
rainbow (3.1.1)
|
|
62
|
+
rake (13.4.2)
|
|
63
|
+
regexp_parser (2.12.0)
|
|
64
|
+
reline (0.6.3)
|
|
65
|
+
io-console (~> 0.5)
|
|
66
|
+
rspec (3.13.2)
|
|
67
|
+
rspec-core (~> 3.13.0)
|
|
68
|
+
rspec-expectations (~> 3.13.0)
|
|
69
|
+
rspec-mocks (~> 3.13.0)
|
|
70
|
+
rspec-core (3.13.6)
|
|
71
|
+
rspec-support (~> 3.13.0)
|
|
72
|
+
rspec-expectations (3.13.5)
|
|
73
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
74
|
+
rspec-support (~> 3.13.0)
|
|
75
|
+
rspec-mocks (3.13.7)
|
|
76
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
77
|
+
rspec-support (~> 3.13.0)
|
|
78
|
+
rspec-support (3.13.7)
|
|
79
|
+
rubocop (1.90.0)
|
|
80
|
+
json (>= 2.3)
|
|
81
|
+
language_server-protocol (~> 3.17.0.2)
|
|
82
|
+
lint_roller (~> 1.1.0)
|
|
83
|
+
parallel (>= 1.10)
|
|
84
|
+
parser (>= 3.3.0.2)
|
|
85
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
86
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
87
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
88
|
+
ruby-progressbar (~> 1.7)
|
|
89
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
90
|
+
rubocop-ast (1.50.0)
|
|
91
|
+
parser (>= 3.3.7.2)
|
|
92
|
+
prism (~> 1.7)
|
|
93
|
+
rubocop-performance (1.27.0)
|
|
94
|
+
lint_roller (~> 1.1)
|
|
95
|
+
rubocop (>= 1.89.0, < 2.0)
|
|
96
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
97
|
+
rubocop-rails (2.37.0)
|
|
98
|
+
activesupport (>= 4.2.0)
|
|
99
|
+
lint_roller (~> 1.1)
|
|
100
|
+
rack (>= 1.1)
|
|
101
|
+
rubocop (>= 1.89.0, < 2.0)
|
|
102
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
|
103
|
+
rubocop-rspec (3.10.2)
|
|
104
|
+
lint_roller (~> 1.1)
|
|
105
|
+
regexp_parser (>= 2.0)
|
|
106
|
+
rubocop (~> 1.86, >= 1.86.2)
|
|
107
|
+
rubocop-thread_safety (0.7.3)
|
|
108
|
+
lint_roller (~> 1.1)
|
|
109
|
+
rubocop (~> 1.72, >= 1.72.1)
|
|
110
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
|
111
|
+
ruby-progressbar (1.13.0)
|
|
112
|
+
securerandom (0.4.1)
|
|
113
|
+
timeout (0.6.1)
|
|
114
|
+
trilogy (2.13.0)
|
|
115
|
+
bigdecimal
|
|
116
|
+
tzinfo (2.0.6)
|
|
117
|
+
concurrent-ruby (~> 1.0)
|
|
118
|
+
unicode-display_width (3.2.0)
|
|
119
|
+
unicode-emoji (~> 4.1)
|
|
120
|
+
unicode-emoji (4.2.0)
|
|
121
|
+
uri (1.1.1)
|
|
122
|
+
|
|
123
|
+
PLATFORMS
|
|
124
|
+
arm64-darwin-23
|
|
125
|
+
x86_64-linux
|
|
126
|
+
|
|
127
|
+
DEPENDENCIES
|
|
128
|
+
activesupport (>= 8.0)
|
|
129
|
+
janus-ar!
|
|
130
|
+
mysql2
|
|
131
|
+
pry
|
|
132
|
+
rake
|
|
133
|
+
rspec (~> 3)
|
|
134
|
+
rubocop (~> 1.90.0)
|
|
135
|
+
rubocop-performance
|
|
136
|
+
rubocop-rails (~> 2.37.0)
|
|
137
|
+
rubocop-rspec
|
|
138
|
+
rubocop-thread_safety
|
|
139
|
+
trilogy
|
|
140
|
+
|
|
141
|
+
BUNDLED WITH
|
|
142
|
+
2.4.22
|
data/README.md
CHANGED
|
@@ -1,131 +1,153 @@
|
|
|
1
|
-
# Janus ActiveRecord
|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<img src="assets/janus-logo.png"
|
|
5
|
-
alt="Janus Logo"
|
|
6
|
-
style="float: left; margin: 0 auto; height: 500px;" />
|
|
7
|
-
</p>
|
|
8
|
-
|
|
9
|
-
> In ancient Roman religion and myth, Janus (/ˈdʒeɪnəs/ JAY-nəs; Latin: Ianvs [ˈi̯aːnʊs]) is the god of beginnings, gates, transitions, time, duality, doorways,[2] passages, frames, and endings. [(wikipedia)](https://en.wikipedia.org/wiki/Janus)
|
|
10
|
-
|
|
11
|
-
[](https://github.com/OLIOEX/janus-ar/actions/workflows/ci.yml)
|
|
12
|
-
[](https://badge.fury.io/rb/janus-ar)
|
|
13
|
-
|
|
14
|
-
Janus ActiveRecord is generic primary/replica proxy for ActiveRecord
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
ActiveRecord::ConnectionAdapters.register("
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
* `
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
1
|
+
# Janus ActiveRecord
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="assets/janus-logo.png"
|
|
5
|
+
alt="Janus Logo"
|
|
6
|
+
style="float: left; margin: 0 auto; height: 500px;" />
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
> In ancient Roman religion and myth, Janus (/ˈdʒeɪnəs/ JAY-nəs; Latin: Ianvs [ˈi̯aːnʊs]) is the god of beginnings, gates, transitions, time, duality, doorways,[2] passages, frames, and endings. [(wikipedia)](https://en.wikipedia.org/wiki/Janus)
|
|
10
|
+
|
|
11
|
+
[](https://github.com/OLIOEX/janus-ar/actions/workflows/ci.yml)
|
|
12
|
+
[](https://badge.fury.io/rb/janus-ar)
|
|
13
|
+
|
|
14
|
+
Janus ActiveRecord is a generic primary/replica proxy for ActiveRecord 8 and MySQL (via `mysql2` and `trilogy`). It handles the switching of connections between primary and replica database servers. It comes with an ActiveRecord database adapter implementation.
|
|
15
|
+
|
|
16
|
+
Janus is heavily inspired by [Makara](https://github.com/instacart/makara) from TaskRabbit and then Instacart. Unfortunately this project is unmaintained and broke for us with Rails 7.1. This is an attempt to start afresh on the project. It is definitely not as fully featured as Makara at this stage.
|
|
17
|
+
|
|
18
|
+
Learn more about its origins: [https://tech.olioex.com/ruby/2024/04/16/introducing-janus.html](https://tech.olioex.com/ruby/2024/04/16/introducing-janus.html).
|
|
19
|
+
|
|
20
|
+
Notes: the gem requires ActiveRecord `>= 8.0, < 9.0` and Ruby `>= 3.2`, and is tested against MySQL 8.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
Use the current version of the gem from [rubygems](https://rubygems.org/gems/janus-ar) in your `Gemfile`.
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
gem 'janus-ar'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This project assumes that your read/write endpoints are handled by a separate system (e.g. DNS).
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
After a write request during a thread the adapter will continue using the `primary` server, unless the context is specifically released.
|
|
35
|
+
|
|
36
|
+
### Setup
|
|
37
|
+
|
|
38
|
+
#### Rails 7.2+
|
|
39
|
+
|
|
40
|
+
For Rails 7.2 you'll need to manually register the database adaptor in `config/application.rb` after requiring rails but before entering the application configuration, e.g.
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
require 'rails/all'
|
|
44
|
+
|
|
45
|
+
ActiveRecord::ConnectionAdapters.register("janus_trilogy", "ActiveRecord::ConnectionAdapters::JanusTrilogyAdapter", 'janus-ar/active_record/connection_adapters/janus_trilogy_adapter')
|
|
46
|
+
# ...or...
|
|
47
|
+
ActiveRecord::ConnectionAdapters.register("janus_mysql2", "ActiveRecord::ConnectionAdapters::JanusMysql2Adapter", 'janus-ar/active_record/connection_adapters/janus_mysql2_adapter')
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### Rails <= 7.1
|
|
51
|
+
|
|
52
|
+
ActiveRecord 7.1 was tested up to releases v0.15.*. After this release we only tested Rails 7.2+. This does not mean it is not compatible, just not tested.
|
|
53
|
+
|
|
54
|
+
### Configuration
|
|
55
|
+
|
|
56
|
+
Update your **database.yml** as follows:
|
|
57
|
+
|
|
58
|
+
```yml
|
|
59
|
+
development:
|
|
60
|
+
adapter: janus_mysql2
|
|
61
|
+
database: database_name
|
|
62
|
+
janus:
|
|
63
|
+
primary:
|
|
64
|
+
<<: *default
|
|
65
|
+
host: primary-host.local
|
|
66
|
+
replica:
|
|
67
|
+
<<: *default
|
|
68
|
+
password: ithappenstobedifferent
|
|
69
|
+
host: replica-host.local
|
|
70
|
+
```
|
|
71
|
+
Note: For `trilogy` please use adapter "janus_trilogy". You'll probably need to add the following to your configuration to have it connect:
|
|
72
|
+
|
|
73
|
+
```yml
|
|
74
|
+
ssl: true
|
|
75
|
+
ssl_mode: 'REQUIRED'
|
|
76
|
+
tls_min_version: 3
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`tls_min_version` here refers to TLS1.2.
|
|
80
|
+
|
|
81
|
+
Otherwise you will get an error like the following (see https://github.com/trilogy-libraries/trilogy/issues/26):
|
|
82
|
+
> trilogy_auth_recv: caching_sha2_password requires either TCP with TLS or a unix socket: TRILOGY_UNSUPPORTED"
|
|
83
|
+
|
|
84
|
+
### Forcing connections
|
|
85
|
+
|
|
86
|
+
A context is local to the current unit of work (thread or fiber, following ActiveRecord's configured isolation level). This allows you to stick to the primary safely within a single request or job, in systems such as Sidekiq for instance.
|
|
87
|
+
|
|
88
|
+
#### Releasing stuck connections (clearing context)
|
|
89
|
+
|
|
90
|
+
In a Rails application the context is released automatically at the start of every unit of work wrapped by the Rails executor — web requests, ActiveJob and Sidekiq-on-Rails jobs — so stickiness from a write never leaks into the next request on a reused thread. You do not need to do anything for this.
|
|
91
|
+
|
|
92
|
+
Outside of Rails (or to clear the context manually), call:
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
Janus::Context.release_all
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Forcing connection to primary server
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
Janus::Context.stick_to_primary
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Logging
|
|
105
|
+
|
|
106
|
+
You can set a logger instance to `::Janus::Logging::Logger.logger`:
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
Janus::Logging::Logger.logger = ::Logger.new(STDOUT)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
If using `ActiveRecord` logging, Janus will append the name of the connection used to any logs e.g. `[primary]` or `[replica]`.
|
|
113
|
+
|
|
114
|
+
### What queries goes where?
|
|
115
|
+
|
|
116
|
+
In general: Any `SELECT` statements will execute against your replica(s), anything else will go to the primary.
|
|
117
|
+
|
|
118
|
+
There are some edge cases:
|
|
119
|
+
* `SET` operations will be sent to all connections
|
|
120
|
+
* Execution of specific methods such as `connect!`, `disconnect!`, `reconnect!`, and `clear_cache!` are invoked on all underlying connections
|
|
121
|
+
* Calls inside a transaction will always be sent to the primary (otherwise changes from within the transaction could not be read back on most transaction isolation levels)
|
|
122
|
+
* Locking reads (e.g. `SELECT ... FOR UPDATE`, `FOR UPDATE SKIP LOCKED`, `FOR SHARE`, `LOCK IN SHARE MODE`, `GET_LOCK(...)`) will always be sent to the primary
|
|
123
|
+
|
|
124
|
+
# Notes
|
|
125
|
+
|
|
126
|
+
Janus does not support Rails' read/write split or sharding using `with_connection`.
|
|
127
|
+
|
|
128
|
+
# Acknowlegements
|
|
129
|
+
|
|
130
|
+
Amazing project logo by @undevelopedbruce.
|
|
131
|
+
|
|
132
|
+
## Releasing
|
|
133
|
+
|
|
134
|
+
Releases are cut from the [GitHub Releases UI](https://github.com/OLIOEX/janus-ar/releases/new).
|
|
135
|
+
Publishing to RubyGems is automatic — there is nothing to bump by hand, and no
|
|
136
|
+
API key to rotate (authentication uses RubyGems
|
|
137
|
+
[trusted publishing](https://guides.rubygems.org/trusted-publishing/) over OIDC).
|
|
138
|
+
|
|
139
|
+
To release:
|
|
140
|
+
|
|
141
|
+
1. Create a new release against the head of `main`, with a tag named
|
|
142
|
+
`vMAJOR.MINOR.PATCH` — e.g. `v8.1.0`. Pre-release suffixes use a dot, as
|
|
143
|
+
RubyGems requires: `v8.1.0.rc1`, not `v8.1.0-rc1`.
|
|
144
|
+
2. Publish it.
|
|
145
|
+
|
|
146
|
+
[`.github/workflows/publish.yml`](.github/workflows/publish.yml) then takes the
|
|
147
|
+
version from the tag, writes it into `lib/janus-ar/version.rb`, refreshes
|
|
148
|
+
`Gemfile.lock`, commits that bump to `main` as `Release vX.Y.Z`, moves the tag
|
|
149
|
+
onto that commit, and pushes the gem.
|
|
150
|
+
|
|
151
|
+
Because the bump is committed to `main`, releases must be created from its head
|
|
152
|
+
— the workflow refuses to publish if the tag sits anywhere else. You never need
|
|
153
|
+
to edit `version.rb` yourself; the tag is the source of truth.
|