fire_and_forget 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/Gemfile.lock +0 -8
  2. data/README.rdoc +75 -14
  3. data/bin/fire_forget +45 -22
  4. data/examples/long_task +27 -16
  5. data/fire_and_forget.gemspec +41 -4
  6. data/lib/fire_and_forget/client.rb +1 -1
  7. data/lib/fire_and_forget/command/fire.rb +23 -4
  8. data/lib/fire_and_forget/command/get_pid.rb +20 -0
  9. data/lib/fire_and_forget/command/set_pid.rb +0 -2
  10. data/lib/fire_and_forget/command/set_status.rb +1 -1
  11. data/lib/fire_and_forget/command.rb +11 -0
  12. data/lib/fire_and_forget/config.rb +3 -8
  13. data/lib/fire_and_forget/daemon.rb +14 -23
  14. data/lib/fire_and_forget/errors.rb +8 -0
  15. data/lib/fire_and_forget/launcher.rb +69 -6
  16. data/lib/fire_and_forget/server.rb +5 -1
  17. data/lib/fire_and_forget/task_description.rb +11 -0
  18. data/lib/fire_and_forget/utilities.rb +4 -4
  19. data/lib/fire_and_forget/version.rb +1 -1
  20. data/lib/fire_and_forget.rb +6 -2
  21. data/test/test_fire_and_forget.rb +59 -26
  22. data/vendor/daemons-1.1.0/LICENSE +29 -0
  23. data/vendor/daemons-1.1.0/README +224 -0
  24. data/vendor/daemons-1.1.0/Rakefile +88 -0
  25. data/vendor/daemons-1.1.0/Releases +152 -0
  26. data/vendor/daemons-1.1.0/TODO +2 -0
  27. data/vendor/daemons-1.1.0/lib/daemons/application.rb +468 -0
  28. data/vendor/daemons-1.1.0/lib/daemons/application_group.rb +194 -0
  29. data/vendor/daemons-1.1.0/lib/daemons/change_privilege.rb +19 -0
  30. data/vendor/daemons-1.1.0/lib/daemons/cmdline.rb +124 -0
  31. data/vendor/daemons-1.1.0/lib/daemons/controller.rb +140 -0
  32. data/vendor/daemons-1.1.0/lib/daemons/daemonize.rb +271 -0
  33. data/vendor/daemons-1.1.0/lib/daemons/etc_extension.rb +12 -0
  34. data/vendor/daemons-1.1.0/lib/daemons/exceptions.rb +28 -0
  35. data/vendor/daemons-1.1.0/lib/daemons/monitor.rb +138 -0
  36. data/vendor/daemons-1.1.0/lib/daemons/pid.rb +109 -0
  37. data/vendor/daemons-1.1.0/lib/daemons/pidfile.rb +116 -0
  38. data/vendor/daemons-1.1.0/lib/daemons/pidmem.rb +19 -0
  39. data/vendor/daemons-1.1.0/lib/daemons.rb +288 -0
  40. data/vendor/daemons-1.1.0/setup.rb +1360 -0
  41. data/vendor/json-1.5.0/COPYING +58 -0
  42. data/vendor/json-1.5.0/GPL +340 -0
  43. data/vendor/json-1.5.0/README +356 -0
  44. data/vendor/json-1.5.0/README-json-jruby.markdown +33 -0
  45. data/vendor/json-1.5.0/Rakefile +397 -0
  46. data/vendor/json-1.5.0/TODO +1 -0
  47. data/vendor/json-1.5.0/VERSION +1 -0
  48. data/vendor/json-1.5.0/lib/json/add/core.rb +147 -0
  49. data/vendor/json-1.5.0/lib/json/add/rails.rb +8 -0
  50. data/vendor/json-1.5.0/lib/json/common.rb +419 -0
  51. data/vendor/json-1.5.0/lib/json/editor.rb +1369 -0
  52. data/vendor/json-1.5.0/lib/json/pure/generator.rb +441 -0
  53. data/vendor/json-1.5.0/lib/json/pure/parser.rb +320 -0
  54. data/vendor/json-1.5.0/lib/json/pure.rb +15 -0
  55. data/vendor/json-1.5.0/lib/json/version.rb +8 -0
  56. data/vendor/json-1.5.0/lib/json.rb +10 -0
  57. metadata +41 -4
  58. data/lib/fire_and_forget/task.rb +0 -11
@@ -0,0 +1,288 @@
1
+ require 'optparse'
2
+ require 'optparse/time'
3
+
4
+
5
+ require 'daemons/pidfile'
6
+ require 'daemons/cmdline'
7
+ require 'daemons/exceptions'
8
+ require 'daemons/monitor'
9
+
10
+
11
+ require 'daemons/application'
12
+ require 'daemons/application_group'
13
+ require 'daemons/controller'
14
+
15
+ require 'timeout'
16
+
17
+ # All functions and classes that Daemons provides reside in this module.
18
+ #
19
+ # Daemons is normally invoked by one of the following four ways:
20
+ #
21
+ # 1. <tt>Daemons.run(script, options)</tt>:
22
+ # This is used in wrapper-scripts that are supposed to control other ruby scripts or
23
+ # external applications. Control is completely passed to the daemons library.
24
+ # Such wrapper script need to be invoked with command line options like 'start' or 'stop'
25
+ # to do anything useful.
26
+ #
27
+ # 2. <tt>Daemons.run_proc(app_name, options) { (...) }</tt>:
28
+ # This is used in wrapper-scripts that are supposed to control a proc.
29
+ # Control is completely passed to the daemons library.
30
+ # Such wrapper script need to be invoked with command line options like 'start' or 'stop'
31
+ # to do anything useful.
32
+ #
33
+ # 3. <tt>Daemons.call(options) { block }</tt>:
34
+ # Execute the block in a new daemon. <tt>Daemons.call</tt> will return immediately
35
+ # after spawning the daemon with the new Application object as a return value.
36
+ #
37
+ # 4. <tt>Daemons.daemonize(options)</tt>:
38
+ # Daemonize the currently runnig process, i.e. the calling process will become a daemon.
39
+ #
40
+ # == What does daemons internally do with my daemons?
41
+ # *or*:: why do my daemons crash when they try to open a file?
42
+ # *or*:: why can I not see any output from the daemon on the console (when using for example +puts+)?
43
+ #
44
+ # From a technical aspect of view, daemons does the following when creating a daemon:
45
+ #
46
+ # 1. Forks a child (and exits the parent process, if needed)
47
+ # 2. Becomes a session leader (which detaches the program from
48
+ # the controlling terminal).
49
+ # 3. Forks another child process and exits first child. This prevents
50
+ # the potential of acquiring a controlling terminal.
51
+ # 4. Changes the current working directory to "/".
52
+ # 5. Clears the file creation mask (sets +umask+ to 0000).
53
+ # 6. Closes file descriptors (reopens +STDOUT+ and +STDERR+ to point to a logfile if
54
+ # possible).
55
+ #
56
+ # So what does this mean for your daemons:
57
+ # - the current directory is '/'
58
+ # - you cannot receive any input from the console (for example no +gets+)
59
+ # - you cannot output anything from the daemons with +puts+/+print+ unless a logfile is used
60
+ #
61
+ # == How do PidFiles work? Where are they stored?
62
+ #
63
+ # Also, you are maybe interested in reading the documentation for the class PidFile.
64
+ # There you can find out about how Daemons works internally and how and where the so
65
+ # called <i>PidFiles</i> are stored.
66
+ #
67
+ module Daemons
68
+
69
+ VERSION = "1.1.0"
70
+
71
+ require 'daemons/daemonize'
72
+
73
+
74
+ # Passes control to Daemons.
75
+ # This is used in wrapper-scripts that are supposed to control other ruby scripts or
76
+ # external applications. Control is completely passed to the daemons library.
77
+ # Such wrapper script should be invoked with command line options like 'start' or 'stop'
78
+ # to do anything useful.
79
+ #
80
+ # +script+:: This is the path to the script that should be run as a daemon.
81
+ # Please note that Daemons runs this script with <tt>load <script></tt>.
82
+ # Also note that Daemons cannot detect the directory in which the controlling
83
+ # script resides, so this has to be either an absolute path or you have to run
84
+ # the controlling script from the appropriate directory.
85
+ #
86
+ # +options+:: A hash that may contain one or more of the options listed below
87
+ #
88
+ # === Options:
89
+ # <tt>:app_name</tt>:: The name of the application. This will be
90
+ # used to contruct the name of the pid files
91
+ # and log files. Defaults to the basename of
92
+ # the script.
93
+ # <tt>:ARGV</tt>:: An array of strings containing parameters and switches for Daemons.
94
+ # This includes both parameters for Daemons itself and the controlled scripted.
95
+ # These are assumed to be separated by an array element '--', .e.g.
96
+ # ['start', 'f', '--', 'param1_for_script', 'param2_for_script'].
97
+ # If not given, ARGV (the parameters given to the Ruby process) will be used.
98
+ # <tt>:dir_mode</tt>:: Either <tt>:script</tt> (the directory for writing the pid files to
99
+ # given by <tt>:dir</tt> is interpreted relative
100
+ # to the script location given by +script+) or <tt>:normal</tt> (the directory given by
101
+ # <tt>:dir</tt> is interpreted as a (absolute or relative) path) or <tt>:system</tt>
102
+ # (<tt>/var/run</tt> is used as the pid file directory)
103
+ #
104
+ # <tt>:dir</tt>:: Used in combination with <tt>:dir_mode</tt> (description above)
105
+ # <tt>:multiple</tt>:: Specifies whether multiple instances of the same script are allowed to run at the
106
+ # same time
107
+ # <tt>:ontop</tt>:: When given (i.e. set to true), stay on top, i.e. do not daemonize the application
108
+ # (but the pid-file and other things are written as usual)
109
+ # <tt>:mode</tt>:: <tt>:load</tt> Load the script with <tt>Kernel.load</tt>;
110
+ # note that :stop_proc only works for the :load (and :proc) mode.
111
+ # <tt>:exec</tt> Execute the script file with <tt>Kernel.exec</tt>
112
+ # <tt>:backtrace</tt>:: Write a backtrace of the last exceptions to the file '[app_name].log' in the
113
+ # pid-file directory if the application exits due to an uncaught exception
114
+ # <tt>:monitor</tt>:: Monitor the programs and restart crashed instances
115
+ # <tt>:log_output</tt>:: When given (i.e. set to true), redirect both STDOUT and STDERR to a logfile named '[app_name].output' in the pid-file directory
116
+ # <tt>:keep_pid_files</tt>:: When given do not delete lingering pid-files (files for which the process is no longer running).
117
+ # <tt>:hard_exit</tt>:: When given use exit! to end a daemons instead of exit (this will for example
118
+ # not call at_exit handlers).
119
+ # <tt>:stop_proc</tt>:: A proc that will be called when the daemonized process receives a request to stop (works only for :load and :proc mode)
120
+ #
121
+ # -----
122
+ #
123
+ # === Example:
124
+ # options = {
125
+ # :app_name => "my_app",
126
+ # :ARGV => ['start', '-f', '--', 'param_for_myscript']
127
+ # :dir_mode => :script,
128
+ # :dir => 'pids',
129
+ # :multiple => true,
130
+ # :ontop => true,
131
+ # :mode => :exec,
132
+ # :backtrace => true,
133
+ # :monitor => true
134
+ # }
135
+ #
136
+ # Daemons.run(File.join(File.dirname(__FILE__), 'myscript.rb'), options)
137
+ #
138
+ def run(script, options = {})
139
+ options[:script] = script
140
+ @controller = Controller.new(options, options[:ARGV] || ARGV)
141
+
142
+ @controller.catch_exceptions {
143
+ @controller.run
144
+ }
145
+
146
+ # I don't think anybody will ever use @group, as this location should not be reached under non-error conditions
147
+ @group = @controller.group
148
+ end
149
+ module_function :run
150
+
151
+
152
+ # Passes control to Daemons.
153
+ # This function does the same as Daemons.run except that not a script but a proc
154
+ # will be run as a daemon while this script provides command line options like 'start' or 'stop'
155
+ # and the whole pid-file management to control the proc.
156
+ #
157
+ # +app_name+:: The name of the application. This will be
158
+ # used to contruct the name of the pid files
159
+ # and log files. Defaults to the basename of
160
+ # the script.
161
+ #
162
+ # +options+:: A hash that may contain one or more of the options listed in the documentation for Daemons.run
163
+ #
164
+ # A block must be given to this function. The block will be used as the :proc entry in the options hash.
165
+ #
166
+ # -----
167
+ #
168
+ # === Example:
169
+ #
170
+ # Daemons.run_proc('myproc.rb') do
171
+ # loop do
172
+ # accept_connection()
173
+ # read_request()
174
+ # send_response()
175
+ # close_connection()
176
+ # end
177
+ # end
178
+ #
179
+ def run_proc(app_name, options = {}, &block)
180
+ options[:app_name] = app_name
181
+ options[:mode] = :proc
182
+ options[:proc] = block
183
+
184
+ # we do not have a script location so the the :script :dir_mode cannot be used, change it to :normal
185
+ if [nil, :script].include? options[:dir_mode]
186
+ options[:dir_mode] = :normal
187
+ options[:dir] = File.expand_path('.')
188
+ end
189
+
190
+ @controller = Controller.new(options, options[:ARGV] || ARGV)
191
+
192
+ @controller.catch_exceptions {
193
+ @controller.run
194
+ }
195
+
196
+ # I don't think anybody will ever use @group, as this location should not be reached under non-error conditions
197
+ @group = @controller.group
198
+ end
199
+ module_function :run_proc
200
+
201
+
202
+ # Execute the block in a new daemon. <tt>Daemons.call</tt> will return immediately
203
+ # after spawning the daemon with the new Application object as a return value.
204
+ #
205
+ # +options+:: A hash that may contain one or more of the options listed below
206
+ #
207
+ # +block+:: The block to call in the daemon.
208
+ #
209
+ # === Options:
210
+ # <tt>:multiple</tt>:: Specifies whether multiple instances of the same script are allowed to run at the
211
+ # same time
212
+ # <tt>:ontop</tt>:: When given, stay on top, i.e. do not daemonize the application
213
+ # <tt>:backtrace</tt>:: Write a backtrace of the last exceptions to the file '[app_name].log' in the
214
+ # pid-file directory if the application exits due to an uncaught exception
215
+ # -----
216
+ #
217
+ # === Example:
218
+ # options = {
219
+ # :backtrace => true,
220
+ # :monitor => true,
221
+ # :ontop => true
222
+ # }
223
+ #
224
+ # Daemons.call(options) begin
225
+ # # Server loop:
226
+ # loop {
227
+ # conn = accept_conn()
228
+ # serve(conn)
229
+ # }
230
+ # end
231
+ #
232
+ def call(options = {}, &block)
233
+ unless block_given?
234
+ raise "Daemons.call: no block given"
235
+ end
236
+
237
+ options[:proc] = block
238
+ options[:mode] = :proc
239
+
240
+ @group ||= ApplicationGroup.new('proc', options)
241
+
242
+ new_app = @group.new_application(options)
243
+ new_app.start
244
+
245
+ return new_app
246
+ end
247
+ module_function :call
248
+
249
+
250
+ # Daemonize the currently runnig process, i.e. the calling process will become a daemon.
251
+ #
252
+ # +options+:: A hash that may contain one or more of the options listed below
253
+ #
254
+ # === Options:
255
+ # <tt>:ontop</tt>:: When given, stay on top, i.e. do not daemonize the application
256
+ # <tt>:backtrace</tt>:: Write a backtrace of the last exceptions to the file '[app_name].log' in the
257
+ # pid-file directory if the application exits due to an uncaught exception
258
+ # -----
259
+ #
260
+ # === Example:
261
+ # options = {
262
+ # :backtrace => true,
263
+ # :ontop => true
264
+ # }
265
+ #
266
+ # Daemons.daemonize(options)
267
+ #
268
+ # # Server loop:
269
+ # loop {
270
+ # conn = accept_conn()
271
+ # serve(conn)
272
+ # }
273
+ #
274
+ def daemonize(options = {})
275
+ @group ||= ApplicationGroup.new(options[:app_name] || 'self', options)
276
+
277
+ @group.new_application(:mode => :none).start
278
+ end
279
+ module_function :daemonize
280
+
281
+ # Return the internal ApplicationGroup instance.
282
+ def group; @group; end
283
+ module_function :group
284
+
285
+ # Return the internal Controller instance.
286
+ def controller; @controller; end
287
+ module_function :controller
288
+ end