rq-ruby1.8 3.4.3

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.
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