rq 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,63 @@
1
+ unless defined? $__rq_jobrunner__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require 'drb/drb'
8
+
9
+ require LIBDIR + 'util'
10
+
11
+ class JobRunner
12
+ #{{{
13
+ include DRbUndumped
14
+ attr :job
15
+ attr :jid
16
+ attr :cid
17
+ attr :shell
18
+ attr :command
19
+ alias pid cid
20
+ def initialize job
21
+ #{{{
22
+ @job = job
23
+ @jid = job['jid']
24
+ @command = job['command']
25
+ @shell = job['shell'] || 'bash'
26
+ @r,@w = IO::pipe
27
+ @env = {}
28
+ @job.fields.each do |field|
29
+ key = "RQ_#{ field }".upcase.gsub(%r/\s+/,'_')
30
+ val = @job[field]
31
+ @env[key] = "#{ val }"
32
+ end
33
+ @cid =
34
+ Util::fork do
35
+ begin
36
+ @env.each{|k,v| ENV[k] = v}
37
+ ENV['RQ_PID'] = "#{ $$ }"
38
+ @w.close
39
+ STDIN.reopen @r
40
+ if File::basename(@shell) == 'bash' || File::basename(@shell) == 'sh'
41
+ exec [@shell, "__rq_job__#{ @jid }__#{ File::basename(@shell) }__"], '--login'
42
+ else
43
+ exec [@shell, "__rq_job__#{ @jid }__#{ File::basename(@shell) }__"], '-l'
44
+ end
45
+ rescue Exception => e
46
+ STDERR.puts(Util::errmsg(e))
47
+ end
48
+ end
49
+ @r.close
50
+ #}}}
51
+ end
52
+ def run
53
+ #{{{
54
+ @w.puts @command
55
+ @w.close
56
+ #}}}
57
+ end
58
+ #}}}
59
+ end # class JobRunner
60
+ #}}}
61
+ end # module RQ
62
+ $__rq_jobrunner__ = __FILE__
63
+ end
@@ -0,0 +1,179 @@
1
+ unless defined? $__rq_jobrunnerdaemon__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require 'drb/drb'
8
+ require 'fileutils'
9
+ require 'tmpdir'
10
+ require 'tempfile'
11
+
12
+ require LIBDIR + 'job'
13
+ require LIBDIR + 'jobrunner'
14
+
15
+ class JobRunnerDaemon
16
+ #{{{
17
+ include Logging
18
+
19
+ class << self
20
+ #{{{
21
+ def daemon(*a,&b)
22
+ #{{{
23
+ jrd = new(*a, &b)
24
+
25
+ r, w = IO::pipe
26
+
27
+ unless((pid = fork)) # child
28
+ $0 = "#{ self }".gsub(%r/[^a-zA-Z]+/,'_').downcase
29
+ begin
30
+ r.close
31
+ n = 0
32
+ uri = nil
33
+ socket = nil
34
+
35
+ 42.times do
36
+ begin
37
+ s = "%s/%s_%s_%s_%s" %
38
+ [Dir::tmpdir, File::basename($0), Process::ppid, n, rand(42)]
39
+ u = "drbunix://#{ s }"
40
+ DRb::start_service u, jrd
41
+ socket = s
42
+ uri = u
43
+ rescue Errno::EADDRINUSE
44
+ n += 1
45
+ end
46
+ end
47
+
48
+ if socket and uri
49
+ w.write socket
50
+ w.close
51
+ pid = Process::pid
52
+ ppid = Process::ppid
53
+ cur = Thread::current
54
+ Thread::new(pid, ppid, cur) do |pid, ppid, cur|
55
+ loop do
56
+ begin
57
+ Process::kill 0, ppid
58
+ sleep 42
59
+ rescue
60
+ cur.raise "parent <#{ ppid }> died unexpectedly"
61
+ end
62
+ end
63
+ end
64
+ DRb::thread.join
65
+ else
66
+ w.close
67
+ end
68
+ ensure
69
+ exit!
70
+ end
71
+ else # parent
72
+ w.close
73
+ socket = r.read
74
+ r.close
75
+
76
+ if socket and File::exist?(socket)
77
+ at_exit{ FileUtils::rm_f socket }
78
+ uri = "drbunix://#{ socket }"
79
+ DRb::start_service 'druby://localhost:0', nil
80
+ jrd = DRbObject::new nil, uri
81
+ jrd.pid = pid
82
+ jrd.uri = uri
83
+ else
84
+ raise "failed to start job runner daemon"
85
+ end
86
+ end
87
+
88
+ return jrd
89
+ #}}}
90
+ end
91
+ #}}}
92
+ end
93
+ attr :runners
94
+ attr :pid, true
95
+ attr :uri, true
96
+ def initialize
97
+ #{{{
98
+ @runners = {}
99
+ @uri = nil
100
+ @pid = Process::pid
101
+ #}}}
102
+ end
103
+ def runner job
104
+ #{{{
105
+ r = nil
106
+ retried = false
107
+ begin
108
+ r = JobRunner::new job
109
+ rescue Errno::ENOMEM, Errno::EAGAIN
110
+ GC::start
111
+ unless retried
112
+ retried = true
113
+ retry
114
+ else
115
+ raise
116
+ end
117
+ end
118
+ @runners[r.pid] = r
119
+ r
120
+ #}}}
121
+ end
122
+ def wait
123
+ #{{{
124
+ pid = Process::wait
125
+ @runners.delete pid
126
+ pid
127
+ #}}}
128
+ end
129
+ def wait2
130
+ #{{{
131
+ pid, status = Process::wait2
132
+ @runners.delete pid
133
+ [pid, status]
134
+ #}}}
135
+ end
136
+ def waitpid pid = -1, flags = 0
137
+ #{{{
138
+ pid = pid.pid if pid.respond_to? 'pid'
139
+ pid = Process::waitpid pid, flags
140
+ @runners.delete pid
141
+ pid
142
+ #}}}
143
+ end
144
+ def waitpid2 pid = -1, flags = 0
145
+ #{{{
146
+ pid = pid.pid if pid.respond_to? 'pid'
147
+ pid, status = Process::waitpid2 pid, flags
148
+ @runners.delete pid
149
+ [pid, status]
150
+ #}}}
151
+ end
152
+ def shutdown
153
+ #{{{
154
+ @death =
155
+ Thread::new do
156
+ begin
157
+ while not @runners.empty?
158
+ pid = Process::wait
159
+ @runners.delete pid
160
+ end
161
+ ensure
162
+ sleep 4.2
163
+ DRb::thread.kill
164
+ Thread::main exit!
165
+ end
166
+ end
167
+ #}}}
168
+ end
169
+ def install_signal_handlers
170
+ #{{{
171
+ %w(TERM INT HUP).each{|sig| trap sig, 'SIG_IGN'}
172
+ #}}}
173
+ end
174
+ #}}}
175
+ end # class JobRunnerDaemon
176
+ #}}}
177
+ end # module RQ
178
+ $__rq_jobrunnerdaemon__ = __FILE__
179
+ end
@@ -0,0 +1,22 @@
1
+ unless defined? $__rq_lister__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require LIBDIR + 'mainhelper'
8
+
9
+ class Lister < MainHelper
10
+ #{{{
11
+ def list
12
+ #{{{
13
+ set_q
14
+ @q.list(*@argv)
15
+ #}}}
16
+ end
17
+ #}}}
18
+ end # class Lister
19
+ #}}}
20
+ end # module RQ
21
+ $__rq_lister__ = __FILE__
22
+ end
@@ -0,0 +1,37 @@
1
+ unless defined? $__rq_locker__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require LIBDIR + 'util'
8
+ require LIBDIR + 'locker'
9
+
10
+ class Locker < MainHelper
11
+ #{{{
12
+ def lock
13
+ #{{{
14
+ set_q
15
+ ltype = @argv.shift
16
+ debug{ "ltype <#{ ltype }>" }
17
+ read_only =
18
+ case ltype
19
+ when /^\s*r(?:ead)?|^\s*sh(?:ared)?/io
20
+ true
21
+ when /^\s*w(?:rite)?|^\s*ex(?:clusive)?/io
22
+ false
23
+ else
24
+ raise "lock type must be one of (r)ead|(sh)ared|(w)rite|(ex)clusive, not <#{ ltype }>"
25
+ end
26
+ cmd = @argv.join(' ').strip
27
+ raise "no command given for lock type <#{ ltype }>" if cmd.empty?
28
+ debug{ "cmd <#{ cmd }>" }
29
+ @q.lock(:read_only => read_only){ Util::system cmd }
30
+ #}}}
31
+ end
32
+ #}}}
33
+ end # class Locker
34
+ #}}}
35
+ end # module RQ
36
+ $__rq_locker__ = __FILE__
37
+ end
@@ -0,0 +1,117 @@
1
+ unless defined? $__rq_logging__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require "logger"
8
+
9
+ require LIBDIR + 'util'
10
+ #
11
+ # module which adds logging methods to classes
12
+ #
13
+ module Logging
14
+ #{{{
15
+ #
16
+ # a module that adds an accessor to Logging objects in ored to fix a bug where
17
+ # not all logging devices are put into sync mode, resulting in improper log
18
+ # rolling. this is a hack.
19
+ #
20
+ module LoggerExt
21
+ #{{{
22
+ attr :logdev
23
+ #}}}
24
+ end # module LoggerExt
25
+ #
26
+ # implementations of the methods shared by both classes and objects of classes
27
+ # which include Logging
28
+ #
29
+ module LogMethods
30
+ #{{{
31
+ def logger
32
+ #{{{
33
+ if defined?(@logger) and @logger
34
+ @logger
35
+ else
36
+ if Class === self
37
+ @logger = self.default_logger
38
+ else
39
+ @logger = self::class::logger
40
+ end
41
+ raise "@logger is undefined!" unless defined?(@logger) and @logger
42
+ @logger
43
+ end
44
+ #}}}
45
+ end
46
+ def logger= log
47
+ #{{{
48
+ @logger = log
49
+ @logger.extend LoggerExt
50
+ @logger.logdev.dev.sync = true
51
+ @logger
52
+ #}}}
53
+ end
54
+ def debug(*args, &block); logger.debug(*args, &block); end
55
+ def info(*args, &block); logger.info(*args, &block) ; end
56
+ def warn(*args, &block); logger.warn(*args, &block) ; end
57
+ def error(*args, &block); logger.error(*args, &block); end
58
+ def fatal(*args, &block); logger.fatal(*args, &block); end
59
+ def logerr e
60
+ #{{{
61
+ if logger.debug?
62
+ error{ Util::errmsg e }
63
+ else
64
+ error{ Util::emsg e }
65
+ end
66
+ #}}}
67
+ end
68
+ #}}}
69
+ end # module LogMethods
70
+ EOL = "\n"
71
+ DIV0 = ("." * 79) << EOL
72
+ DIV1 = ("-" * 79) << EOL
73
+ DIV2 = ("=" * 79) << EOL
74
+ DIV3 = ("#" * 79) << EOL
75
+ SEC0 = ("." * 16) << EOL
76
+ SEC1 = ("-" * 16) << EOL
77
+ SEC2 = ("=" * 16) << EOL
78
+ SEC3 = ("#" * 16) << EOL
79
+ class << self
80
+ #{{{
81
+ def append_features c
82
+ #{{{
83
+ ret = super
84
+ c.extend LogMethods
85
+ class << c
86
+ def default_logger
87
+ #{{{
88
+ if defined?(@default_logger) and @default_logger
89
+ @default_logger
90
+ else
91
+ self.default_logger = Logger.new STDOUT
92
+ @default_logger.debug{ "<#{ self }> using default logger"}
93
+ @default_logger
94
+ end
95
+ #}}}
96
+ end
97
+ def default_logger= log
98
+ #{{{
99
+ @default_logger = log
100
+ @default_logger.extend LoggerExt
101
+ @default_logger.logdev.dev.sync = true
102
+ @default_logger
103
+ #}}}
104
+ end
105
+ end
106
+ ret
107
+ #}}}
108
+ end
109
+ #}}}
110
+ end
111
+ include LogMethods
112
+ #}}}
113
+ end # module Logging
114
+ #}}}
115
+ end # module rq
116
+ $__rq_logging__ = __FILE__
117
+ end
@@ -0,0 +1,53 @@
1
+ unless defined? $__rq_mainhelper__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require LIBDIR + 'util'
8
+ require LIBDIR + 'logging'
9
+
10
+ class MainHelper
11
+ #{{{
12
+ include Util
13
+ include Logging
14
+ attr :main
15
+ attr :logger
16
+ attr :argv
17
+ attr :env
18
+ attr :cmd
19
+ attr :options
20
+ attr :qpath
21
+ attr :mode
22
+ attr :q
23
+ def initialize main
24
+ #{{{
25
+ @main = main
26
+ @logger = main.logger
27
+ @argv = main.argv
28
+ @env = main.env
29
+ @cmd = main.cmd
30
+ @options = main.options
31
+ @qpath = main.qpath
32
+ @mode = main.mode
33
+ @q = nil
34
+ #}}}
35
+ end
36
+ def set_q
37
+ #{{{
38
+ raise "q <#{ @qpath }> does not exist" unless test ?d, @qpath
39
+ @q = JobQueue::new @qpath, 'logger' => @logger
40
+ if @options['snapshot']
41
+ ss = "#{ $0 }_#{ Process::pid }_#{ Thread::current.id.abs }_#{ rand Time::now.to_i }".gsub(%r|/|o,'_')
42
+ qtmp = File::join Dir::tmpdir, ss
43
+ @q = @q.snapshot qtmp, @options['retries']
44
+ at_exit{ FileUtils::rm_rf qtmp }
45
+ end
46
+ #}}}
47
+ end
48
+ #}}}
49
+ end # class MainHelper
50
+ #}}}
51
+ end # module RQ
52
+ $__rq_mainhelper__ = __FILE__
53
+ end