Module: Angael::Worker
- Includes:
- ProcessHelper
- Defined in:
- lib/angael/worker.rb
Overview
Usage
include Angael::Worker
def work
# Do something interesting, without raising an exception.
end
You can also add some optional behavior by defining the following methods:
#after_fork - This is run once, immediately after the child process is forked
#fork_child - This actually does the forking. You can overwrite this method
to do wrap the child process in a block. This is useful for
exception handling. Be sure to actually fork or you may break
something important.
#log - If defined, this will be called at various points of interest
with 1 String as the argument. Log levels are not supported.
#timeout - Number of seconds to wait for the child process to exit after
it is sent SIGINT. If you don't define this method, it waits
60 seconds.
Defined Under Namespace
Classes: ChildProcessNotStoppedError
Instance Attribute Summary collapse
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
Instance Method Summary collapse
-
#restart! ⇒ Object
This only exists for the sake of testing.
-
#start! ⇒ Object
Loops forever, taking jobs off the queue.
- #started? ⇒ Boolean
-
#stop_with_wait ⇒ Object
Keeps sending SIGINT until the child process exits.
-
#stop_without_wait ⇒ Object
Returns true if SIGINT was sent to the child process, even if the child process does not exists.
- #stopped? ⇒ Boolean
-
#stopping? ⇒ Boolean
TODO: test this.
Methods included from ProcessHelper
Instance Attribute Details
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
23 24 25 |
# File 'lib/angael/worker.rb', line 23 def pid @pid end |
Instance Method Details
#restart! ⇒ Object
This only exists for the sake of testing. I need a way to stub the restart! but not the original start! Note: this method is not tested directly. Users of this library should not call this method or depend on its existence or behavior.
64 65 66 |
# File 'lib/angael/worker.rb', line 64 def restart! start! end |
#start! ⇒ Object
Loops forever, taking jobs off the queue. SIGINT will stop it after allowing any jobs already taken from the queue to be processed.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/angael/worker.rb', line 27 def start! @stopping = false @pid = fork_child do __log("Started") if respond_to?(:after_fork) __log("Running after fork callback") after_fork __log("Finished running after fork callback") end @interrupted = false trap("INT") do __log("SIGINT Received") @interrupted = true end trap("TERM") do __log("SIGTERM Received") @interrupted = true end loop do if @interrupted __log("Child process exiting gracefully") exit 0 end work end end end |
#started? ⇒ Boolean
117 118 119 |
# File 'lib/angael/worker.rb', line 117 def started? !!(pid && pid_running?) end |
#stop_with_wait ⇒ Object
Keeps sending SIGINT until the child process exits. If #timeout seconds pass, then it sends 1 SIGKILL. If that also fails, it raises ChildProcessNotStoppedError.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/angael/worker.rb', line 89 def stop_with_wait return false unless stop_without_wait __log("Waiting for child process with pid #{pid} to stop.") counter = 0 while pid_running? && counter < timeout sleep 1 counter += 1 __log("Sending SIGINT to child process with pid #{pid}. Attempt Count: #{counter}.") send_signal('INT', pid) end if pid_running? __log("Child process with pid #{pid} did not stop within #{timeout} seconds of SIGINT. Sending SIGKILL to child process.") send_signal('KILL', pid) sleep 1 end if pid_running? # SIGKILL didn't work. msg = "Unable to kill child process with PID: #{pid}" __log(msg) raise ChildProcessNotStoppedError, msg end end |
#stop_without_wait ⇒ Object
Returns true if SIGINT was sent to the child process, even if the child process does not exists. Returns false if started? is true. Sets stopping? to false.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/angael/worker.rb', line 72 def stop_without_wait unless started? __log("Tried to stop worker with PID #{pid} but it is not started") return false end # This informs the Manager (through #stopping?) that we intentionally # stopped the child process. @stopping = true __log("Sending SIGINT to child process with pid #{pid}.") send_signal('INT', pid) true end |
#stopped? ⇒ Boolean
120 121 122 |
# File 'lib/angael/worker.rb', line 120 def stopped? !started? end |
#stopping? ⇒ Boolean
TODO: test this
124 125 126 |
# File 'lib/angael/worker.rb', line 124 def stopping? @stopping end |