rq-ruby1.8 3.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/Gemfile +22 -0
  2. data/Gemfile.lock +22 -0
  3. data/INSTALL +166 -0
  4. data/LICENSE +10 -0
  5. data/Makefile +6 -0
  6. data/README +1183 -0
  7. data/Rakefile +37 -0
  8. data/TODO +24 -0
  9. data/TUTORIAL +230 -0
  10. data/VERSION +1 -0
  11. data/bin/rq +902 -0
  12. data/bin/rqmailer +865 -0
  13. data/example/a.rb +7 -0
  14. data/extconf.rb +198 -0
  15. data/gemspec.rb +40 -0
  16. data/install.rb +210 -0
  17. data/lib/rq.rb +155 -0
  18. data/lib/rq/arrayfields.rb +371 -0
  19. data/lib/rq/backer.rb +31 -0
  20. data/lib/rq/configfile.rb +82 -0
  21. data/lib/rq/configurator.rb +40 -0
  22. data/lib/rq/creator.rb +54 -0
  23. data/lib/rq/cron.rb +144 -0
  24. data/lib/rq/defaultconfig.txt +5 -0
  25. data/lib/rq/deleter.rb +51 -0
  26. data/lib/rq/executor.rb +40 -0
  27. data/lib/rq/feeder.rb +527 -0
  28. data/lib/rq/ioviewer.rb +48 -0
  29. data/lib/rq/job.rb +51 -0
  30. data/lib/rq/jobqueue.rb +947 -0
  31. data/lib/rq/jobrunner.rb +110 -0
  32. data/lib/rq/jobrunnerdaemon.rb +193 -0
  33. data/lib/rq/lister.rb +47 -0
  34. data/lib/rq/locker.rb +43 -0
  35. data/lib/rq/lockfile.rb +564 -0
  36. data/lib/rq/logging.rb +124 -0
  37. data/lib/rq/mainhelper.rb +189 -0
  38. data/lib/rq/orderedautohash.rb +39 -0
  39. data/lib/rq/orderedhash.rb +240 -0
  40. data/lib/rq/qdb.rb +733 -0
  41. data/lib/rq/querier.rb +98 -0
  42. data/lib/rq/rails.rb +80 -0
  43. data/lib/rq/recoverer.rb +28 -0
  44. data/lib/rq/refresher.rb +80 -0
  45. data/lib/rq/relayer.rb +283 -0
  46. data/lib/rq/resource.rb +22 -0
  47. data/lib/rq/resourcemanager.rb +40 -0
  48. data/lib/rq/resubmitter.rb +100 -0
  49. data/lib/rq/rotater.rb +98 -0
  50. data/lib/rq/sleepcycle.rb +46 -0
  51. data/lib/rq/snapshotter.rb +40 -0
  52. data/lib/rq/sqlite.rb +286 -0
  53. data/lib/rq/statuslister.rb +48 -0
  54. data/lib/rq/submitter.rb +113 -0
  55. data/lib/rq/toucher.rb +182 -0
  56. data/lib/rq/updater.rb +94 -0
  57. data/lib/rq/usage.rb +1222 -0
  58. data/lib/rq/util.rb +304 -0
  59. data/rdoc.sh +17 -0
  60. data/rq-ruby1.8.gemspec +120 -0
  61. data/test/.gitignore +1 -0
  62. data/test/test_rq.rb +145 -0
  63. data/white_box/crontab +2 -0
  64. data/white_box/joblist +8 -0
  65. data/white_box/killrq +18 -0
  66. data/white_box/rq_killer +27 -0
  67. metadata +208 -0
@@ -0,0 +1,31 @@
1
+ unless defined? $__rq_backer__
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
+ #
10
+ # a Backer object makes an (optionally) timestamped hot backup/snapshot of a
11
+ # queue using a timestamp of milli second resolution.
12
+ #
13
+ class Backer < MainHelper
14
+ #--{{{
15
+ def backup
16
+ #--{{{
17
+ set_q
18
+ bak = @argv.shift
19
+ bak ||= "#{ @qpath }.#{ Util::timestamp.gsub(/[:\s\.-]/,'_') }.bak"
20
+ raise "<#{ bak }> exists" if bak and test(?e, bak)
21
+ debug{ "bak <#{ bak }>" }
22
+ @q.lock{ FileUtils::cp_r @qpath, bak }
23
+ info{ "created backup <#{ bak }>" }
24
+ #--}}}
25
+ end
26
+ #--}}}
27
+ end # class Backer
28
+ #--}}}
29
+ end # module RQ
30
+ $__rq_backer__ = __FILE__
31
+ end
@@ -0,0 +1,82 @@
1
+ unless defined? $__rq_configfile__
2
+ module RQ
3
+ #--{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require 'yaml'
8
+
9
+ #
10
+ # the ConfigFile class is a thin class that munges yaml input and populates
11
+ # itself
12
+ #
13
+ class ConfigFile < ::Hash
14
+ #--{{{
15
+ DEFAULT_CONFIG = LIBDIR + 'defaultconfig.txt'
16
+
17
+ class << self
18
+ def gen_template(arg = nil)
19
+ #--{{{
20
+ @data ||= IO::read(DEFAULT_CONFIG)
21
+ case arg
22
+ when IO
23
+ arg.write @data
24
+ when String
25
+ open(arg, 'w'){|f| f.write @data}
26
+ else
27
+ STDOUT.write @data
28
+ end
29
+ self
30
+ #--}}}
31
+ end
32
+ def load_default
33
+ #--{{{
34
+ @data ||= IO::read(DEFAULT_CONFIG)
35
+ @default ||= YAML::load(munge(@data)) || {}
36
+ #--}}}
37
+ end
38
+ def any(basename, *dirnames)
39
+ #--{{{
40
+ config = nil
41
+ dirnames.each do |dirname|
42
+ path = File::join dirname, basename
43
+ if test ?e, path
44
+ config = self::new(path)
45
+ break
46
+ end
47
+ end
48
+ config || self::new('default')
49
+ #--}}}
50
+ end
51
+ def munge buf
52
+ #--{{{
53
+ buf.gsub(%r/\t/o,' ')
54
+ #--}}}
55
+ end
56
+ end
57
+ attr :path
58
+ def initialize path
59
+ #--{{{
60
+ @path = nil
61
+ yaml = nil
62
+ if path.nil? or path and path =~ /^\s*default/io
63
+ yaml = self.class.load_default
64
+ @path = 'DEFAULT'
65
+ else path
66
+ yaml = YAML::load(self.class.munge(open(path).read))
67
+ @path = path
68
+ end
69
+ self.update yaml
70
+ #--}}}
71
+ end
72
+ def to_hash
73
+ #--{{{
74
+ {}.update self
75
+ #--}}}
76
+ end
77
+ #--}}}
78
+ end # class ConfigFile
79
+ #--}}}
80
+ end # module RQ
81
+ $__rq_configfile__ = __FILE__
82
+ end
@@ -0,0 +1,40 @@
1
+ unless defined? $__rq_configurator__
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
+ #
10
+ # a Configurator adds key/value pairs to a queue's configuration. these
11
+ # key/value pairs are not currently used, but will be in a future release
12
+ #
13
+ class Configurator < MainHelper
14
+ #--{{{
15
+ #--}}}
16
+ def configure
17
+ #--{{{
18
+ set_q
19
+ attributes = {}
20
+ unless @argv.empty?
21
+ kv_pat = %r/^\s*([^\s]+)\s*=+\s*([^\s]+)\s*$/o
22
+ @q.transaction do
23
+ @argv.each do |arg|
24
+ match = kv_pat.match arg
25
+ if match
26
+ k, v = match[1], match[2]
27
+ @q[k] = v
28
+ end
29
+ end
30
+ attributes = @q.attributes
31
+ end
32
+ end
33
+ y attributes
34
+ #--}}}
35
+ end
36
+ end # class Configurator
37
+ #--}}}
38
+ end # module RQ
39
+ $__rq_configurator__ = __FILE__
40
+ end
@@ -0,0 +1,54 @@
1
+ unless defined? $__rq_creator__
2
+ module RQ
3
+ #--{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require 'fileutils'
8
+ require LIBDIR + 'mainhelper'
9
+
10
+ #
11
+ # a queue is a directory
12
+ #
13
+ # the Creator class is responsible for initializing the queue directory and
14
+ # all supporting files. these include:
15
+ # * the sqlite database (binary)
16
+ # * the sqlite database schema description file (text)
17
+ # * the empty sentinel file used for locking (text - empty)
18
+ #
19
+ # it is an error to attempt to initialize a queue which already exists
20
+ #
21
+ class Creator < MainHelper
22
+ #--{{{
23
+ def create
24
+ #--{{{
25
+ raise "q <#{ @qpath }> exists!" if test ?e, @qpath
26
+ @q = JobQueue::create @qpath, 'logger' => @logger
27
+
28
+ unless quiet?
29
+ puts '---'
30
+ puts "q: #{ @q.path }"
31
+ puts "db: #{ @q.db.path }"
32
+ puts "schema: #{ @q.db.schema }"
33
+ puts "lock: #{ @q.db.lockfile }"
34
+ puts "bin: #{ @q.bin }"
35
+ puts "stdin: #{ @q.stdin }"
36
+ puts "stdout: #{ @q.stdout }"
37
+ puts "stderr: #{ @q.stderr }"
38
+ puts "data: #{ @q.data }"
39
+ end
40
+
41
+ rqmailer = File.join(File.dirname(@program), 'rqmailer')
42
+ if test ?e, rqmailer
43
+ FileUtils.cp rqmailer, @q.bin
44
+ end
45
+
46
+ self
47
+ #--}}}
48
+ end
49
+ #--}}}
50
+ end # class Creator
51
+ #--}}}
52
+ end # module RQ
53
+ $__rq_creator__ = __FILE__
54
+ end
@@ -0,0 +1,144 @@
1
+ unless defined? $__rq_cron__
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
+ #
10
+ # a class for managing crontab entries and to start/stop rq
11
+ #
12
+ class Cron < MainHelper
13
+ #--{{{
14
+ def initialize *a, &b
15
+ #--{{{
16
+ super
17
+ ruby = Util::which_ruby
18
+ this = Util::realpath( File.expand_path( $0 ) )
19
+ q = qpath
20
+
21
+ @cmd = "#{ ruby } #{ this } #{ q }"
22
+ @md5 = lambda{|mode| Digest::MD5::hexdigest "#{ @cmd } #{ mode }" }
23
+ #--}}}
24
+ end
25
+ def cron
26
+ #--{{{
27
+ which = @argv.shift || 'start'
28
+ which = which.strip.downcase
29
+ #abort "arg not add|start|shutdown|stop" unless %w( start shutdown stop ).include? which
30
+ msg = "cron_#{ which }"
31
+ begin
32
+ send msg
33
+ rescue NoMethodError
34
+ raise ArgumentError, which
35
+ end
36
+ self
37
+ #--}}}
38
+ end
39
+ def cron_add
40
+ #--{{{
41
+ lines = `crontab -l`.split "\n"
42
+
43
+ found = nil
44
+
45
+ re = %r/###\s*md5:#{ @md5[:start] }/
46
+
47
+ lines.each do |line|
48
+ line.strip!
49
+ next if line[ %r/^\s*#/ ]
50
+ min, hour, dom, mon, dow, entry = line.split %r/\s+/, 6
51
+ next unless entry
52
+ entry.strip!
53
+ entry.gsub! %r/#[^'"]$/, ''
54
+ entry.strip!
55
+ found = re.match entry
56
+ break if found
57
+ end
58
+
59
+ unless found
60
+ opts = @options.map{|kv| "'--#{ kv.join('=') }'" }.join(' ')
61
+ entries = [
62
+ "*/15 * * * * #{ @cmd } start #{ opts } ###md5:#{ @md5[:start] }\n",
63
+ "0 0 * * * #{ @cmd } rotate ###md5:#{ @md5[:start] }\n",
64
+ ]
65
+ tmp = Tempfile::new Process::pid.to_s
66
+ lines.each{|line| tmp << "#{ line }\n"}
67
+ entries.each do |entry|
68
+ tmp << entry
69
+ end
70
+ tmp.close
71
+ system("crontab #{ tmp.path }") or abort("failed to cronify!")
72
+ tmp.close!
73
+ entries.each do |entry|
74
+ puts entry
75
+ end
76
+ end
77
+ #--}}}
78
+ end
79
+ def cron_tab
80
+ #--{{{
81
+ opts = @options.map{|kv| "'--#{ kv.join('=') }'" }.join(' ')
82
+ entries = [
83
+ "*/15 * * * * #{ @cmd } start #{ opts } ###md5:#{ @md5[:start] }\n",
84
+ "0 0 * * * #{ @cmd } rotate ###md5:#{ @md5[:start] }\n",
85
+ ]
86
+ puts entries
87
+ #--}}}
88
+ end
89
+ def cron_start
90
+ #--{{{
91
+ cron_add
92
+ #main.start
93
+ #--}}}
94
+ end
95
+ def cron_delete
96
+ #--{{{
97
+ lines = `crontab -l`.split "\n"
98
+
99
+ re = %r/###\s*md5:(#{ @md5[:start] })/
100
+ found = []
101
+
102
+ lines.each_with_index do |line, idx|
103
+ line.strip!
104
+ next if line[ %r/^\s*#/ ]
105
+ min, hour, dom, mon, dow, entry = line.split %r/\s+/, 6
106
+ next unless entry
107
+ entry.strip!
108
+ entry.gsub! %r/#[^'"]$/, ''
109
+ entry.strip!
110
+ found << idx if(re.match entry)
111
+ end
112
+
113
+ p found
114
+
115
+ unless found.empty?
116
+ deleted = []
117
+ found.each{|idx| deleted << lines[idx]; lines.delete_at(idx)}
118
+ tmp = Tempfile::new Process::pid.to_s
119
+ lines.each{|line| tmp << "#{ line }\n"}
120
+ tmp.close
121
+ system("crontab #{ tmp.path }") or abort("failed to cronify!")
122
+ tmp.close!
123
+ puts deleted
124
+ end
125
+ #--}}}
126
+ end
127
+ def cron_shutdown
128
+ #--{{{
129
+ cron_delete
130
+ main.shutdown
131
+ #--}}}
132
+ end
133
+ def cron_stop
134
+ #--{{{
135
+ cron_delete
136
+ main.stop
137
+ #--}}}
138
+ end
139
+ #--}}}
140
+ end # class Cron
141
+ #--}}}
142
+ end # module RQ
143
+ $__rq_cron__ = __FILE__
144
+ end
@@ -0,0 +1,5 @@
1
+ #
2
+ # rq config
3
+ #
4
+
5
+ key : value
@@ -0,0 +1,51 @@
1
+ unless defined? $__rq_deleter__
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
+ #
10
+ # the Deleter class reads the command line, stdin, or an infile to determine
11
+ # the job ids (jid) of jobs to be deleted from the queue. jids may be
12
+ # specified on the command line or parsed from stdin or the infile. any
13
+ # input line matching 'jid : number' or 'number' is taken to be a line
14
+ # indicating a jid to delete.
15
+ #
16
+ class Deleter < MainHelper
17
+ #--{{{
18
+ def delete
19
+ #--{{{
20
+ set_q
21
+
22
+ whats = @argv
23
+
24
+ if whats.empty? and stdin?
25
+ pat = %r/^(?:\s*jid\s*:)?\s*(\d+)\s*$|^\s*(all)\s*$/io
26
+ while((line = stdin.gets))
27
+ match = pat.match line
28
+ next unless match
29
+ whats << (match[1] || match[2])
30
+ end
31
+ end
32
+
33
+ #whats.map!{|what| what =~ %r/^\s*\d+\s*$/o ? Integer(what) : what}
34
+
35
+ raise "nothing to delete" if whats.empty?
36
+
37
+ if @options['quiet']
38
+ @q.delete(*whats)
39
+ else
40
+ @q.delete(*whats, &dumping_yaml_tuples)
41
+ end
42
+
43
+ @q.vacuum
44
+ #--}}}
45
+ end
46
+ #--}}}
47
+ end # class Deleter
48
+ #--}}}
49
+ end # module RQ
50
+ $__rq_deleter__ = __FILE__
51
+ end
@@ -0,0 +1,40 @@
1
+ unless defined? $__rq_executor__
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
+ #
10
+ # the Executor is for expert use only and executes arbitrary sql on the
11
+ # queue's db. the reason one should not do this directly with the sqlite
12
+ # command line program is that it will not respect the locking subsystem
13
+ # used in RQ - the Executor method will
14
+ #
15
+ class Executor < MainHelper
16
+ #--{{{
17
+ def execute
18
+ #--{{{
19
+ set_q
20
+ sql = @argv.join ' '
21
+ if sql.empty? and stdin?
22
+ debug{ "reading sql from stdin" }
23
+ while((buf = stdin.gets))
24
+ buf.strip!
25
+ buf.gsub! %r/#.*$/o, ''
26
+ next if buf.empty?
27
+ sql << "#{ buf } "
28
+ end
29
+ end
30
+ abort "no sql to execute" if sql.empty?
31
+ @q.qdb.transaction_retries = 0
32
+ @q.transaction{@q.execute(sql, &dumping_yaml_tuples)}
33
+ #--}}}
34
+ end
35
+ #--}}}
36
+ end # class Executor
37
+ #--}}}
38
+ end # module RQ
39
+ $__rq_executor__ = __FILE__
40
+ end