makara 0.4.1 → 0.5.1

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.
Files changed (88) 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 +69 -48
  9. data/Gemfile +1 -16
  10. data/README.md +8 -9
  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 +107 -30
  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/cache.rb +0 -2
  27. data/lib/makara/config_parser.rb +7 -15
  28. data/lib/makara/connection_wrapper.rb +43 -22
  29. data/lib/makara/context.rb +1 -0
  30. data/lib/makara/cookie.rb +1 -0
  31. data/lib/makara/error_handler.rb +0 -9
  32. data/lib/makara/errors/all_connections_blacklisted.rb +0 -2
  33. data/lib/makara/errors/blacklist_connection.rb +0 -2
  34. data/lib/makara/errors/blacklisted_while_in_transaction.rb +12 -0
  35. data/lib/makara/errors/invalid_shard.rb +14 -0
  36. data/lib/makara/errors/makara_error.rb +0 -1
  37. data/lib/makara/errors/no_connections_available.rb +0 -2
  38. data/lib/makara/logging/logger.rb +0 -4
  39. data/lib/makara/logging/subscriber.rb +0 -2
  40. data/lib/makara/middleware.rb +1 -2
  41. data/lib/makara/pool.rb +49 -31
  42. data/lib/makara/proxy.rb +56 -30
  43. data/lib/makara/railtie.rb +0 -2
  44. data/lib/makara/strategies/abstract.rb +1 -0
  45. data/lib/makara/strategies/priority_failover.rb +2 -0
  46. data/lib/makara/strategies/round_robin.rb +1 -3
  47. data/lib/makara/strategies/shard_aware.rb +45 -0
  48. data/lib/makara/version.rb +1 -3
  49. data/lib/makara.rb +7 -6
  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 +0 -9
  53. data/spec/active_record/connection_adapters/makara_mysql2_adapter_spec.rb +9 -22
  54. data/spec/active_record/connection_adapters/makara_postgis_adapter_spec.rb +2 -10
  55. data/spec/active_record/connection_adapters/makara_postgresql_adapter_spec.rb +62 -18
  56. data/spec/cache_spec.rb +0 -1
  57. data/spec/config_parser_spec.rb +54 -56
  58. data/spec/connection_wrapper_spec.rb +1 -2
  59. data/spec/cookie_spec.rb +4 -4
  60. data/spec/middleware_spec.rb +2 -2
  61. data/spec/pool_spec.rb +25 -14
  62. data/spec/proxy_spec.rb +0 -4
  63. data/spec/spec_helper.rb +6 -1
  64. data/spec/strategies/priority_failover_spec.rb +3 -4
  65. data/spec/strategies/round_robin_spec.rb +4 -8
  66. data/spec/strategies/shard_aware_spec.rb +218 -0
  67. data/spec/support/deep_dup.rb +1 -1
  68. data/spec/support/helpers.rb +5 -5
  69. data/spec/support/mock_objects.rb +5 -4
  70. data/spec/support/mysql2_database.yml +2 -2
  71. data/spec/support/mysql2_database_with_custom_errors.yml +2 -2
  72. data/spec/support/pool_extensions.rb +0 -3
  73. data/spec/support/postgis_schema.rb +1 -1
  74. data/spec/support/postgresql_database.yml +0 -2
  75. data/spec/support/proxy_extensions.rb +1 -3
  76. data/spec/support/schema.rb +1 -1
  77. data/spec/support/user.rb +1 -2
  78. metadata +165 -20
  79. data/.travis.yml +0 -105
  80. data/gemfiles/ar-head.gemfile +0 -24
  81. data/gemfiles/ar30.gemfile +0 -36
  82. data/gemfiles/ar31.gemfile +0 -36
  83. data/gemfiles/ar32.gemfile +0 -36
  84. data/gemfiles/ar40.gemfile +0 -24
  85. data/gemfiles/ar41.gemfile +0 -24
  86. data/gemfiles/ar42.gemfile +0 -24
  87. data/gemfiles/ar50.gemfile +0 -24
  88. data/gemfiles/ar51.gemfile +0 -24
data/CHANGELOG.md CHANGED
@@ -1,109 +1,130 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## Unreleased
5
+
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
+
4
25
  ## v0.4.1 - 2019-03-25
5
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.4.0...v0.4.1)
26
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.4.0...v0.4.1)
6
27
 
7
- - Fix crash by requiring makara in the adapter [#54](https://github.com/taskrabbit/makara/pull/54) Eric Saxby
8
- - Add connection logging in non-Rails enviroments [#223](https://github.com/taskrabbit/makara/pull/223) Andrew Kane
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
9
30
 
10
31
  ## v0.4.0 - 2018-04-01
11
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.10...v0.4.0)
32
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.10...v0.4.0)
12
33
 
13
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.
14
- - Implement stickiness for the duration of `master_ttl` via cookies [#194](https://github.com/taskrabbit/makara/pull/194) Rosa Gutierrez
35
+ - Implement stickiness for the duration of `master_ttl` via cookies [#194](https://github.com/instacart/makara/pull/194) Rosa Gutierrez
15
36
 
16
37
 
17
38
  ## v0.3.10 - 2018-03-20
18
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.9...v0.3.10)
39
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.9...v0.3.10)
19
40
 
20
41
  Fixed
21
- - Send nextval queries to master and show queries to replicas for Postgres [#173](https://github.com/taskrabbit/makara/pull/173) Andrew Kane
22
- - Fixes can't add a new key into hash during iteration error [#174](https://github.com/taskrabbit/makara/pull/174) Andrew Kane
23
- - Fix: an application freezes when a slave is down [#180](https://github.com/taskrabbit/makara/pull/180) Alexey P
24
- - Allow SELECTs that use common table expressions to go to replicas [#184](https://github.com/taskrabbit/makara/pull/184) Andrew Kane
25
- - Send advisory lock requests to the master [#198](https://github.com/taskrabbit/makara/pull/198) George Claghorn
26
- - Postgres exists query [#199](https://github.com/taskrabbit/makara/pull/199) Brian Leonard
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
27
48
 
28
49
  Documentation and Test
29
- - Clarify README's "What goes where" [#187](https://github.com/taskrabbit/makara/pull/187) Jan Sandbrink
30
- - Fix loading fixtures in Rails 5.2 [#192](https://github.com/taskrabbit/makara/pull/192) George Claghorn
31
- - Travis Upgrade [#199](https://github.com/taskrabbit/makara/pull/199) Brian Leonard
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
32
53
 
33
54
  ## v0.3.9 - 2017-08-14
34
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.8...v0.3.9)
55
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.8...v0.3.9)
35
56
 
36
57
  Changed
37
- - Add postgis support [#118](https://github.com/taskrabbit/makara/pull/118) Kevin Bacha
58
+ - Add postgis support [#118](https://github.com/instacart/makara/pull/118) Kevin Bacha
38
59
 
39
60
  ## v0.3.8 - 2017-07-11
40
61
 
41
- [Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.7...v0.3.8)
62
+ [Full Changelog](https://github.com/instacart/makara/compare/v0.3.7...v0.3.8)
42
63
 
43
64
  Changed
44
- - Rails 5.1 compatibility [#150](https://github.com/taskrabbit/makara/pull/150) Jeremy Daer
45
- - Minimize redundant context cache requests [#157](https://github.com/taskrabbit/makara/issues/157) Greg Patrick
46
- - thread-local cache for previous context stickiness [#158](https://github.com/taskrabbit/makara/issues/158) Jeremy Daer
47
- - Configurable cookie options [#159](https://github.com/taskrabbit/makara/pull/159) Jeremy Daer
48
- - 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
49
70
 
50
71
  ## v0.3.7 - 2016-09-22
51
72
 
52
- [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)
53
74
 
54
75
  Changed
55
76
 
56
- - Fix the hierarchy of the config file [#116](https://github.com/taskrabbit/makara/pull/116) Kevin Bacha
57
- - "Disable blacklist" parameter [#134](https://github.com/taskrabbit/makara/pull/134) Alex Tonkonozhenko
58
- - Fixes bug in `without_sticking` [#96](https://github.com/taskrabbit/makara/pull/96) Brian Leonard
59
- - Always stick inside transactions [#96](https://github.com/taskrabbit/makara/pull/96) Brian Leonard
60
- - 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
61
82
 
62
83
  ## v0.3.6 - 2016-04-21
63
84
 
64
- [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)
65
86
 
66
87
  Changed
67
88
 
68
- - 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
69
90
 
70
91
 
71
92
  ## v0.3.5 - 2016-01-08
72
93
 
73
- [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)
74
95
 
75
96
  Changed
76
97
 
77
- - 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
78
99
 
79
100
  ## v0.3.4.rc1 - 2016-01-06
80
101
 
81
- [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)
82
103
 
83
104
  Added
84
105
 
85
- - 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
86
107
 
87
108
  Changed
88
109
 
89
- - 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
90
- - 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
91
112
 
92
113
  ## v0.3.3 - 2015-05-20
93
114
 
94
- [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)
95
116
 
96
117
  Changed
97
118
 
98
- - 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
99
120
 
100
121
  ## v0.3.2 - 2015-05-16
101
122
 
102
- [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)
103
124
 
104
125
  Fixed
105
126
 
106
- - 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
107
128
 
108
129
  Changed
109
130
 
@@ -111,7 +132,7 @@ Changed
111
132
 
112
133
  ## v0.3.1 - 2015-05-08
113
134
 
114
- [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)
115
136
 
116
137
  Changed
117
138
 
@@ -121,21 +142,21 @@ Changed
121
142
 
122
143
  ## v0.3.0 - 2015-04-27
123
144
 
124
- [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)
125
146
 
126
147
  Changed
127
148
 
128
- - 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
129
150
 
130
151
  Fixed
131
152
 
132
- - Fix an issue for postgres that would route all queries to master. [#72](https://github.com/taskrabbit/makara/pull/72) Kali Donovan
133
- - 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
134
- - 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
135
156
 
136
157
  ## 0.3.0.rc3 - 2014-09-02[YANKED]
137
158
 
138
- [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)
139
160
 
140
161
  Added
141
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', '0.21.0', :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`.
@@ -67,6 +60,12 @@ Makara handles stickiness by keeping track of which proxies are stuck at any giv
67
60
 
68
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.
69
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.
68
+
70
69
  #### Releasing stuck connections (clearing context)
71
70
 
72
71
  If you need to clear the current context, releasing any stuck connections, all you have to do is:
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
@@ -4,18 +4,13 @@ require 'makara'
4
4
  module ActiveRecord
5
5
  module ConnectionAdapters
6
6
  class MakaraAbstractAdapter < ::Makara::Proxy
7
-
8
-
9
7
  class ErrorHandler < ::Makara::ErrorHandler
10
-
11
-
12
8
  HARSH_ERRORS = [
13
9
  'ActiveRecord::RecordNotUnique',
14
10
  'ActiveRecord::InvalidForeignKey',
15
11
  'Makara::Errors::BlacklistConnection'
16
12
  ].map(&:freeze).freeze
17
13
 
18
-
19
14
  CONNECTION_MATCHERS = [
20
15
  /(closed|lost|no|terminating|terminated)\s?([^\s]+)?\sconnection/,
21
16
  /gone away/,
@@ -32,11 +27,8 @@ module ActiveRecord
32
27
  /the database system is (starting|shutting)/
33
28
  ].map(&:freeze).freeze
34
29
 
35
-
36
30
  def handle(connection)
37
-
38
31
  yield
39
-
40
32
  rescue Exception => e
41
33
  # do it via class name to avoid version-specific constant dependencies
42
34
  case e.class.name
@@ -49,20 +41,16 @@ module ActiveRecord
49
41
  harshly(e)
50
42
  end
51
43
  end
52
-
53
44
  end
54
45
 
55
-
56
46
  def harsh_errors
57
47
  HARSH_ERRORS
58
48
  end
59
49
 
60
-
61
50
  def connection_matchers
62
51
  CONNECTION_MATCHERS
63
52
  end
64
53
 
65
-
66
54
  def connection_message?(message)
67
55
  message = message.to_s.downcase
68
56
 
@@ -74,7 +62,6 @@ module ActiveRecord
74
62
  end
75
63
  end
76
64
 
77
-
78
65
  def custom_error_message?(connection, message)
79
66
  custom_error_matchers = connection._makara_custom_error_matchers
80
67
  return false if custom_error_matchers.empty?
@@ -82,7 +69,6 @@ module ActiveRecord
82
69
  message = message.to_s
83
70
 
84
71
  custom_error_matchers.each do |matcher|
85
-
86
72
  if matcher.is_a?(String)
87
73
 
88
74
  # accept strings that look like "/.../" as a regex
@@ -101,49 +87,43 @@ module ActiveRecord
101
87
 
102
88
  false
103
89
  end
104
-
105
-
106
90
  end
107
91
 
108
-
109
92
  hijack_method :execute, :exec_query, :exec_no_cache, :exec_cache, :transaction
110
93
  send_to_all :connect, :reconnect!, :verify!, :clear_cache!, :reset!
111
94
 
95
+ control_method :close, :steal!, :expire, :lease, :in_use?, :owner, :schema_cache, :pool=, :pool,
96
+ :schema_cache=, :lock, :seconds_idle, :==
97
+
112
98
  SQL_MASTER_MATCHERS = [/\A\s*select.+for update\Z/i, /select.+lock in share mode\Z/i, /\A\s*select.+(nextval|currval|lastval|get_lock|release_lock|pg_advisory_lock|pg_advisory_unlock)\(/i].map(&:freeze).freeze
113
99
  SQL_SLAVE_MATCHERS = [/\A\s*(select|with.+\)\s*select)\s/i].map(&:freeze).freeze
114
100
  SQL_ALL_MATCHERS = [/\A\s*set\s/i].map(&:freeze).freeze
115
101
  SQL_SKIP_STICKINESS_MATCHERS = [/\A\s*show\s([\w]+\s)?(field|table|database|schema|view|index)(es|s)?/i, /\A\s*(set|describe|explain|pragma)\s/i].map(&:freeze).freeze
116
102
 
117
-
118
103
  def sql_master_matchers
119
104
  SQL_MASTER_MATCHERS
120
105
  end
121
106
 
122
-
123
107
  def sql_slave_matchers
124
108
  SQL_SLAVE_MATCHERS
125
109
  end
126
110
 
127
-
128
111
  def sql_all_matchers
129
112
  SQL_ALL_MATCHERS
130
113
  end
131
114
 
132
-
133
115
  def sql_skip_stickiness_matchers
134
116
  SQL_SKIP_STICKINESS_MATCHERS
135
117
  end
136
118
 
137
-
138
119
  def initialize(config)
139
120
  @error_handler = ::ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter::ErrorHandler.new
121
+ @control = ActiveRecordPoolControl.new(self)
140
122
  super(config)
141
123
  end
142
124
 
143
-
144
125
  protected
145
126
 
146
-
147
127
  def appropriate_connection(method_name, args, &block)
148
128
  if needed_by_all?(method_name, args)
149
129
 
@@ -164,29 +144,28 @@ module ActiveRecord
164
144
  end
165
145
  end
166
146
 
167
-
168
147
  def should_stick?(method_name, args)
169
148
  sql = coerce_query_to_sql_string(args.first)
170
149
  return false if sql_skip_stickiness_matchers.any?{|m| sql =~ m }
150
+
171
151
  super
172
152
  end
173
153
 
174
-
175
154
  def needed_by_all?(method_name, args)
176
155
  sql = coerce_query_to_sql_string(args.first)
177
156
  return true if sql_all_matchers.any?{|m| sql =~ m }
157
+
178
158
  false
179
159
  end
180
160
 
181
-
182
161
  def needs_master?(method_name, args)
183
162
  sql = coerce_query_to_sql_string(args.first)
184
163
  return true if sql_master_matchers.any?{|m| sql =~ m }
185
164
  return false if sql_slave_matchers.any?{|m| sql =~ m }
165
+
186
166
  true
187
167
  end
188
168
 
189
-
190
169
  def coerce_query_to_sql_string(sql_or_arel)
191
170
  if sql_or_arel.respond_to?(:to_sql)
192
171
  sql_or_arel.to_sql
@@ -195,18 +174,116 @@ module ActiveRecord
195
174
  end
196
175
  end
197
176
 
198
-
199
177
  def connection_for(config)
200
178
  config = Makara::ConfigParser.merge_and_resolve_default_url_config(config)
201
179
  active_record_connection_for(config)
202
180
  end
203
181
 
204
-
205
182
  def active_record_connection_for(config)
206
183
  raise NotImplementedError
207
184
  end
208
185
 
186
+ class ActiveRecordPoolControl
187
+ attr_reader :owner
188
+ alias :in_use? :owner
189
+
190
+ def initialize(proxy)
191
+ @proxy = proxy
192
+ @owner = nil
193
+ @pool = nil
194
+ @schema_cache = ActiveRecord::ConnectionAdapters::SchemaCache.new @proxy
195
+ @idle_since = Concurrent.monotonic_time
196
+ @adapter = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(@proxy)
197
+ end
198
+
199
+ def close(*args)
200
+ @pool.checkin @proxy
201
+ end
202
+
203
+ # this method must only be called while holding connection pool's mutex
204
+ def lease(*args)
205
+ if in_use?
206
+ msg = +"Cannot lease connection, "
207
+ if @owner == Thread.current
208
+ msg << "it is already leased by the current thread."
209
+ else
210
+ msg << "it is already in use by a different thread: #{@owner}. " \
211
+ "Current thread: #{Thread.current}."
212
+ end
213
+ raise ActiveRecordError, msg
214
+ end
215
+ @owner = Thread.current
216
+ end
217
+
218
+ # this method must only be called while holding connection pool's mutex
219
+ def expire(*args)
220
+ if in_use?
221
+ if @owner != Thread.current
222
+ raise ActiveRecordError, "Cannot expire connection, " \
223
+ "it is owned by a different thread: #{@owner}. " \
224
+ "Current thread: #{Thread.current}."
225
+ end
226
+
227
+ @idle_since = Concurrent.monotonic_time
228
+ @owner = nil
229
+ else
230
+ raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
231
+ end
232
+ end
233
+
234
+ # Seconds since this connection was returned to the pool
235
+ def seconds_idle(*args)
236
+ return 0 if in_use?
237
+
238
+ Concurrent.monotonic_time - @idle_since
239
+ end
240
+
241
+ # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
242
+ def steal!(*args)
243
+ if in_use?
244
+ if @owner != Thread.current
245
+ @pool.send :remove_connection_from_thread_cache, @proxy, @owner
246
+ @owner = Thread.current
247
+ end
248
+ else
249
+ raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
250
+ end
251
+ end
252
+
253
+ def schema_cache(*args)
254
+ if @pool.respond_to?(:get_schema_cache) # AR6
255
+ @pool.get_schema_cache(@proxy)
256
+ else
257
+ @schema_cache
258
+ end
259
+ end
260
+
261
+ def schema_cache=(*args)
262
+ cache = args[0]
263
+ cache.connection = @proxy
264
+ if @pool.respond_to?(:set_schema_cache) # AR6
265
+ @pool.set_schema_cache(cache)
266
+ else
267
+ @schema_cache = cache
268
+ end
269
+ end
270
+
271
+ def lock(*args)
272
+ @adapter.lock
273
+ end
274
+
275
+ def pool=(*args)
276
+ @pool = args[0]
277
+ end
209
278
 
279
+ def pool(*args)
280
+ @pool
281
+ end
282
+
283
+ def ==(*args)
284
+ @proxy.object_id == args[0].object_id
285
+ end
286
+ end
210
287
  end
211
288
  end
212
289
  end