makara 0.3.9 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/CI.yml +88 -0
  4. data/.github/workflows/gem-publish-public.yml +36 -0
  5. data/.rspec +1 -1
  6. data/.rubocop.yml +15 -0
  7. data/.rubocop_todo.yml +670 -0
  8. data/CHANGELOG.md +88 -32
  9. data/Gemfile +1 -16
  10. data/README.md +39 -35
  11. data/Rakefile +1 -1
  12. data/gemfiles/activerecord_5.2.gemfile +8 -0
  13. data/gemfiles/activerecord_6.0.gemfile +8 -0
  14. data/gemfiles/activerecord_6.1.gemfile +8 -0
  15. data/gemfiles/activerecord_head.gemfile +6 -0
  16. data/lib/active_record/connection_adapters/jdbcmysql_makara_adapter.rb +4 -18
  17. data/lib/active_record/connection_adapters/jdbcpostgresql_makara_adapter.rb +4 -18
  18. data/lib/active_record/connection_adapters/makara_abstract_adapter.rb +111 -33
  19. data/lib/active_record/connection_adapters/makara_jdbcmysql_adapter.rb +4 -18
  20. data/lib/active_record/connection_adapters/makara_jdbcpostgresql_adapter.rb +4 -18
  21. data/lib/active_record/connection_adapters/makara_mysql2_adapter.rb +4 -20
  22. data/lib/active_record/connection_adapters/makara_postgis_adapter.rb +4 -19
  23. data/lib/active_record/connection_adapters/makara_postgresql_adapter.rb +4 -20
  24. data/lib/active_record/connection_adapters/mysql2_makara_adapter.rb +4 -20
  25. data/lib/active_record/connection_adapters/postgresql_makara_adapter.rb +4 -20
  26. data/lib/makara.rb +14 -5
  27. data/lib/makara/cache.rb +4 -42
  28. data/lib/makara/config_parser.rb +18 -16
  29. data/lib/makara/connection_wrapper.rb +43 -22
  30. data/lib/makara/context.rb +108 -37
  31. data/lib/makara/cookie.rb +53 -0
  32. data/lib/makara/error_handler.rb +2 -11
  33. data/lib/makara/errors/all_connections_blacklisted.rb +0 -2
  34. data/lib/makara/errors/blacklist_connection.rb +0 -2
  35. data/lib/makara/errors/blacklisted_while_in_transaction.rb +12 -0
  36. data/lib/makara/errors/invalid_shard.rb +14 -0
  37. data/lib/makara/errors/makara_error.rb +0 -1
  38. data/lib/makara/errors/no_connections_available.rb +0 -2
  39. data/lib/makara/logging/logger.rb +1 -5
  40. data/lib/makara/logging/subscriber.rb +0 -2
  41. data/lib/makara/middleware.rb +12 -76
  42. data/lib/makara/pool.rb +55 -47
  43. data/lib/makara/proxy.rb +76 -56
  44. data/lib/makara/railtie.rb +0 -8
  45. data/lib/makara/strategies/abstract.rb +1 -0
  46. data/lib/makara/strategies/priority_failover.rb +2 -0
  47. data/lib/makara/strategies/round_robin.rb +7 -3
  48. data/lib/makara/strategies/shard_aware.rb +45 -0
  49. data/lib/makara/version.rb +2 -4
  50. data/makara.gemspec +26 -3
  51. data/spec/active_record/connection_adapters/makara_abstract_adapter_error_handling_spec.rb +1 -6
  52. data/spec/active_record/connection_adapters/makara_abstract_adapter_spec.rb +10 -14
  53. data/spec/active_record/connection_adapters/makara_mysql2_adapter_spec.rb +18 -16
  54. data/spec/active_record/connection_adapters/makara_postgis_adapter_spec.rb +6 -9
  55. data/spec/active_record/connection_adapters/makara_postgresql_adapter_spec.rb +70 -10
  56. data/spec/cache_spec.rb +2 -53
  57. data/spec/config_parser_spec.rb +75 -57
  58. data/spec/connection_wrapper_spec.rb +6 -4
  59. data/spec/context_spec.rb +163 -100
  60. data/spec/cookie_spec.rb +72 -0
  61. data/spec/middleware_spec.rb +27 -56
  62. data/spec/pool_spec.rb +25 -14
  63. data/spec/proxy_spec.rb +50 -39
  64. data/spec/spec_helper.rb +10 -10
  65. data/spec/strategies/priority_failover_spec.rb +3 -4
  66. data/spec/strategies/round_robin_spec.rb +4 -8
  67. data/spec/strategies/shard_aware_spec.rb +218 -0
  68. data/spec/support/deep_dup.rb +1 -1
  69. data/spec/support/helpers.rb +10 -6
  70. data/spec/support/mock_objects.rb +6 -5
  71. data/spec/support/mysql2_database.yml +3 -2
  72. data/spec/support/mysql2_database_with_custom_errors.yml +6 -1
  73. data/spec/support/pool_extensions.rb +0 -3
  74. data/spec/support/postgis_database.yml +2 -0
  75. data/spec/support/postgis_schema.rb +6 -3
  76. data/spec/support/postgresql_database.yml +2 -2
  77. data/spec/support/proxy_extensions.rb +1 -3
  78. data/spec/support/schema.rb +6 -6
  79. data/spec/support/user.rb +4 -0
  80. metadata +170 -22
  81. data/.travis.yml +0 -70
  82. data/gemfiles/ar-head.gemfile +0 -15
  83. data/gemfiles/ar30.gemfile +0 -32
  84. data/gemfiles/ar31.gemfile +0 -31
  85. data/gemfiles/ar32.gemfile +0 -31
  86. data/gemfiles/ar40.gemfile +0 -17
  87. data/gemfiles/ar41.gemfile +0 -17
  88. data/gemfiles/ar42.gemfile +0 -17
  89. data/gemfiles/ar50.gemfile +0 -15
  90. data/gemfiles/ar51.gemfile +0 -15
  91. data/lib/makara/cache/memory_store.rb +0 -28
  92. data/lib/makara/cache/noop_store.rb +0 -15
data/CHANGELOG.md CHANGED
@@ -1,74 +1,130 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- ## v0.3.8 - 2016-07-11
4
+ ## Unreleased
5
5
 
6
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.7...v0.3.8)
6
+ ### v0.5.1 - 2021-06-04
7
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.5.0...v0.6.0.pre)
8
+ - Use ActiveRecord URL resolver instead of copying definition [#294](https://github.com/instacart/makara/pull/294) Matt Larraz
9
+ - Fix Ruby 2.7 kwarg warning and add Ruby 3 support [#283](https://github.com/instacart/makara/pull/283) Matt Larraz
10
+ - Drop support for Ruby < 2.5 and ActiveRecord < 5.2 [#281](https://github.com/instacart/makara/pull/281) Matt Larraz
11
+
12
+ ## v0.5.0 - 2021-01-08
13
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.4.1...v0.4.2)
14
+ - Replace deprecated URI.unescape with CGI.unescape [#252](https://github.com/instacart/makara/pull/252) Kevin Robatel
15
+ - Override equality operator for ActiveRecord connection wrapper [#269](https://github.com/instacart/makara/pull/269) Praveen Burgu
16
+ - Handle blacklisted connections in master pool while in transaction [#267](https://github.com/instacart/makara/pull/267) Praveen Burgu
17
+ - Handle ActiveRecord connection pools correctly [#267](https://github.com/instacart/makara/pull/267) Praveen Burgu
18
+ - Add preliminary support for sharded databases [#267](https://github.com/instacart/makara/pull/267) Praveen Burgu
19
+ - Fix ActiveRecord connection pool exhaustion [#268](https://github.com/instacart/makara/pull/268) Praveen Burgu
20
+ - Drop support for Ruby 2.0, 2.1 and 2.2 [#267](https://github.com/instacart/makara/pull/267) Praveen Burgu
21
+ - Drop support ActiveRecord 3.x and 4.x [#267](https://github.com/instacart/makara/pull/267) Praveen Burgu
22
+ - Set up automatic publishing to Github and Rubygems [#275](https://github.com/instacart/makara/pull/275) Matt Larraz
23
+
24
+
25
+ ## v0.4.1 - 2019-03-25
26
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.4.0...v0.4.1)
27
+
28
+ - Fix crash by requiring makara in the adapter [#54](https://github.com/instacart/makara/pull/54) Eric Saxby
29
+ - Add connection logging in non-Rails enviroments [#223](https://github.com/instacart/makara/pull/223) Andrew Kane
30
+
31
+ ## v0.4.0 - 2018-04-01
32
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.10...v0.4.0)
33
+
34
+ This release is a major change to how we remember state between requests. A redis store is no longer needed. Everything is in the cookies.
35
+ - Implement stickiness for the duration of `master_ttl` via cookies [#194](https://github.com/instacart/makara/pull/194) Rosa Gutierrez
36
+
37
+
38
+ ## v0.3.10 - 2018-03-20
39
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.9...v0.3.10)
40
+
41
+ Fixed
42
+ - Send nextval queries to master and show queries to replicas for Postgres [#173](https://github.com/instacart/makara/pull/173) Andrew Kane
43
+ - Fixes can't add a new key into hash during iteration error [#174](https://github.com/instacart/makara/pull/174) Andrew Kane
44
+ - Fix: an application freezes when a slave is down [#180](https://github.com/instacart/makara/pull/180) Alexey P
45
+ - Allow SELECTs that use common table expressions to go to replicas [#184](https://github.com/instacart/makara/pull/184) Andrew Kane
46
+ - Send advisory lock requests to the master [#198](https://github.com/instacart/makara/pull/198) George Claghorn
47
+ - Postgres exists query [#199](https://github.com/instacart/makara/pull/199) Brian Leonard
48
+
49
+ Documentation and Test
50
+ - Clarify README's "What goes where" [#187](https://github.com/instacart/makara/pull/187) Jan Sandbrink
51
+ - Fix loading fixtures in Rails 5.2 [#192](https://github.com/instacart/makara/pull/192) George Claghorn
52
+ - Travis Upgrade [#199](https://github.com/instacart/makara/pull/199) Brian Leonard
53
+
54
+ ## v0.3.9 - 2017-08-14
55
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.8...v0.3.9)
56
+
57
+ Changed
58
+ - Add postgis support [#118](https://github.com/instacart/makara/pull/118) Kevin Bacha
59
+
60
+ ## v0.3.8 - 2017-07-11
61
+
62
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.7...v0.3.8)
7
63
 
8
64
  Changed
9
- - Rails 5.1 compatibility [#150](https://github.com/taskrabbit/makara/pull/150) Jeremy Daer
10
- - Minimize redundant context cache requests [#157](https://github.com/taskrabbit/makara/issues/157) Greg Patrick
11
- - thread-local cache for previous context stickiness [#158](https://github.com/taskrabbit/makara/issues/158) Jeremy Daer
12
- - Configurable cookie options [#159](https://github.com/taskrabbit/makara/pull/159) Jeremy Daer
13
- - Test against Rails 5.x and Ruby 2.x [#160](https://github.com/taskrabbit/makara/pull/160) Jeremy Daer
65
+ - Rails 5.1 compatibility [#150](https://github.com/instacart/makara/pull/150) Jeremy Daer
66
+ - Minimize redundant context cache requests [#157](https://github.com/instacart/makara/issues/157) Greg Patrick
67
+ - thread-local cache for previous context stickiness [#158](https://github.com/instacart/makara/issues/158) Jeremy Daer
68
+ - Configurable cookie options [#159](https://github.com/instacart/makara/pull/159) Jeremy Daer
69
+ - Test against Rails 5.x and Ruby 2.x [#160](https://github.com/instacart/makara/pull/160) Jeremy Daer
14
70
 
15
71
  ## v0.3.7 - 2016-09-22
16
72
 
17
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.6...v0.3.7)
73
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.6...v0.3.7)
18
74
 
19
75
  Changed
20
76
 
21
- - Fix the hierarchy of the config file [#116](https://github.com/taskrabbit/makara/pull/116) Kevin Bacha
22
- - "Disable blacklist" parameter [#134](https://github.com/taskrabbit/makara/pull/134) Alex Tonkonozhenko
23
- - Fixes bug in `without_sticking` [#96](https://github.com/taskrabbit/makara/pull/96) Brian Leonard
24
- - Always stick inside transactions [#96](https://github.com/taskrabbit/makara/pull/96) Brian Leonard
25
- - Rails 5 support [#122](https://github.com/taskrabbit/makara/pull/122) Jonny McAllister
77
+ - Fix the hierarchy of the config file [#116](https://github.com/instacart/makara/pull/116) Kevin Bacha
78
+ - "Disable blacklist" parameter [#134](https://github.com/instacart/makara/pull/134) Alex Tonkonozhenko
79
+ - Fixes bug in `without_sticking` [#96](https://github.com/instacart/makara/pull/96) Brian Leonard
80
+ - Always stick inside transactions [#96](https://github.com/instacart/makara/pull/96) Brian Leonard
81
+ - Rails 5 support [#122](https://github.com/instacart/makara/pull/122) Jonny McAllister
26
82
 
27
83
  ## v0.3.6 - 2016-04-21
28
84
 
29
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.5...v0.3.6)
85
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.5...v0.3.6)
30
86
 
31
87
  Changed
32
88
 
33
- - Allow different strategies such as `priority` and `round_robin` for pools [#105](https://github.com/taskrabbit/makara/pull/105) Brian Leonard
89
+ - Allow different strategies such as `priority` and `round_robin` for pools [#105](https://github.com/instacart/makara/pull/105) Brian Leonard
34
90
 
35
91
 
36
92
  ## v0.3.5 - 2016-01-08
37
93
 
38
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.4.rc1...v0.3.5)
94
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.4.rc1...v0.3.5)
39
95
 
40
96
  Changed
41
97
 
42
- - Raise `Makara::Errors::AllConnectionsBlacklisted` on timeout. [#104](https://github.com/taskrabbit/makara/pull/104) Brian Leonard
98
+ - Raise `Makara::Errors::AllConnectionsBlacklisted` on timeout. [#104](https://github.com/instacart/makara/pull/104) Brian Leonard
43
99
 
44
100
  ## v0.3.4.rc1 - 2016-01-06
45
101
 
46
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.3...v0.3.4.rc1)
102
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.3...v0.3.4.rc1)
47
103
 
48
104
  Added
49
105
 
50
- - Add `url` to database connections configurations. [#93](https://github.com/taskrabbit/makara/pull/93) Benjamin Fleischer
106
+ - Add `url` to database connections configurations. [#93](https://github.com/instacart/makara/pull/93) Benjamin Fleischer
51
107
 
52
108
  Changed
53
109
 
54
- - Improve Postgresql compatibility and failover support, also fix [#78](https://github.com/taskrabbit/makara/issues/78), [#79](https://github.com/taskrabbit/makara/issues/79). [#87](https://github.com/taskrabbit/makara/pull/87) Vlad
55
- - Update README: Specify newrelic_rpm gem versions that will have the performance issue. [#95](https://github.com/taskrabbit/makara/pull/95) Benjamin Fleischer
110
+ - Improve Postgresql compatibility and failover support, also fix [#78](https://github.com/instacart/makara/issues/78), [#79](https://github.com/instacart/makara/issues/79). [#87](https://github.com/instacart/makara/pull/87) Vlad
111
+ - Update README: Specify newrelic_rpm gem versions that will have the performance issue. [#95](https://github.com/instacart/makara/pull/95) Benjamin Fleischer
56
112
 
57
113
  ## v0.3.3 - 2015-05-20
58
114
 
59
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.2...v0.3.3)
115
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.2...v0.3.3)
60
116
 
61
117
  Changed
62
118
 
63
- - A context is local to the curent thread of execution. This will allow you to stick to master safely in a single thread in systems such as sidekiq, for instance. Fix [#83](https://github.com/taskrabbit/makara/issues/83). [#84](https://github.com/taskrabbit/makara/pull/84) Matt Camuto
119
+ - A context is local to the curent thread of execution. This will allow you to stick to master safely in a single thread in systems such as sidekiq, for instance. Fix [#83](https://github.com/instacart/makara/issues/83). [#84](https://github.com/instacart/makara/pull/84) Matt Camuto
64
120
 
65
121
  ## v0.3.2 - 2015-05-16
66
122
 
67
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.1...v0.3.2)
123
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.1...v0.3.2)
68
124
 
69
125
  Fixed
70
126
 
71
- - Fix a `ArgumentError: not delegated` error for rails 3. [#82](https://github.com/taskrabbit/makara/pull/82) Eric Saxby
127
+ - Fix a `ArgumentError: not delegated` error for rails 3. [#82](https://github.com/instacart/makara/pull/82) Eric Saxby
72
128
 
73
129
  Changed
74
130
 
@@ -76,7 +132,7 @@ Changed
76
132
 
77
133
  ## v0.3.1 - 2015-05-08
78
134
 
79
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.0...v0.3.1)
135
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.0...v0.3.1)
80
136
 
81
137
  Changed
82
138
 
@@ -86,21 +142,21 @@ Changed
86
142
 
87
143
  ## v0.3.0 - 2015-04-27
88
144
 
89
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.0.rc3...v0.3.0)
145
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.0.rc3...v0.3.0)
90
146
 
91
147
  Changed
92
148
 
93
- - Reduce logging noise by using [the same rules as ActiveRecord uses](https://github.com/rails/rails/blob/b06f64c3480cd389d14618540d62da4978918af0/activerecord/lib/active_record/log_subscriber.rb#L33). [#76](https://github.com/taskrabbit/makara/pull/76) Andrew Kane
149
+ - Reduce logging noise by using [the same rules as ActiveRecord uses](https://github.com/rails/rails/blob/b06f64c3480cd389d14618540d62da4978918af0/activerecord/lib/active_record/log_subscriber.rb#L33). [#76](https://github.com/instacart/makara/pull/76) Andrew Kane
94
150
 
95
151
  Fixed
96
152
 
97
- - Fix an issue for postgres that would route all queries to master. [#72](https://github.com/taskrabbit/makara/pull/72) Kali Donovan
98
- - Fix an edge case which would cause SET operations to send to all connections([#70](https://github.com/taskrabbit/makara/issues/70)). [#80](https://github.com/taskrabbit/makara/pull/80) Michael Amor Righi
99
- - Fix performance regression with certain verions of [newrelic/rpm](https://github.com/newrelic/rpm)([#59](https://github.com/taskrabbit/makara/issues/59)). [#75](https://github.com/taskrabbit/makara/pull/75) Mike Nelson
153
+ - Fix an issue for postgres that would route all queries to master. [#72](https://github.com/instacart/makara/pull/72) Kali Donovan
154
+ - Fix an edge case which would cause SET operations to send to all connections([#70](https://github.com/instacart/makara/issues/70)). [#80](https://github.com/instacart/makara/pull/80) Michael Amor Righi
155
+ - Fix performance regression with certain verions of [newrelic/rpm](https://github.com/newrelic/rpm)([#59](https://github.com/instacart/makara/issues/59)). [#75](https://github.com/instacart/makara/pull/75) Mike Nelson
100
156
 
101
157
  ## 0.3.0.rc3 - 2014-09-02[YANKED]
102
158
 
103
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.0.rc2...v0.3.0.rc3)
159
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.0.rc2...v0.3.0.rc3)
104
160
 
105
161
  Added
106
162
  - Allow bypassing of stickiness
data/Gemfile CHANGED
@@ -1,19 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in makara.gemspec
4
4
  gemspec
5
-
6
- gem 'rake'
7
- gem 'rspec'
8
- gem 'timecop'
9
- gem 'byebug', :platform => :ruby
10
- gem 'ruby-debug', :platform => :jruby
11
- gem 'rack', '1.6.0'
12
-
13
- gem 'mysql2', :platform => :ruby
14
- gem 'pg', :platform => :ruby
15
- gem 'activerecord-postgis-adapter', :platform => :ruby
16
- gem 'rgeo', :platform => :ruby
17
-
18
- gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
19
- gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
data/README.md CHANGED
@@ -1,19 +1,12 @@
1
1
  # Makara
2
2
 
3
- [![Build Status](https://travis-ci.org/taskrabbit/makara.png?branch=master)](https://travis-ci.org/taskrabbit/makara)
3
+ ![Build Status](https://github.com/instacart/makara/workflows/CI/badge.svg)
4
+ [![Gem Version](https://badge.fury.io/rb/makara.svg)](https://badge.fury.io/rb/makara)
4
5
  [![Code Climate](https://codeclimate.com/repos/526886a7f3ea00679b00cae6/badges/7905f7a000492a1078f7/gpa.png)](https://codeclimate.com/repos/526886a7f3ea00679b00cae6/feed)
5
6
 
6
7
 
7
8
  Makara is generic master/slave proxy. It handles the heavy lifting of managing, choosing, blacklisting, and cycling through connections. It comes with an ActiveRecord database adapter implementation.
8
9
 
9
- #### Warning:
10
-
11
- There is a potential performance issue when used alongside certain versions of
12
- [newrelic/rpm](https://github.com/newrelic/rpm), [Issue #59](https://github.com/taskrabbit/makara/issues/59).
13
-
14
- > Any newrelic_rpm `< 3.11.2` and `>= 3.7.2` will have the regression.
15
- > I'd recommend upgrading newrelic_rpm to avoid the problem.
16
-
17
10
  ## Installation
18
11
 
19
12
  Use the current version of the gem from [rubygems](https://rubygems.org/gems/makara) in your `Gemfile`.
@@ -61,40 +54,50 @@ This implementation will send any request not like "SELECT..." to a master conne
61
54
 
62
55
  Makara comes with a config parser which will handle providing subconfigs to the `connection_for` method. Check out the ActiveRecord database.yml example below for more info.
63
56
 
64
- ### Context
57
+ ### Stickiness Context
65
58
 
66
- Makara handles stickyness by keeping track of a context (sha). In a multi-instance environment it persists a context in a cache. If Rails is present it will automatically use Rails.cache. You can provide any kind of store as long as it responds to the methods required in [lib/makara/cache.rb](lib/makara/cache.rb).
59
+ Makara handles stickiness by keeping track of which proxies are stuck at any given moment. The context is basically a mapping of proxy ids to the timestamp until which they are stuck.
67
60
 
68
- ```ruby
69
- Makara::Cache.store = MyRedisCacheStore.new
70
- ```
61
+ To handle persistence of context across requests in a Rack app, makara provides a middleware. It lays a cookie named `_mkra_stck` which contains the current context. If the next request is executed before the cookie expires, that given context will be used. If something occurs which naturally requires master on the second request, the context is updated and stored again.
62
+
63
+ #### Stickiness Impact
64
+
65
+ When `sticky:true`, once a query as been sent to master, all queries for the rest of the request will also be sent to master. In addition, the cookie described above will be set client side with an expiration defined by time at end of original request + `master_ttl`. As long as the cookie is valid, all requests will send queries to master.
66
+
67
+ When `sticky:false`, only queries that need to go to master will go there. Subsequent read queries in the same request will go to slaves.
71
68
 
72
- To handle persistence of context across requests in a Rack app, makara provides a middleware. It lays a cookie named `_mkra_ctxt` which contains the current master context. If the next request is executed before the cookie expires, master will be used. If something occurs which naturally requires master on the second request, the context is changed and stored again.
69
+ #### Releasing stuck connections (clearing context)
73
70
 
74
- #### Changing Context
71
+ If you need to clear the current context, releasing any stuck connections, all you have to do is:
75
72
 
76
- If you need to change the makara context, releasing any stuck connections, all you have to do is:
73
+ ```ruby
74
+ Makara::Context.release_all
75
+ ```
77
76
 
77
+ You can also clear stuck connections for a specific proxy:
78
78
  ```ruby
79
- ctx = Makara::Context.generate # or any unique sha
80
- Makara::Context.set_current ctx
79
+ Makara::Context.release(proxy_id)
80
+ Makara::Context.release('mysql_main')
81
+ Makara::Context.release('redis')
82
+ ...
81
83
  ```
82
84
 
83
85
  A context is local to the curent thread of execution. This will allow you to stick to master safely in a single thread
84
86
  in systems such as sidekiq, for instance.
85
87
 
86
88
 
87
- ### Forcing Master
89
+ #### Forcing Master
88
90
 
89
91
  If you need to force master in your app then you can simply invoke stick_to_master! on your connection:
90
92
 
91
93
  ```ruby
92
- write_to_cache = true # or false
93
- proxy.stick_to_master!(write_to_cache)
94
+ persist = true # or false, it's true by default
95
+ proxy.stick_to_master!(persist)
94
96
  ```
95
97
 
98
+ It'll keep the proxy stuck to master for the current request, and if `persist = true` (default), it'll be also stored in the context for subsequent requests, keeping the proxy stuck up to the duration of `master_ttl` configured for the proxy.
96
99
 
97
- ### Skipping the Stickiness
100
+ #### Skipping the Stickiness
98
101
 
99
102
  If you're using the `sticky: true` configuration and you find yourself in a situation where you need to write information through the proxy but you don't want the context to be stuck to master, you should use a `without_sticking` block:
100
103
 
@@ -120,7 +123,13 @@ By creating a makara database adapter which simply acts as a proxy we avoid any
120
123
 
121
124
  ### What goes where?
122
125
 
123
- Any `SELECT` statements will execute against your slave(s), anything else will go to master. The only edge case is `SET` operations which are sent to all connections. Execution of specific methods such as `connect!`, `disconnect!`, and `clear_cache!` are invoked on all underlying connections.
126
+ In general: Any `SELECT` statements will execute against your slave(s), anything else will go to master.
127
+
128
+ There are some edge cases:
129
+ * `SET` operations will be sent to all connections
130
+ * Execution of specific methods such as `connect!`, `disconnect!`, and `clear_cache!` are invoked on all underlying connections
131
+ * Calls inside a transaction will always be sent to the master (otherwise changes from within the transaction could not be read back on most transaction isolation levels)
132
+ * Locking reads (e.g. `SELECT ... FOR UPDATE`) will always be sent to the master
124
133
 
125
134
  ### Errors / blacklisting
126
135
 
@@ -139,6 +148,8 @@ production:
139
148
  # add a makara subconfig
140
149
  makara:
141
150
 
151
+ # optional id to identify the proxy with this configuration for stickiness
152
+ id: mysql
142
153
  # the following are default values
143
154
  blacklist_duration: 5
144
155
  master_ttl: 5
@@ -161,11 +172,13 @@ Let's break this down a little bit. At the top level of your config you have the
161
172
  Following the adapter choice is all the standard configurations (host, port, retry, database, username, password, etc). With all the standard configurations provided, you can now provide the makara subconfig.
162
173
 
163
174
  The makara subconfig sets up the proxy with a few of its own options, then provides the connection list. The makara options are:
175
+ * id - an identifier for the proxy, used for sticky behaviour and context. The default is to use a MD5 hash of the configuration contents, so if you are setting `sticky` to true, it's a good idea to also set an `id`. Otherwise any stuck connections will be cleared if the configuration changes (as the default MD5 hash id would change as well)
164
176
  * blacklist_duration - the number of seconds a node is blacklisted when a connection failure occurs
165
177
  * disable_blacklist - do not blacklist node at any error, useful in case of one master
166
178
  * sticky - if a node should be stuck to once it's used during a specific context
167
179
  * master_ttl - how long the master context is persisted. generally, this needs to be longer than any replication lag
168
- * master_strategy - use a different strategy for picking the "current" node: `failover` will try to keep the same one until it is blacklisted. The default is `round_robin` which will cycle through available ones.
180
+ * master_strategy - use a different strategy for picking the "current" master node: `failover` will try to keep the same one until it is blacklisted. The default is `round_robin` which will cycle through available ones.
181
+ * slave_strategy - use a different strategy for picking the "current" slave node: `failover` will try to keep the same one until it is blacklisted. The default is `round_robin` which will cycle through available ones.
169
182
  * connection_error_matchers - array of custom error matchers you want to be handled gracefully by Makara (as in, errors matching these regexes will result in blacklisting the connection as opposed to raising directly).
170
183
 
171
184
  Connection definitions contain any extra node-specific configurations. If the node should behave as a master you must provide `role: master`. Any previous configurations can be overridden within a specific node's config. Nodes can also contain weights if you'd like to balance usage based on hardware specifications. Optionally, you can provide a name attribute which will be used in sql logging.
@@ -268,16 +281,7 @@ def handle_request_after_third_party_record_creation
268
281
  end
269
282
  ```
270
283
 
271
- Similarly, if you have a third party service which will conduct a generic request against your Rack app, you can force master via a query param:
272
-
273
- ```ruby
274
- def send_url_to_third_party
275
- context = Makara::Context.get_current
276
- ThirdParty.read_from_here!("http://mysite.com/path/to/resource?_mkra_ctxt=#{context}")
277
- end
278
- ```
279
-
280
284
  ## Todo
281
285
 
282
- * Cookie based cache store?
286
+ * Support for providing context as query param
283
287
  * More real world examples
data/Rakefile CHANGED
@@ -6,4 +6,4 @@ require 'rspec/core/rake_task'
6
6
  RSpec::Core::RakeTask.new(:spec) do |spec|
7
7
  spec.pattern = 'spec/**/*_spec.rb'
8
8
  end
9
- task :default => :spec
9
+ task default: :spec
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in makara.gemspec
4
+ gemspec path: "../"
5
+
6
+ gem "activerecord", "~> 5.2.0"
7
+
8
+ # gem "mysql2", "~> 0.4.10", platform: :ruby
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in makara.gemspec
4
+ gemspec path: "../"
5
+
6
+ gem "activerecord", "~> 6.0.0"
7
+
8
+ # gem "mysql2", "~> 0.4.10", platform: :ruby
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in makara.gemspec
4
+ gemspec path: "../"
5
+
6
+ gem "activerecord", "~> 6.1.0"
7
+
8
+ # gem "mysql2", "~> 0.4.10", platform: :ruby
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in makara.gemspec
4
+ gemspec path: "../"
5
+
6
+ gem "activerecord", github: "rails/rails", branch: "main"
@@ -2,24 +2,10 @@ require 'active_record/connection_adapters/makara_abstract_adapter'
2
2
  require 'active_record/connection_adapters/jdbcmysql_adapter'
3
3
  require 'active_record/connection_adapters/mysql2_makara_adapter'
4
4
 
5
- if ActiveRecord::VERSION::MAJOR >= 4
6
-
7
- module ActiveRecord
8
- module ConnectionHandling
9
- def jdbcmysql_makara_connection(config)
10
- mysql2_makara_connection(config)
11
- end
12
- end
13
- end
14
-
15
- else
16
-
17
- module ActiveRecord
18
- class Base
19
- def self.jdbcmysql_makara_connection(config)
20
- self.mysql2_makara_connection(config)
21
- end
5
+ module ActiveRecord
6
+ module ConnectionHandling
7
+ def jdbcmysql_makara_connection(config)
8
+ mysql2_makara_connection(config)
22
9
  end
23
10
  end
24
-
25
11
  end
@@ -2,24 +2,10 @@ require 'active_record/connection_adapters/makara_abstract_adapter'
2
2
  require 'active_record/connection_adapters/jdbcpostgresql_adapter'
3
3
  require 'active_record/connection_adapters/postgresql_makara_adapter'
4
4
 
5
- if ActiveRecord::VERSION::MAJOR >= 4
6
-
7
- module ActiveRecord
8
- module ConnectionHandling
9
- def jdbcpostgresql_makara_connection(config)
10
- postgresql_makara_connection(config)
11
- end
12
- end
13
- end
14
-
15
- else
16
-
17
- module ActiveRecord
18
- class Base
19
- def self.jdbcpostgresql_makara_connection(config)
20
- self.postgresql_makara_connection(config)
21
- end
5
+ module ActiveRecord
6
+ module ConnectionHandling
7
+ def jdbcpostgresql_makara_connection(config)
8
+ postgresql_makara_connection(config)
22
9
  end
23
10
  end
24
-
25
11
  end