Class: SoftTimeout::Timeout

Inherits:
Object
  • Object
show all
Defined in:
lib/soft_timeout.rb

Overview

require ‘soft_timeout’

timeout = SoftTimeout::Timeout.new(10, 20) do

puts 'Soft timeout reached'

end

timeout.soft_timeout do

...
Some code
...

end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(soft_expiry, hard_expiry, error_class = nil, &block) ⇒ Timeout

Initialize

soft_expiry

Number of seconds to wait to execute on_soft_timeout block

hard_expiry

Number of seconds to wait before raising Timeout Error

error_class

Exception class to raise

block

Proc to be run at end of soft_expiry



30
31
32
33
34
35
# File 'lib/soft_timeout.rb', line 30

def initialize(soft_expiry, hard_expiry, error_class = nil, &block)
  self.soft_expiry = soft_expiry
  self.hard_expiry = hard_expiry
  self.error_class = error_class
  self.on_soft_timeout = block if block_given?
end

Instance Attribute Details

#error_classObject

Returns the value of attribute error_class.



21
22
23
# File 'lib/soft_timeout.rb', line 21

def error_class
  @error_class
end

#hard_expiryObject

Returns the value of attribute hard_expiry.



21
22
23
# File 'lib/soft_timeout.rb', line 21

def hard_expiry
  @hard_expiry
end

#on_soft_timeoutObject

Returns the value of attribute on_soft_timeout.



21
22
23
# File 'lib/soft_timeout.rb', line 21

def on_soft_timeout
  @on_soft_timeout
end

#soft_expiryObject

Returns the value of attribute soft_expiry.



21
22
23
# File 'lib/soft_timeout.rb', line 21

def soft_expiry
  @soft_expiry
end

Instance Method Details

#soft_timeoutObject

Raises:

  • (e)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/soft_timeout.rb', line 37

def soft_timeout
  return yield(soft_expiry) if soft_expiry == nil || soft_expiry < 0 || hard_expiry == nil || hard_expiry < 0 || hard_expiry <= soft_expiry
  message = "execution expired".freeze

  e = ::Timeout::Error
  bl = proc do |exception|
    begin
      original_thread = Thread.current
      timeout_thread = Thread.start {
        begin
          sleep soft_expiry
        rescue => e
          original_thread.raise e
        else
          on_soft_timeout.call if on_soft_timeout
        end

        begin
          sleep hard_expiry - soft_expiry
        rescue => e
          original_thread.raise e
        else
          original_thread.raise exception, message
        end
      }
      return yield(soft_expiry)
    ensure
      if timeout_thread
        timeout_thread.kill
        timeout_thread.join # make sure timeout_thread is dead.
      end
    end
  end

  # Why this strange Error catch and all. checkout http://stackoverflow.com/questions/35447230/ruby-timeout-behaves-differently-between-2-0-and-2-1
  if error_class
    begin
      bl.call(error_class)
    rescue error_class => l
      bt = l.backtrace
    end
  else
    bt = ::Timeout::Error.catch(message, &bl)
  end


  level = -caller(CALLER_OFFSET).size-2
  while THIS_FILE =~ bt[level]
    bt.delete_at(level)
  end
  raise(e, message, bt)
end