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 = ::Timeout::Error, &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 = ::Timeout::Error, &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

#build_timeout_procObject

nodoc



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
89
90
# File 'lib/soft_timeout.rb', line 59

def build_timeout_proc
  message = "execution expired".freeze

  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
      }
      yield(soft_expiry)
    ensure
      if timeout_thread
        timeout_thread.kill
        timeout_thread.join # make sure timeout_thread is dead.
      end
    end
  end
end

#run_proc_with_error_handling(timeout_proc) ⇒ Object

nodoc

Raises:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/soft_timeout.rb', line 43

def run_proc_with_error_handling(timeout_proc)
  message = "execution expired".freeze
  begin
    return timeout_proc.call(error_class)
  rescue error_class => e
    bt = e.backtrace
  end

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

#soft_timeout(&block) ⇒ Object



37
38
39
40
# File 'lib/soft_timeout.rb', line 37

def soft_timeout(&block)
  return yield(soft_expiry) if soft_expiry == nil || soft_expiry < 0 || hard_expiry == nil || hard_expiry < 0 || hard_expiry <= soft_expiry
  run_proc_with_error_handling(build_timeout_proc(&block))
end