Module: SafeRequestTimeout
- Defined in:
- lib/safe_request_timeout.rb,
lib/safe_request_timeout/hooks.rb,
lib/safe_request_timeout/railtie.rb,
lib/safe_request_timeout/version.rb,
lib/safe_request_timeout/rack_middleware.rb,
lib/safe_request_timeout/active_record_hook.rb,
lib/safe_request_timeout/sidekiq_middleware.rb
Overview
This module adds the capability to add a general timeout to any block of code. Unlike the Timeout module, an error is not raised to indicate a timeout. Instead, the ‘timed_out?` method can be used to check if the block of code has taken longer than the specified duration so the application can take the appropriate action.
This is a safer alternative to the Timeout module because it does not fork new threads or risk raising errors from unexpected places.
Defined Under Namespace
Modules: Hooks Classes: ActiveRecordHook, RackMiddleware, Railtie, SidekiqMiddleware, TimeoutError
Constant Summary collapse
- VERSION =
File.read(File.("../../VERSION", __dir__)).chomp.freeze
Class Method Summary collapse
-
.check_timeout! ⇒ void
Raise an error if the current timeout block has timed out.
-
.clear_timeout { ... } ⇒ Object
Clear the current timeout.
-
.set_timeout(duration) ⇒ void
Set the duration for the current timeout block.
-
.time_elapsed ⇒ Float?
Get the number of seconds elapsed in the current timeout block or nil if there is no timeout block.
-
.time_remaining ⇒ Float?
Get the number of seconds remaining in the current timeout block or nil if there is no timeout block.
-
.timed_out? ⇒ Boolean
Check if the current timeout block has timed out.
-
.timeout(duration) { ... } ⇒ Object
Execute the given block with a timeout.
Class Method Details
.check_timeout! ⇒ void
This method returns an undefined value.
Raise an error if the current timeout block has timed out. If there is no timeout block, then this method does nothing. If an error is raised, then the current timeout is cleared to prevent the error from being raised multiple times.
67 68 69 70 71 72 |
# File 'lib/safe_request_timeout.rb', line 67 def check_timeout! if timed_out? Thread.current[:safe_request_timeout_timeout_at] = nil raise TimeoutError.new("after #{time_elapsed.round(6)} seconds") end end |
.clear_timeout { ... } ⇒ Object
Clear the current timeout. If a block is passed, then the timeout will be cleared only for the duration of the block.
112 113 114 115 116 117 118 |
# File 'lib/safe_request_timeout.rb', line 112 def clear_timeout(&block) if block timeout(nil, &block) else set_timeout(nil) end end |
.set_timeout(duration) ⇒ void
This method returns an undefined value.
Set the duration for the current timeout block. This is useful if you want to set the duration after the timeout block has started. The timer for the timeout block will restart whenever a new duration is set.
97 98 99 100 101 102 103 104 105 |
# File 'lib/safe_request_timeout.rb', line 97 def set_timeout(duration) if Thread.current[:safe_request_timeout_started_at] start_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) duration = duration.call if duration.respond_to?(:call) timeout_at = start_at + duration if duration Thread.current[:safe_request_timeout_started_at] = start_at Thread.current[:safe_request_timeout_timeout_at] = timeout_at end end |
.time_elapsed ⇒ Float?
Get the number of seconds elapsed in the current timeout block or nil if there is no timeout block.
87 88 89 90 |
# File 'lib/safe_request_timeout.rb', line 87 def time_elapsed start_at = Thread.current[:safe_request_timeout_started_at] Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_at if start_at end |
.time_remaining ⇒ Float?
Get the number of seconds remaining in the current timeout block or nil if there is no timeout block.
78 79 80 81 |
# File 'lib/safe_request_timeout.rb', line 78 def time_remaining timeout_at = Thread.current[:safe_request_timeout_timeout_at] [timeout_at - Process.clock_gettime(Process::CLOCK_MONOTONIC), 0.0].max if timeout_at end |
.timed_out? ⇒ Boolean
Check if the current timeout block has timed out.
56 57 58 59 |
# File 'lib/safe_request_timeout.rb', line 56 def timed_out? timeout_at = Thread.current[:safe_request_timeout_timeout_at] !!timeout_at && Process.clock_gettime(Process::CLOCK_MONOTONIC) > timeout_at end |
.timeout(duration) { ... } ⇒ Object
Execute the given block with a timeout. If the block takes longer than the specified duration to execute, then the ‘timed_out?“ method will return true within the block.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/safe_request_timeout.rb', line 31 def timeout(duration, &block) duration = duration.call if duration.respond_to?(:call) previous_start_at = Thread.current[:safe_request_timeout_started_at] previous_timeout_at = Thread.current[:safe_request_timeout_timeout_at] start_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) timeout_at = start_at + duration if duration if timeout_at && previous_timeout_at && previous_timeout_at < timeout_at timeout_at = previous_timeout_at end begin Thread.current[:safe_request_timeout_started_at] = start_at Thread.current[:safe_request_timeout_timeout_at] = timeout_at yield ensure Thread.current[:safe_request_timeout_started_at] = previous_start_at Thread.current[:safe_request_timeout_timeout_at] = previous_timeout_at end end |