trilogy_aurora 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30793dcf14f37f6c04d69ff701c85b709279ce88fa81301b33e749f05c5b05ba
4
- data.tar.gz: b243bfe9899bb88ecc1b0e91472567d870161b0af6074b1db0e70584d4ccdd27
3
+ metadata.gz: 35db8108014a6e21a985a21fbce35d8ecea1e50a610e0b90d0311494f7e766ac
4
+ data.tar.gz: c798f7504199f039eb435c9055ab4fbda470cb87f72afe07c0a8a4b14562a0dd
5
5
  SHA512:
6
- metadata.gz: 458345a870ba34e36d5fecc6bbaa5cb432925bf04e5e09d4bba81f62d47343cdf8e717d0c254910e2d94ae3c8a0180c57272c1c347c9f368a75befda00fb6c74
7
- data.tar.gz: 90d3e86cbe6d04db68d2ae23547f303a2dc7d8883b34bc8af664f9a3f1f6ddd05e3c24d84c783fc146d45356f0a52bcae9230849c37c684a03f445beb5cf0110
6
+ metadata.gz: 1d8844c208b6cd107473b7da1b3cf35e7b87f614249e64ace04f538850731b272896e2ff727b2c1981d3f4e4c53e0080d6b19a958c5c02459157f5efb6802fe6
7
+ data.tar.gz: b0e9e837a24f5f71153dc774cbcbcd5a8a83d310f02acecd84da0779d64b36a1c5c1280f4c8577cc84493bd11d4fed2d00fad6656cd5eceaa7d3b9943bab961a
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
- --format documentation
1
+ --format progress
2
2
  --color
3
3
  --require spec_helper
data/README.md CHANGED
@@ -14,11 +14,13 @@ Essentially, the [mysql2-aurora](https://github.com/alfa-jpn/mysql2-aurora) gem
14
14
 
15
15
  Install the gem and add to the application's Gemfile by executing:
16
16
 
17
- $ bundle add trilogy_aurora
17
+ ```shell
18
+ bundle add trilogy_aurora
19
+ ```
18
20
 
19
21
  ## Usage
20
22
 
21
- In addition to existing initialization options for `Trilogy`, you can now also use the `aurora_max_retry` and `aurora_disconnect_on_readonly` options.
23
+ In addition to existing initialization options for `Trilogy`, you can now also use the `aurora_disconnect_on_readonly` and `aurora_max_retry` options.
22
24
 
23
25
  ```ruby
24
26
  Trilogy.new(
@@ -32,14 +34,12 @@ Trilogy.new(
32
34
 
33
35
  with Rails >= 7.1, in `database.yml`
34
36
 
35
- ```yml
37
+ ```yaml
36
38
  development:
37
- adapter: trilogy
38
- host: localhost
39
- username: root
40
- password: change_me
41
- aurora_max_retry: 5
39
+ adapter: trilogy
40
+ # ...
42
41
  aurora_disconnect_on_readonly: true
42
+ aurora_max_retry: 5
43
43
  ```
44
44
 
45
45
  From the README of [mysql2-aurora](https://github.com/alfa-jpn/mysql2-aurora):
@@ -77,10 +77,14 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/a-lavi
77
77
 
78
78
  ## Testing
79
79
 
80
+ Run Rubocop + RSpec
81
+
80
82
  ```shell
81
- # Image build
82
- bin/docker-build
83
+ bundle exec rake
84
+ ```
83
85
 
84
- # Run tests
85
- bin/docker-test
86
+ Clean up
87
+
88
+ ```shell
89
+ docker compose down
86
90
  ```
data/Rakefile CHANGED
@@ -3,10 +3,22 @@
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
5
 
6
- RSpec::Core::RakeTask.new(:spec)
6
+ RSpec::Core::RakeTask.new(spec: :mysql)
7
7
 
8
8
  require 'rubocop/rake_task'
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
12
- task default: %i[spec rubocop]
12
+ task default: %i[rubocop spec]
13
+
14
+ desc 'Ensure MySQL is available'
15
+ task :mysql do
16
+ sh 'docker compose up --detach mysql &> /dev/null'
17
+ catch :ready do
18
+ loop do
19
+ sh 'docker compose run --rm mysql mysql -h mysql -e "SELECT 1" &> /dev/null' do |ok|
20
+ ok ? throw(:ready) : sleep(1)
21
+ end
22
+ end
23
+ end
24
+ end
data/compose.yml ADDED
@@ -0,0 +1,7 @@
1
+ services:
2
+ mysql:
3
+ image: mysql:8.0
4
+ environment:
5
+ MYSQL_ALLOW_EMPTY_PASSWORD: true
6
+ ports:
7
+ - 3306
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'trilogy'
4
+
5
+ module TrilogyAurora
6
+ # Trilogy Aurora wrapper
7
+ class Client
8
+ attr_reader :trilogy
9
+
10
+ def initialize(options = {})
11
+ @trilogy = TrilogyAurora::Trilogy.new(options)
12
+ end
13
+
14
+ # Disconnect and re-initialize TrilogyAurora::Trilogy
15
+ def reconnect!
16
+ disconnect!
17
+
18
+ @trilogy = TrilogyAurora::Trilogy.new(@trilogy.connection_options.dup)
19
+ end
20
+
21
+ # Close TrilogyAurora::Trilogy connection
22
+ def disconnect!
23
+ trilogy&.close
24
+ rescue StandardError
25
+ nil
26
+ end
27
+
28
+ # Execute a TrilogyAurora::Trilogy query, disconnecting or reconnecting after read-only errors
29
+ # based on initialization options.
30
+ def query(...) # rubocop:disable Metrics/AbcSize
31
+ try_count = 0
32
+
33
+ begin
34
+ trilogy.query(...)
35
+ rescue TrilogyAurora::Trilogy::Error => e
36
+ raise unless e.message&.include?('--read-only')
37
+
38
+ try_count += 1
39
+
40
+ if trilogy.connection_options[:aurora_disconnect_on_readonly]
41
+ warn <<~WARNING
42
+ [trilogy_aurora] Database is readonly, Aurora failover event likely occured. \
43
+ Closing database connection
44
+ WARNING
45
+ disconnect!
46
+ elsif try_count <= trilogy.connection_options[:aurora_max_retry]
47
+ retry_interval_seconds = [1.5 * (try_count - 1), 10].min
48
+ warn <<~WARNING
49
+ [trilogy_aurora] Database is readonly. \
50
+ Retry after #{retry_interval_seconds} seconds
51
+ WARNING
52
+ sleep retry_interval_seconds
53
+ reconnect!
54
+ retry
55
+ end
56
+
57
+ raise
58
+ end
59
+ end
60
+
61
+ # Delegate instance method calls to TrilogyAurora::Trilogy instance.
62
+ def method_missing(...)
63
+ trilogy.public_send(...)
64
+ end
65
+
66
+ # Delegate `respond_to?` to TrilogyAurora::Trilogy instance.
67
+ def respond_to_missing?(...)
68
+ trilogy.respond_to?(...)
69
+ end
70
+
71
+ # Delegate class method calls to TrilogyAurora::Trilogy.
72
+ def self.method_missing(...)
73
+ TrilogyAurora::Trilogy.public_send(...)
74
+ end
75
+
76
+ # Delegate `respond_to?` to TrilogyAurora::Trilogy.
77
+ def self.respond_to_missing?(...)
78
+ TrilogyAurora::Trilogy.respond_to?(...)
79
+ end
80
+
81
+ # Delegate const reference to TrilogyAurora::Trilogy.
82
+ def self.const_missing(...)
83
+ TrilogyAurora::Trilogy.const_get(...)
84
+ end
85
+
86
+ # Delegate `const_defined?` to TrilogyAurora::Trilogy.
87
+ def self.const_defined?(...)
88
+ TrilogyAurora::Trilogy.const_defined?(...)
89
+ end
90
+ end
91
+
92
+ Trilogy = Object.send(:remove_const, :Trilogy)
93
+ end
94
+
95
+ Trilogy = TrilogyAurora::Client
@@ -2,5 +2,5 @@
2
2
 
3
3
  module TrilogyAurora
4
4
  # The version of this gem.
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
6
6
  end
@@ -1,111 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'trilogy_aurora/version'
4
- require 'trilogy'
5
-
6
- # This module contains Trilogy, a wrapper around ::Trilogy that handles read-only errors from Aurora.
7
- #
8
- # It also contains the original ::Trilogy class as ORIGINAL_TRILOGY_CLASS.
9
- module TrilogyAurora
10
- # A wrapper around ::Trilogy that handles read-only errors from Aurora.
11
- class Trilogy
12
- # The ::Trilogy instance.
13
- attr_reader :trilogy
14
-
15
- # Pass in any options that ::Trilogy accepts.
16
- #
17
- # Additionally, you can pass in the `aurora_max_retry` and `aurora_disconnect_on_readonly` options:
18
- #
19
- # - `aurora_max_retry` is the number of times to retry a query when it fails due to a read-only error.
20
- # The default is 5.
21
- #
22
- # - `aurora_disconnect_on_readonly` is a boolean that determines whether or not to disconnect from the database
23
- # after a read-only error is encountered.
24
- # The default is false.
25
- def initialize(opts)
26
- @opts = opts&.transform_keys(&:to_sym)
27
- @max_retry = @opts.delete(:aurora_max_retry) || 5
28
- @disconnect_only = @opts.delete(:aurora_disconnect_on_readonly) || false
29
- reconnect!
30
- end
31
-
32
- # Execute a ::Trilogy query, disconnecting or reconnecting after read-only errors
33
- # based on initialization options.
34
- def query(...)
35
- try_count = 0
36
-
37
- begin
38
- trilogy.query(...)
39
- rescue TrilogyAurora::ORIGINAL_TRILOGY_CLASS::Error => e
40
- raise e unless e.message&.include?('--read-only')
41
-
42
- try_count += 1
43
-
44
- if @disconnect_only
45
- warn(
46
- '[trilogy_aurora] Database is readonly, Aurora failover event likely occured, closing database connection'
47
- )
48
- disconnect!
49
- elsif try_count <= @max_retry
50
- retry_interval_seconds = [1.5 * (try_count - 1), 10].min
51
-
52
- warn "[trilogy_aurora] Database is readonly. Retry after #{retry_interval_seconds}seconds"
53
- sleep retry_interval_seconds
54
- reconnect!
55
- retry
56
- end
57
-
58
- raise e
59
- end
60
- end
61
-
62
- # Disconnect and re-initialize ::Trilogy
63
- def reconnect!
64
- disconnect!
65
-
66
- @trilogy = TrilogyAurora::ORIGINAL_TRILOGY_CLASS.new(@opts)
67
- end
68
-
69
- # Close ::Trilogy connection
70
- def disconnect!
71
- @trilogy&.close
72
- rescue StandardError
73
- nil
74
- end
75
-
76
- # Delegate instance method calls to ::Trilogy instance.
77
- def method_missing(name, ...)
78
- trilogy.public_send(name, ...)
79
- end
80
-
81
- # Delegate `respond_to?` to ::Trilogy instance.
82
- def respond_to_missing?(name, ...)
83
- trilogy.respond_to?(name, ...)
84
- end
85
-
86
- # Delegate class method calls to ::Trilogy.
87
- def self.method_missing(name, ...)
88
- TrilogyAurora::ORIGINAL_TRILOGY_CLASS.public_send(name, ...)
89
- end
90
-
91
- # Delegate `respond_to?` to ::Trilogy.
92
- def self.respond_to_missing?(name, ...)
93
- TrilogyAurora::ORIGINAL_TRILOGY_CLASS.respond_to?(name, ...)
94
- end
95
-
96
- # Delegate const reference to ::Trilogy.
97
- def self.const_missing(name)
98
- TrilogyAurora::ORIGINAL_TRILOGY_CLASS.const_get(name)
99
- end
100
-
101
- # Delegate `const_defined?` to ::Trilogy.
102
- def self.const_defined?(name, ...)
103
- TrilogyAurora::ORIGINAL_TRILOGY_CLASS.const_defined?(name, ...)
104
- end
105
- end
106
-
107
- # The original ::Trilogy class.
108
- ORIGINAL_TRILOGY_CLASS = ::Trilogy
109
- # Swap out the original ::Trilogy class with our wrapper (Trilogy).
110
- ::Trilogy = TrilogyAurora::Trilogy
111
- end
3
+ require 'trilogy_aurora/version'
4
+ require 'trilogy_aurora/client'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trilogy_aurora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aidan Lavis
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-05-05 00:00:00.000000000 Z
10
+ date: 2025-05-07 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bigdecimal
@@ -15,50 +15,43 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 3.0.2
18
+ version: '0'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 3.0.2
25
+ version: '0'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: trilogy
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: '2.3'
33
- - - "<"
34
- - !ruby/object:Gem::Version
35
- version: '3.0'
32
+ version: '2.5'
36
33
  type: :runtime
37
34
  prerelease: false
38
35
  version_requirements: !ruby/object:Gem::Requirement
39
36
  requirements:
40
37
  - - ">="
41
38
  - !ruby/object:Gem::Version
42
- version: '2.3'
43
- - - "<"
44
- - !ruby/object:Gem::Version
45
- version: '3.0'
39
+ version: '2.5'
46
40
  email:
47
41
  - aidanlavis@gmail.com
48
42
  executables: []
49
43
  extensions: []
50
44
  extra_rdoc_files: []
51
45
  files:
52
- - ".dockerignore"
53
46
  - ".rdoc_options"
54
47
  - ".rspec"
55
48
  - ".rubocop.yml"
56
- - Dockerfile
57
49
  - LICENSE.txt
58
50
  - README.md
59
51
  - Rakefile
60
- - docker-compose.yml
52
+ - compose.yml
61
53
  - lib/trilogy_aurora.rb
54
+ - lib/trilogy_aurora/client.rb
62
55
  - lib/trilogy_aurora/version.rb
63
56
  homepage: https://github.com/a-lavis/trilogy_aurora
64
57
  licenses:
data/.dockerignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
data/Dockerfile DELETED
@@ -1,20 +0,0 @@
1
- ARG RUBY_VERSION=3.4
2
-
3
- FROM ruby:${RUBY_VERSION}-alpine
4
-
5
- ARG TRILOGY_VERSION
6
-
7
- ENV TRILOGY_VERSION=$TRILOGY_VERSION
8
-
9
- # Create application directory.
10
- RUN mkdir /app
11
- WORKDIR /app
12
-
13
- # Install packages
14
- RUN apk upgrade && apk add --update build-base git linux-headers libxml2-dev libxslt-dev mariadb-dev ruby-dev tzdata yaml-dev zlib-dev
15
-
16
- # Deploy application
17
- ADD . /app
18
-
19
- # Install gems
20
- RUN sh /app/bin/setup
data/docker-compose.yml DELETED
@@ -1,23 +0,0 @@
1
- services:
2
- app:
3
- build:
4
- context: .
5
- environment:
6
- TEST_DB_HOST: 'mysql'
7
- TEST_DB_USER: 'root'
8
- TEST_DB_PASS: ''
9
- volumes:
10
- - .:/app
11
- depends_on:
12
- mysql:
13
- condition: service_healthy
14
- mysql:
15
- image: mysql:8.0
16
- environment:
17
- MYSQL_ROOT_PASSWORD: ''
18
- MYSQL_ALLOW_EMPTY_PASSWORD: 1
19
- healthcheck:
20
- test: ["CMD-SHELL", "mysqladmin ping -h mysql"]
21
- interval: 10s
22
- timeout: 5s
23
- retries: 3