safe_request_timeout 1.0.2 → 1.0.3

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: 1fb790302089e758479b7c2ec238ba5ad66d5f2cd01388c4be8679b3c15c7057
4
- data.tar.gz: 9358570335e15cfe58340edb0c7b9ec9d3cf436b698fe34dd5164c8532101c6b
3
+ metadata.gz: c87a2c51edeb0644cea9c06b230dcc657b38fa61cf294dc395cd93396dc8e13a
4
+ data.tar.gz: 2b025ed3a1e7e4d1f40b29e4699ab24184de1924eaa417042c9a6cc411a03c2e
5
5
  SHA512:
6
- metadata.gz: 431be87c04f338cca58f4376cbcc71a7dbe2dbafd09457d9cc427cb96a8130bbd01b5e19bc45bbb895927119b55e50ff4ba023d1e6e009a25b481866fad55091
7
- data.tar.gz: 010ebff4d68d374cd403a5480a856a20d84b9fb5b73d931ec32f4821e1c7cd298c08bf0fdd4d8840c1b4297df0e75ffa6bac7be27764c4b209284635002eeb07
6
+ metadata.gz: a7826eb9467f5b842be5d54c5044d693288dfcf7439075e3e36b8adc7197e3100929e3505b7c2421f9e3c1b00a68388b21065f08503e64b5da20a40a69d50812
7
+ data.tar.gz: 6f126f39f97f17fbe778ebf3db11bf2b1c5cb5cab300bd5a98489b80f60acc9c5c27ad494035a34dc1bf9289550c77a55ba5b92709ea878e621951ecbd11f625
data/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 1.0.3
8
+
9
+ ### Fixed
10
+ - Removed unused runtime dependency on the redis gem.
11
+ - The ActiveJob timeout block no longer clears a timeout already established for the request or worker running the job (e.g. jobs run with `perform_now` inside a request, or ActiveJob jobs running with the Sidekiq middleware).
12
+ - `SafeRequestTimeout.check_timeout!` no longer raises a second error from an enclosing timeout block when a deadline shared by nested timeout blocks has already raised.
13
+ - ActiveRecord hooks no longer require a live database connection when they are installed. They are now added to each adapter class the first time a connection is instantiated, so applications that boot while the database is unavailable and applications with multiple databases are fully covered.
14
+ - Registering the same hooks more than once is now a no-op instead of raising an error.
15
+ - The transaction commit hook now clears the timeout after the commit succeeds instead of before it runs.
16
+
17
+ ### Changed
18
+ - Timeout state is stored in `ActiveSupport::IsolatedExecutionState` when available (ActiveSupport 7+) so that it follows the application's configured isolation level. Otherwise it is stored in fiber-local variables as before.
19
+ - ActiveJob and ActiveRecord integrations in the Railtie are now set up with lazy load hooks instead of loading the frameworks during initialization.
20
+
7
21
  ## 1.0.2
8
22
 
9
23
  ### Added
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Safe Request Timeout
2
2
 
3
3
  [![Continuous Integration](https://github.com/bdurand/safe_request_timeout/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/bdurand/safe_request_timeout/actions/workflows/continuous_integration.yml)
4
- [![Regression Test](https://github.com/bdurand/safe_request_timeout/actions/workflows/regression_test.yml/badge.svg)](https://github.com/bdurand/safe_request_timeout/actions/workflows/regression_test.yml)
5
4
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
5
+ [![Gem Version](https://badge.fury.io/rb/safe_request_timeout.svg)](https://badge.fury.io/rb/safe_request_timeout)
6
6
 
7
7
  This gem provides a safe and convenient mechanism for adding a timeout mechanism to a block of code. The gem ensures that the timeout is safe to call and will not raise timeout errors from random places in your code which can leave your application in an indeterminate state.
8
8
 
@@ -16,7 +16,7 @@ There is built in support for Rails applications. For other frameworks you will
16
16
 
17
17
  ## Usage
18
18
 
19
- You can wrap code in a timout block.
19
+ You can wrap code in a timeout block.
20
20
 
21
21
  ```ruby
22
22
  SafeRequestTimeout.timeout(15) do
@@ -33,7 +33,7 @@ SafeRequestTimeout.timeout(5) do
33
33
  1000.times do
34
34
  # This will raise an error if the loop takes longer than 5 seconds.
35
35
  SafeRequestTimeout.check_timeout!
36
- do_somthing
36
+ do_something
37
37
  end
38
38
  end
39
39
  ```
@@ -41,7 +41,7 @@ end
41
41
  You can also set a timeout value retroactively from within a `timeout` block. You can use this feature to change the timeout based on application state.
42
42
 
43
43
  ```ruby
44
- # Setting a timeout of nil will set up a block that will never timout.
44
+ # Setting a timeout of nil will set up a block that will never time out.
45
45
  SafeRequestTimeout.timeout(nil) do
46
46
  # Set the timeout duration to 5 seconds for non-admin users
47
47
  SafeRequestTimeout.set_timeout(5) unless current_user.admin?
@@ -58,7 +58,7 @@ SafeRequestTimeout.timeout(lambda { CurrentUser.new.admin? ? nil : 5 })
58
58
  end
59
59
  ```
60
60
 
61
- You can clear the timeout if you want to ensure a block of code can run without begin timed out (i.e. if you need to run cleanup code).
61
+ You can clear the timeout if you want to ensure a block of code can run without being timed out (i.e. if you need to run cleanup code).
62
62
 
63
63
  ```ruby
64
64
  SafeRequestTimeout.timeout(5) do
@@ -71,9 +71,17 @@ SafeRequestTimeout.timeout(5) do
71
71
  end
72
72
  ```
73
73
 
74
+ ### Behavior notes
75
+
76
+ - Timeout blocks can be nested. A nested block will use the soonest deadline of the nested blocks, so a nested block cannot extend a timeout set by an enclosing block. Calling `set_timeout` inside a nested block, however, replaces the deadline for that block even if it extends past the enclosing block's deadline; the enclosing deadline is restored when the nested block exits.
77
+
78
+ - `SafeRequestTimeout::TimeoutError` is a subclass of `Timeout::Error` from the Ruby standard library. Generic error handling that rescues or retries on `Timeout::Error` will catch it as well.
79
+
80
+ - The timeout state is stored per thread or fiber. When ActiveSupport 7+ is available, the state is stored in `ActiveSupport::IsolatedExecutionState` and follows the application's configured `active_support.isolation_level`. Otherwise the state is stored in fiber-local variables. In either case, the timeout will not be visible in new threads spawned within a timeout block (including ActiveRecord `load_async` queries), so `check_timeout!` calls in those threads will do nothing.
81
+
74
82
  ### Hooks
75
83
 
76
- You can add hooks into other classes to check the current timeout if you don't want to have to sprinkle `SafeRequestTimeout.check_timeout!` throughout your code. To do this, use the `SafeRequestTimeout.add_timeout!` method. You need to specify the class and methods where you want to add the timeout hooks:
84
+ You can add hooks into other classes to check the current timeout if you don't want to have to sprinkle `SafeRequestTimeout.check_timeout!` throughout your code. To do this, use the `SafeRequestTimeout::Hooks.add_timeout!` method. You need to specify the class and methods where you want to add the timeout hooks:
77
85
 
78
86
  ```ruby
79
87
  # Add a timeout check to the MyDriver#make_request method.
@@ -129,13 +137,13 @@ end
129
137
 
130
138
  This gem comes with built in support for Rails applications.
131
139
 
132
- - The Rack middleware is added to the middleware chain. There is no timeout value set by default. You can specify a global one by setting `safe_request_timout.rack_timeout` in your Rails configuration.
140
+ - The Rack middleware is added to the middleware chain. There is no timeout value set by default. You can specify a global one by setting `safe_request_timeout.rack_timeout` in your Rails configuration.
133
141
 
134
142
  - If Sidekiq is being used, then the Sidekiq middleware is added. Sidekiq workers can specify a timeout with the `safe_request_timeout` option.
135
143
 
136
- - A timeout block is added around ActiveJob execution. Jobs can specify a timeout by calling `SafeRequestTimeout.set_timeout` in the `perform` method or in a `before_perform` callback.
144
+ - A timeout block is added around ActiveJob execution. Jobs can specify a timeout by calling `SafeRequestTimeout.set_timeout` in the `perform` method or in a `before_perform` callback. If a timeout has already been set up for the request or worker running the job (i.e. a job run with `perform_now` inside a request, or an ActiveJob running on Sidekiq with the Sidekiq middleware), then that timeout is kept rather than replaced.
137
145
 
138
- - A timeout check is added on all ActiveRecord queries. The timeout is cleared when a database transaction is committed so that you won't unexpectedly timeout a request after making persistent changes. You can disable these hooks by setting `safe_request_timeout.active_record_hook` to false in your Rails configuration.
146
+ - A timeout check is added on all ActiveRecord queries. The timeout is cleared when a database transaction is committed so that you won't unexpectedly timeout a request after making persistent changes. You can disable these hooks by setting `safe_request_timeout.active_record_hook` to false in your Rails configuration. The hooks are installed on each database adapter class the first time a connection is instantiated, so no database connection is required at boot time and all databases in a multiple database configuration are covered.
139
147
 
140
148
  ## Installation
141
149
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.0.3
@@ -2,19 +2,60 @@
2
2
 
3
3
  module SafeRequestTimeout
4
4
  class ActiveRecordHook
5
+ MUTEX = Mutex.new
6
+ private_constant :MUTEX
7
+
8
+ @hooked_classes = []
9
+
5
10
  class << self
6
- # Add the timeout hook to the connection class.
11
+ # Add the timeout hook to a connection adapter class. If no class is given, then the
12
+ # hooks will be added to each connection adapter class the first time it is instantiated.
13
+ # This does not require a database connection to be established and covers every adapter
14
+ # in use, including applications with multiple databases.
7
15
  #
8
16
  # @param connection_class [Class] The class to add the timeout hook to.
9
17
  # @return [void]
10
18
  def add_timeout!(connection_class = nil)
11
- connection_class ||= ::ActiveRecord::Base.connection.class
12
- exec_method = (connection_class.instance_methods.include?(:internal_exec_query) ? :internal_exec_query : :exec_query)
19
+ if connection_class
20
+ add_hooks(connection_class)
21
+ else
22
+ ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(AdapterInitializer)
23
+ # Add the hooks to any adapter that already has a live connection.
24
+ if ::ActiveRecord::Base.connected?
25
+ ::ActiveRecord::Base.connection_pool.with_connection do |connection|
26
+ add_hooks(connection.class)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ private
13
33
 
14
- SafeRequestTimeout::Hooks.add_timeout!(connection_class, [exec_method])
34
+ def add_hooks(connection_class)
35
+ MUTEX.synchronize do
36
+ return if @hooked_classes.include?(connection_class)
15
37
 
16
- SafeRequestTimeout::Hooks.clear_timeout!(connection_class, [:commit_db_transaction])
38
+ exec_method = (connection_class.method_defined?(:internal_exec_query) ? :internal_exec_query : :exec_query)
39
+ SafeRequestTimeout::Hooks.add_timeout!(connection_class, [exec_method])
40
+ SafeRequestTimeout::Hooks.clear_timeout!(connection_class, [:commit_db_transaction])
41
+
42
+ @hooked_classes << connection_class
43
+ end
17
44
  end
18
45
  end
46
+
47
+ # Prepended to AbstractAdapter so the timeout hooks are added to each concrete adapter
48
+ # class the first time it is instantiated. The hooks must go on the concrete class since
49
+ # adapters can override the hooked methods.
50
+ module AdapterInitializer
51
+ ruby_major, ruby_minor, _ = RUBY_VERSION.split(".").collect(&:to_i)
52
+ splat_args = ((ruby_major >= 3 || (ruby_major == 2 && ruby_minor >= 7)) ? "..." : "*args, &block")
53
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
54
+ def initialize(#{splat_args})
55
+ super(#{splat_args})
56
+ SafeRequestTimeout::ActiveRecordHook.add_timeout!(self.class)
57
+ end
58
+ RUBY
59
+ end
19
60
  end
20
61
  end
@@ -4,12 +4,17 @@ module SafeRequestTimeout
4
4
  # Hooks into other classes from other libraries with timeout blocks. This allows
5
5
  # timeouts to be automatically checked before making requests to external services.
6
6
  module Hooks
7
+ MUTEX = Mutex.new
8
+ private_constant :MUTEX
9
+
7
10
  class << self
8
11
  # Hooks into a class by surrounding specified instance methods with timeout checks.
9
12
  def add_timeout!(klass, methods, module_name = nil)
10
13
  hooks_module = create_module(klass, module_name, "AddTimeout")
11
14
 
12
15
  Array(methods).each do |method_name|
16
+ next if hooks_module.method_defined?(method_name)
17
+
13
18
  hooks_module.class_eval <<~RUBY, __FILE__, __LINE__ + 1
14
19
  def #{method_name}(#{splat_args})
15
20
  SafeRequestTimeout.check_timeout!
@@ -25,10 +30,13 @@ module SafeRequestTimeout
25
30
  hooks_module = create_module(klass, module_name, "ClearTimeout")
26
31
 
27
32
  Array(methods).each do |method_name|
33
+ next if hooks_module.method_defined?(method_name)
34
+
28
35
  hooks_module.class_eval <<~RUBY, __FILE__, __LINE__ + 1
29
36
  def #{method_name}(#{splat_args})
37
+ result = super(#{splat_args})
30
38
  SafeRequestTimeout.clear_timeout
31
- super(#{splat_args})
39
+ result
32
40
  end
33
41
  RUBY
34
42
  end
@@ -41,17 +49,20 @@ module SafeRequestTimeout
41
49
  def create_module(klass, module_name, module_type)
42
50
  # Create a module that will be prepended to the specified class.
43
51
  unless module_name
44
- camelized_name = name.to_s.gsub(/[^a-z0-9]+([a-z0-9])/i) { |m| m[m.length - 1, m.length].upcase }
52
+ camelized_name = name.to_s.gsub(/[^a-z0-9]+([a-z0-9])/i) { |m| m[-1].upcase }
45
53
  camelized_name = "#{camelized_name[0].upcase}#{camelized_name[1, camelized_name.length]}"
46
54
  module_name = "#{klass.name.split("::").join}#{camelized_name}#{module_type}"
47
55
  end
48
56
 
49
- if const_defined?(module_name)
50
- raise ArgumentError.new("Cannot create duplicate #{module_name} for hooking #{name} into #{klass.name}")
57
+ # Reuse an existing module so that registering the same hooks twice is a no-op.
58
+ MUTEX.synchronize do
59
+ if const_defined?(module_name, false)
60
+ const_get(module_name, false)
61
+ else
62
+ # Dark arts & witchery to dynamically generate the module methods.
63
+ const_set(module_name, Module.new)
64
+ end
51
65
  end
52
-
53
- # Dark arts & witchery to dynamically generate the module methods.
54
- const_set(module_name, Module.new)
55
66
  end
56
67
 
57
68
  def splat_args
@@ -9,17 +9,24 @@ module SafeRequestTimeout
9
9
  initializer "safe_request_timeout" do |app|
10
10
  if app.config.safe_request_timeout.active_record_hook
11
11
  ActiveSupport.on_load(:active_record) do
12
- begin
13
- SafeRequestTimeout::ActiveRecordHook.add_timeout!
14
- rescue ActiveRecord::ActiveRecordError => e
15
- Rails.logger&.warn("Could not add ActiveRecord hook for SafeRequestTimeout: #{e.inspect}")
16
- end
12
+ SafeRequestTimeout::ActiveRecordHook.add_timeout!
13
+ rescue => e
14
+ # The hook is an optional safeguard, so any error installing it (including an
15
+ # unexpected incompatibility with the ActiveRecord version in use) is logged
16
+ # rather than allowed to prevent the application from booting.
17
+ Rails.logger&.warn("Could not add ActiveRecord hook for SafeRequestTimeout: #{e.inspect}")
17
18
  end
18
19
  end
19
20
 
20
- if defined?(ActiveJob::Base.around_perform)
21
- ActiveJob::Base.around_perform do |job, block|
22
- SafeRequestTimeout.timeout(nil, &block)
21
+ ActiveSupport.on_load(:active_job) do
22
+ around_perform do |job, block|
23
+ # Open a timeout context so jobs can call set_timeout, but don't replace a timeout
24
+ # already established for the request or worker that is running the job.
25
+ if SafeRequestTimeout.time_elapsed
26
+ block.call
27
+ else
28
+ SafeRequestTimeout.timeout(nil, &block)
29
+ end
23
30
  end
24
31
  end
25
32
 
@@ -31,8 +31,9 @@ module SafeRequestTimeout
31
31
  def timeout(duration, &block)
32
32
  duration = duration.call if duration.respond_to?(:call)
33
33
 
34
- previous_start_at = Thread.current[:safe_request_timeout_started_at]
35
- previous_timeout_at = Thread.current[:safe_request_timeout_timeout_at]
34
+ state = current_state
35
+ previous_start_at = state[:safe_request_timeout_started_at]
36
+ previous_timeout_at = state[:safe_request_timeout_timeout_at]
36
37
 
37
38
  start_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
38
39
  timeout_at = start_at + duration if duration
@@ -41,12 +42,18 @@ module SafeRequestTimeout
41
42
  end
42
43
 
43
44
  begin
44
- Thread.current[:safe_request_timeout_started_at] = start_at
45
- Thread.current[:safe_request_timeout_timeout_at] = timeout_at
45
+ state[:safe_request_timeout_started_at] = start_at
46
+ state[:safe_request_timeout_timeout_at] = timeout_at
46
47
  yield
47
48
  ensure
48
- Thread.current[:safe_request_timeout_started_at] = previous_start_at
49
- Thread.current[:safe_request_timeout_timeout_at] = previous_timeout_at
49
+ # If the deadline shared with the parent block was already raised by check_timeout!,
50
+ # don't re-arm it when restoring the parent block's state.
51
+ if previous_timeout_at && previous_timeout_at == state[:safe_request_timeout_fired_at]
52
+ previous_timeout_at = nil
53
+ end
54
+ state[:safe_request_timeout_started_at] = previous_start_at
55
+ state[:safe_request_timeout_timeout_at] = previous_timeout_at
56
+ state[:safe_request_timeout_fired_at] = nil if previous_start_at.nil?
50
57
  end
51
58
  end
52
59
 
@@ -54,7 +61,7 @@ module SafeRequestTimeout
54
61
  #
55
62
  # @return [Boolean] true if the current timeout block has timed out
56
63
  def timed_out?
57
- timeout_at = Thread.current[:safe_request_timeout_timeout_at]
64
+ timeout_at = current_state[:safe_request_timeout_timeout_at]
58
65
  !!timeout_at && Process.clock_gettime(Process::CLOCK_MONOTONIC) > timeout_at
59
66
  end
60
67
 
@@ -66,7 +73,9 @@ module SafeRequestTimeout
66
73
  # @raise [SafeRequestTimeout::TimeoutError] if the current timeout block has timed out
67
74
  def check_timeout!
68
75
  if timed_out?
69
- Thread.current[:safe_request_timeout_timeout_at] = nil
76
+ state = current_state
77
+ state[:safe_request_timeout_fired_at] = state[:safe_request_timeout_timeout_at]
78
+ state[:safe_request_timeout_timeout_at] = nil
70
79
  raise TimeoutError.new("after #{time_elapsed.round(6)} seconds")
71
80
  end
72
81
  end
@@ -76,7 +85,7 @@ module SafeRequestTimeout
76
85
  #
77
86
  # @return [Float, nil] the number of seconds remaining in the current timeout block
78
87
  def time_remaining
79
- timeout_at = Thread.current[:safe_request_timeout_timeout_at]
88
+ timeout_at = current_state[:safe_request_timeout_timeout_at]
80
89
  [timeout_at - Process.clock_gettime(Process::CLOCK_MONOTONIC), 0.0].max if timeout_at
81
90
  end
82
91
 
@@ -85,7 +94,7 @@ module SafeRequestTimeout
85
94
  #
86
95
  # @return [Float, nil] the number of seconds elapsed in the current timeout block began
87
96
  def time_elapsed
88
- start_at = Thread.current[:safe_request_timeout_started_at]
97
+ start_at = current_state[:safe_request_timeout_started_at]
89
98
  Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_at if start_at
90
99
  end
91
100
 
@@ -95,12 +104,17 @@ module SafeRequestTimeout
95
104
  #
96
105
  # @return [void]
97
106
  def set_timeout(duration)
98
- if Thread.current[:safe_request_timeout_started_at]
107
+ state = current_state
108
+ if state[:safe_request_timeout_started_at]
99
109
  start_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
100
110
  duration = duration.call if duration.respond_to?(:call)
101
111
  timeout_at = start_at + duration if duration
102
- Thread.current[:safe_request_timeout_started_at] = start_at
103
- Thread.current[:safe_request_timeout_timeout_at] = timeout_at
112
+ state[:safe_request_timeout_started_at] = start_at
113
+ state[:safe_request_timeout_timeout_at] = timeout_at
114
+ # Arming a new deadline invalidates any record of a previously fired deadline so
115
+ # that the ensure block in `timeout` cannot mistake the new deadline for one that
116
+ # has already raised.
117
+ state[:safe_request_timeout_fired_at] = nil if timeout_at
104
118
  end
105
119
  end
106
120
 
@@ -116,6 +130,19 @@ module SafeRequestTimeout
116
130
  set_timeout(nil)
117
131
  end
118
132
  end
133
+
134
+ private
135
+
136
+ # Storage for the timeout state. ActiveSupport::IsolatedExecutionState is used when it
137
+ # is available so that the state follows the application's configured isolation level
138
+ # (:thread or :fiber). Otherwise the state is fiber local.
139
+ def current_state
140
+ if defined?(::ActiveSupport::IsolatedExecutionState)
141
+ ::ActiveSupport::IsolatedExecutionState
142
+ else
143
+ ::Thread.current
144
+ end
145
+ end
119
146
  end
120
147
  end
121
148
 
@@ -8,6 +8,12 @@ Gem::Specification.new do |spec|
8
8
  spec.homepage = "https://github.com/bdurand/safe_request_timeout"
9
9
  spec.license = "MIT"
10
10
 
11
+ spec.metadata = {
12
+ "homepage_uri" => spec.homepage,
13
+ "source_code_uri" => spec.homepage,
14
+ "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
15
+ }
16
+
11
17
  # Specify which files should be added to the gem when it is released.
12
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
13
19
  ignore_files = %w[
@@ -26,9 +32,5 @@ Gem::Specification.new do |spec|
26
32
 
27
33
  spec.require_paths = ["lib"]
28
34
 
29
- spec.add_dependency "redis"
30
-
31
- spec.add_development_dependency "bundler"
32
-
33
- spec.required_ruby_version = ">= 2.5"
35
+ spec.required_ruby_version = ">= 2.6"
34
36
  end
metadata CHANGED
@@ -1,44 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe_request_timeout
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-11-11 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: redis
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- description:
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
42
12
  email:
43
13
  - bbdurand@gmail.com
44
14
  executables: []
@@ -49,7 +19,6 @@ files:
49
19
  - MIT_LICENSE.txt
50
20
  - README.md
51
21
  - VERSION
52
- - dependabot.yml
53
22
  - lib/safe_request_timeout.rb
54
23
  - lib/safe_request_timeout/active_record_hook.rb
55
24
  - lib/safe_request_timeout/hooks.rb
@@ -61,8 +30,10 @@ files:
61
30
  homepage: https://github.com/bdurand/safe_request_timeout
62
31
  licenses:
63
32
  - MIT
64
- metadata: {}
65
- post_install_message:
33
+ metadata:
34
+ homepage_uri: https://github.com/bdurand/safe_request_timeout
35
+ source_code_uri: https://github.com/bdurand/safe_request_timeout
36
+ changelog_uri: https://github.com/bdurand/safe_request_timeout/blob/main/CHANGELOG.md
66
37
  rdoc_options: []
67
38
  require_paths:
68
39
  - lib
@@ -70,15 +41,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
41
  requirements:
71
42
  - - ">="
72
43
  - !ruby/object:Gem::Version
73
- version: '2.5'
44
+ version: '2.6'
74
45
  required_rubygems_version: !ruby/object:Gem::Requirement
75
46
  requirements:
76
47
  - - ">="
77
48
  - !ruby/object:Gem::Version
78
49
  version: '0'
79
50
  requirements: []
80
- rubygems_version: 3.4.12
81
- signing_key:
51
+ rubygems_version: 4.0.3
82
52
  specification_version: 4
83
53
  summary: Mechanism for safely aborting long-running requests after a specified timeout.
84
54
  test_files: []
data/dependabot.yml DELETED
@@ -1,12 +0,0 @@
1
- # Dependabot update strategy
2
- version: 2
3
- updates:
4
- - package-ecosystem: bundler
5
- directory: "/"
6
- schedule:
7
- interval: daily
8
- allow:
9
- # Automatically keep all runtime dependencies updated
10
- - dependency-name: "*"
11
- dependency-type: "production"
12
- versioning-strategy: lockfile-only