activerecord-dynamic_timeout 0.0.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0f13bd79fe5a35f5979b91ec7f702ad0fe0d95ff743a2a91dc3a81a9c8e78fa7
4
+ data.tar.gz: d1c6f748961cb9c812215f2ee710fc88f99d7230a67986710152ecda8bb8f811
5
+ SHA512:
6
+ metadata.gz: 57286088e5d8fdb64d24e24e949dce507ff8afb10d295182c42926df5eef6fa2c4d1abc5e3a55812596b32d56969f8b9ad2b0eadbd6c7fc1443b973a6109c32b
7
+ data.tar.gz: 24e3f13a1c85ab0efd0d68222fe9b8e2fd4e1a84816c01fe28b00736e386c33a6d70ed94ae6261ecb57400a644d24a2e9415c89c55e4d851945ccfe94c417e6b
data/Appraisals ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "appraisal/matrix"
4
+
5
+ appraisal_matrix(activerecord: "6.1") do |activerecord:|
6
+ if activerecord < "7.2"
7
+ gem "sqlite3", "~> 1.4"
8
+ end
9
+ end
10
+ # appraisal_matrix(activerecord: "6.1", mysql2: { versions: ["~> 0.5"], step: :major })
11
+ # appraisal_matrix(activerecord: "6.1", pg: { versions: ["~> 1.5"], step: :major })
12
+ #
13
+ # appraisal_matrix(activerecord: [">= 6.1", "< 7.2"], sqlite3: { versions: ["~> 1.4"], step: :major })
14
+ # appraisal_matrix(activerecord: "7.2", sqlite3: { versions: [">= 1.4"], step: :major })
15
+ # appraisal_matrix(activerecord: "7.1", trilogy: { versions: [">= 2.8"], step: :major })
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "appraisal"
6
+ gem "appraisal-matrix"
7
+ gem "debug"
8
+ gem "mysql2"
9
+ gem "pg"
10
+ gem "rspec"
11
+ gem "sqlite3"
12
+ gem "trilogy"
data/Gemfile.lock ADDED
@@ -0,0 +1,96 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ activerecord-dynamic_timeout (0.0.1.rc1)
5
+ activerecord (>= 6.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (7.2.1)
11
+ activesupport (= 7.2.1)
12
+ activerecord (7.2.1)
13
+ activemodel (= 7.2.1)
14
+ activesupport (= 7.2.1)
15
+ timeout (>= 0.4.0)
16
+ activesupport (7.2.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
+ logger (>= 1.4.2)
24
+ minitest (>= 5.1)
25
+ securerandom (>= 0.3)
26
+ tzinfo (~> 2.0, >= 2.0.5)
27
+ appraisal (2.5.0)
28
+ bundler
29
+ rake
30
+ thor (>= 0.14.0)
31
+ appraisal-matrix (0.3.0)
32
+ appraisal (~> 2.2)
33
+ base64 (0.2.0)
34
+ bigdecimal (3.1.8)
35
+ concurrent-ruby (1.3.4)
36
+ connection_pool (2.4.1)
37
+ debug (1.9.2)
38
+ irb (~> 1.10)
39
+ reline (>= 0.3.8)
40
+ diff-lcs (1.5.1)
41
+ drb (2.2.1)
42
+ i18n (1.14.6)
43
+ concurrent-ruby (~> 1.0)
44
+ io-console (0.7.2)
45
+ irb (1.14.0)
46
+ rdoc (>= 4.0.0)
47
+ reline (>= 0.4.2)
48
+ logger (1.6.1)
49
+ minitest (5.25.1)
50
+ mysql2 (0.5.6)
51
+ pg (1.5.8)
52
+ psych (5.1.2)
53
+ stringio
54
+ rake (13.2.1)
55
+ rdoc (6.7.0)
56
+ psych (>= 4.0.0)
57
+ reline (0.5.10)
58
+ io-console (~> 0.5)
59
+ rspec (3.13.0)
60
+ rspec-core (~> 3.13.0)
61
+ rspec-expectations (~> 3.13.0)
62
+ rspec-mocks (~> 3.13.0)
63
+ rspec-core (3.13.1)
64
+ rspec-support (~> 3.13.0)
65
+ rspec-expectations (3.13.3)
66
+ diff-lcs (>= 1.2.0, < 2.0)
67
+ rspec-support (~> 3.13.0)
68
+ rspec-mocks (3.13.1)
69
+ diff-lcs (>= 1.2.0, < 2.0)
70
+ rspec-support (~> 3.13.0)
71
+ rspec-support (3.13.1)
72
+ securerandom (0.3.1)
73
+ sqlite3 (2.0.4-arm64-darwin)
74
+ stringio (3.1.1)
75
+ thor (1.3.2)
76
+ timeout (0.4.1)
77
+ trilogy (2.8.1)
78
+ tzinfo (2.0.6)
79
+ concurrent-ruby (~> 1.0)
80
+
81
+ PLATFORMS
82
+ arm64-darwin
83
+
84
+ DEPENDENCIES
85
+ activerecord-dynamic_timeout!
86
+ appraisal
87
+ appraisal-matrix
88
+ debug
89
+ mysql2
90
+ pg
91
+ rspec
92
+ sqlite3
93
+ trilogy
94
+
95
+ BUNDLED WITH
96
+ 2.5.5
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT LICENSE
2
+
3
+ Copyright (c) 2024 Tristan Starck <tstarck@invoca.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # activerecord-dynamic_timeout
2
+ Dynamic Timeouts within ActiveRecord
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ Bundler::GemHelper.install_tasks
2
+
3
+ task default: :rspec
4
+
5
+ desc "run rspec unit tests"
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:rspec)
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ $:.unshift File.expand_path("../lib", __FILE__)
4
+ require "active_record/dynamic_timeout/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "activerecord-dynamic_timeout"
8
+ s.version = ActiveRecord::DynamicTimeout::VERSION
9
+ s.authors = ["Tristan Starck"]
10
+ s.email = ["tstarck@invoca.com", "Invoca Development"]
11
+ s.homepage = "https://github.com/Invoca/activerecord-dynamic_timeout"
12
+ s.licenses = ["MIT"]
13
+ s.summary = "ActiveRecord extension for dynamically setting connection timeouts"
14
+ s.description = s.summary
15
+ s.metadata = {
16
+ "allowed_push_host" => "https://rubygems.org",
17
+ "source_code_uri" => s.homepage,
18
+ }
19
+
20
+ s.files = Dir.glob("{bin/*,lib/**/*,[A-Z]*}")
21
+ s.platform = Gem::Platform::RUBY
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_dependency "activerecord", ">= 6.1"
25
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/concern"
5
+ require_relative "../../dynamic_timeout"
6
+
7
+ module ActiveRecord::DynamicTimeout
8
+ module AbstractAdapterExtension
9
+ extend ActiveSupport::Concern
10
+
11
+ attr_accessor :active_record_dynamic_timeout
12
+
13
+ included do
14
+ set_callback :checkin, :before, :reset_dynamic_timeout_for_checkin, prepend: true
15
+ end
16
+
17
+ def supports_dynamic_timeouts?
18
+ false
19
+ end
20
+
21
+ def set_dynamic_timeout(raw_connection, timeout)
22
+ return unless supports_dynamic_timeouts?
23
+ return if active_record_dynamic_timeout == timeout
24
+ if timeout.nil?
25
+ reset_dynamic_timeout(raw_connection)
26
+ else
27
+ set_connection_timeout(raw_connection, timeout)
28
+ self.active_record_dynamic_timeout = timeout
29
+ end
30
+ end
31
+
32
+ def reset_dynamic_timeout(raw_connection)
33
+ return unless supports_dynamic_timeouts?
34
+ return if active_record_dynamic_timeout.nil?
35
+ reset_connection_timeout(raw_connection)
36
+ self.active_record_dynamic_timeout = nil
37
+ end
38
+ end
39
+
40
+ module TimeoutAdapterExtension
41
+ def with_raw_connection(*args, **kwargs, &block)
42
+ super do |raw_connection|
43
+ set_dynamic_timeout(raw_connection, ActiveRecord::Base.current_timeout)
44
+ yield raw_connection
45
+ ensure
46
+ if timeout_set_client_side?
47
+ reset_dynamic_timeout(raw_connection)
48
+ end
49
+ end
50
+ end
51
+
52
+ # This ensures new connections from reconnects have the correct timeout.
53
+ def configure_connection
54
+ super
55
+ if active_record_dynamic_timeout && !timeout_set_client_side?
56
+ set_connection_timeout(@raw_connection, active_record_dynamic_timeout)
57
+ end
58
+ end
59
+
60
+ def reset_dynamic_timeout_for_checkin
61
+ if active_record_dynamic_timeout
62
+ with_raw_connection do |conn|
63
+ reset_dynamic_timeout(conn)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ module TimeoutAdapterExtension_Rails_7_0
70
+ def log(*args, **kwargs, &block)
71
+ super do
72
+ set_dynamic_timeout(@connection, ActiveRecord::Base.current_timeout)
73
+ yield
74
+ ensure
75
+ if timeout_set_client_side?
76
+ reset_dynamic_timeout(@connection)
77
+ end
78
+ end
79
+ end
80
+
81
+ # This ensures new connections from reconnects have the correct timeout.
82
+ def configure_connection
83
+ super
84
+ if active_record_dynamic_timeout && !timeout_set_client_side?
85
+ set_connection_timeout(@connection, active_record_dynamic_timeout)
86
+ end
87
+ end
88
+
89
+ def reset_dynamic_timeout_for_checkin
90
+ if @connection
91
+ reset_dynamic_timeout(@connection)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/concern"
5
+
6
+ module ActiveRecord::DynamicTimeout
7
+ module BaseExtension
8
+ extend ActiveSupport::Concern
9
+
10
+ module ClassMethods
11
+ def with_timeout(timeout)
12
+ (timeout.is_a?(Integer) || timeout.nil?) or raise ArgumentError, "timeout must be an Integer or NilClass, got: `#{timeout.inspect}`"
13
+ timeout_stack << timeout
14
+ yield
15
+ ensure
16
+ timeout_stack.pop
17
+ end
18
+
19
+ def current_timeout
20
+ timeout_stack.last
21
+ end
22
+
23
+ # @param [Class] scope_class
24
+ def timeout_isolation_scope=(scope_class)
25
+ (scope_class == Thread || scope_class == Fiber) or raise ArgumentError, "scope must be `Thread` or `Fiber`, got: `#{scope_class.inspect}`"
26
+ raise ArgumentError, "timeout_isolation_scope can only be set once" if @timeout_isolation_scope
27
+ @timeout_isolation_scope = scope_class
28
+ end
29
+
30
+ private
31
+
32
+ def timeout_stack
33
+ if (stack = timeout_isolation_state[:active_record_dynamic_timeout_stack])
34
+ stack
35
+ else
36
+ stack = []
37
+ timeout_isolation_state[:active_record_dynamic_timeout_stack] = stack
38
+ stack
39
+ end
40
+ end
41
+
42
+ def timeout_isolation_state
43
+ if timeout_isolation_scope == Thread
44
+ Thread.current.thread_variable_get(:ar_dynamic_timeout_execution_state) ||
45
+ Thread.current.thread_variable_set(:ar_dynamic_timeout_execution_state, {})
46
+ else
47
+ # Thread.current[] is Fiber local
48
+ Thread.current[:ar_dynamic_timeout_execution_state] ||= {}
49
+ end
50
+ end
51
+
52
+ def timeout_isolation_scope
53
+ @timeout_isolation_scope
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ module ActiveRecord::DynamicTimeout
2
+ module Mysql2AdapterExtension
3
+ def set_connection_timeout(raw_connection, timeout)
4
+ set_timeouts_on_connection(raw_connection, read_timeout: timeout, write_timeout: timeout)
5
+ end
6
+
7
+ def reset_connection_timeout(raw_connection)
8
+ read_timeout = Integer(@config[:read_timeout]) unless @config[:read_timeout].nil?
9
+ write_timeout = Integer(@config[:write_timeout]) unless @config[:write_timeout].nil?
10
+ set_timeouts_on_connection(raw_connection, read_timeout:, write_timeout:)
11
+ end
12
+
13
+ def timeout_set_client_side?
14
+ true
15
+ end
16
+
17
+ def supports_dynamic_timeouts?
18
+ true
19
+ end
20
+
21
+ private
22
+
23
+ def set_timeouts_on_connection(raw_connection, read_timeout:, write_timeout:)
24
+ raw_connection.instance_variable_set(:@read_timeout, read_timeout)
25
+ raw_connection.instance_variable_set(:@write_timeout, write_timeout)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ module ActiveRecord::DynamicTimeout
2
+ module PostgresAdapterExtension
3
+ def set_connection_timeout(raw_connection, timeout)
4
+ if timeout.nil? || timeout == ":default" || timeout == :default
5
+ raw_connection.query("SET SESSION statement_timeout TO DEFAULT")
6
+ else
7
+ raw_connection.query("SET SESSION statement_timeout TO #{quote(timeout)}")
8
+ end
9
+ end
10
+
11
+ def reset_connection_timeout(raw_connection)
12
+ set_connection_timeout(raw_connection, default_statement_timeout)
13
+ end
14
+
15
+ def timeout_set_client_side?
16
+ false
17
+ end
18
+
19
+ def supports_dynamic_timeouts?
20
+ true
21
+ end
22
+
23
+ private
24
+
25
+ def default_statement_timeout
26
+ unless defined?(@default_statement_timeout)
27
+ @default_statement_timeout = @config.fetch(:variables, {}).stringify_keys["statement_timeout"]
28
+ end
29
+ @default_statement_timeout
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord::DynamicTimeout
4
+ module SqliteAdapterExtension
5
+ def set_connection_timeout(raw_connection, timeout)
6
+ if timeout
7
+ raw_connection.busy_timeout(timeout)
8
+ else
9
+ raw_connection.busy_timeout(0)
10
+ end
11
+ end
12
+
13
+ def reset_connection_timeout(raw_connection)
14
+ timeout = @config[:timeout]
15
+ set_connection_timeout(raw_connection, self.class.type_cast_config_to_integer(timeout))
16
+ end
17
+
18
+ def timeout_set_client_side?
19
+ false
20
+ end
21
+
22
+ def supports_dynamic_timeouts?
23
+ true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ module ActiveRecord::DynamicTimeout
2
+ module TrilogyAdapterExtension
3
+ def set_connection_timeout(raw_connection, timeout)
4
+ set_timeouts_on_connection(raw_connection, read_timeout: timeout, write_timeout: timeout)
5
+ end
6
+
7
+ def reset_connection_timeout(raw_connection)
8
+ read_timeout = @config[:read_timeout]
9
+ write_timeout = @config[:write_timeout]
10
+ set_timeouts_on_connection(raw_connection, read_timeout:, write_timeout:)
11
+ end
12
+
13
+ def timeout_set_client_side?
14
+ true
15
+ end
16
+
17
+ def supports_dynamic_timeouts?
18
+ true
19
+ end
20
+
21
+ private
22
+
23
+ def set_timeouts_on_connection(raw_connection, read_timeout:, write_timeout:)
24
+ raw_connection.read_timeout = read_timeout
25
+ raw_connection.write_timeout = write_timeout
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "active_support"
5
+ require_relative "../dynamic_timeout"
6
+ require_relative "extensions/base_extension"
7
+ require_relative "extensions/abstract_adapter_extension"
8
+ require_relative "extensions/mysql2_adapter_extension"
9
+ require_relative "extensions/trilogy_adapter_extension"
10
+ require_relative "extensions/sqlite_adapter_extension"
11
+ require_relative "extensions/postgres_adapter_extension"
12
+
13
+ module ActiveRecord::DynamicTimeout
14
+ module Initializer
15
+ class << self
16
+ def initialize!
17
+ ActiveRecord::Base.include(ActiveRecord::DynamicTimeout::BaseExtension)
18
+ ActiveRecord::Base.connection.class.include(ActiveRecord::DynamicTimeout::AbstractAdapterExtension)
19
+
20
+ if ActiveRecord.gem_version < "7.1"
21
+ ActiveRecord::Base.connection.class.prepend(ActiveRecord::DynamicTimeout::TimeoutAdapterExtension_Rails_7_0)
22
+ else
23
+ ActiveRecord::Base.connection.class.prepend(ActiveRecord::DynamicTimeout::TimeoutAdapterExtension)
24
+ end
25
+ register_adapter_extension(ActiveRecord::Base.connection.class)
26
+ end
27
+
28
+ def register_adapter_extension(adapter_class)
29
+ extension = case adapter_class.name
30
+ when "ActiveRecord::ConnectionAdapters::Mysql2Adapter"
31
+ ActiveRecord::DynamicTimeout::Mysql2AdapterExtension
32
+ when "ActiveRecord::ConnectionAdapters::TrilogyAdapter"
33
+ ActiveRecord::DynamicTimeout::TrilogyAdapterExtension
34
+ when "ActiveRecord::ConnectionAdapters::SQLite3Adapter"
35
+ ActiveRecord::DynamicTimeout::SqliteAdapterExtension
36
+ when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
37
+ ActiveRecord::DynamicTimeout::PostgresAdapterExtension
38
+ end
39
+ adapter_class.prepend(extension) if extension
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "initializer"
4
+
5
+ module ActiveRecord::DynamicTimeout
6
+ class Railtie < Rails::Railtie
7
+ initializer "active_record-dynamic_timeout.initialize", after: "active_record.initialize_database" do |app|
8
+ ActiveSupport.on_load :active_record do
9
+ ActiveRecord::DynamicTimeout::Initializer.initialize!
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveRecord
2
+ module DynamicTimeout
3
+ VERSION = '0.0.1.rc1'
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "active_support"
5
+
6
+ module ActiveRecord
7
+ module DynamicTimeout
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-dynamic_timeout
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.rc1
5
+ platform: ruby
6
+ authors:
7
+ - Tristan Starck
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-09-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ description: ActiveRecord extension for dynamically setting connection timeouts
28
+ email:
29
+ - tstarck@invoca.com
30
+ - Invoca Development
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - Appraisals
36
+ - Gemfile
37
+ - Gemfile.lock
38
+ - LICENSE.md
39
+ - README.md
40
+ - Rakefile
41
+ - activerecord-dynamic_timeout.gemspec
42
+ - lib/active_record/dynamic_timeout.rb
43
+ - lib/active_record/dynamic_timeout/extensions/abstract_adapter_extension.rb
44
+ - lib/active_record/dynamic_timeout/extensions/base_extension.rb
45
+ - lib/active_record/dynamic_timeout/extensions/mysql2_adapter_extension.rb
46
+ - lib/active_record/dynamic_timeout/extensions/postgres_adapter_extension.rb
47
+ - lib/active_record/dynamic_timeout/extensions/sqlite_adapter_extension.rb
48
+ - lib/active_record/dynamic_timeout/extensions/trilogy_adapter_extension.rb
49
+ - lib/active_record/dynamic_timeout/initializer.rb
50
+ - lib/active_record/dynamic_timeout/railtie.rb
51
+ - lib/active_record/dynamic_timeout/version.rb
52
+ homepage: https://github.com/Invoca/activerecord-dynamic_timeout
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ allowed_push_host: https://rubygems.org
57
+ source_code_uri: https://github.com/Invoca/activerecord-dynamic_timeout
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">"
70
+ - !ruby/object:Gem::Version
71
+ version: 1.3.1
72
+ requirements: []
73
+ rubygems_version: 3.3.27
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: ActiveRecord extension for dynamically setting connection timeouts
77
+ test_files: []