rsched 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,284 +1,5 @@
1
- require 'thread'
2
- require 'time'
3
-
4
- module RSched
5
-
6
-
7
- class Lock
8
- def initialize(hostname, timeout)
9
- end
10
-
11
- # acquired=token, locked=false, finished=nil
12
- def aquire(ident, time)
13
- end
14
-
15
- def release(token)
16
- end
17
-
18
- def finish(token)
19
- end
20
-
21
- def delete_before(ident, time)
22
- end
23
- end
24
-
25
-
26
- class DBLock < Lock
27
- def initialize(hostname, timeout, uri, user, pass)
28
- require 'dbi'
29
- @hostname = hostname
30
- @timeout = timeout
31
- @db = DBI.connect(uri, user, pass)
32
- init_db
33
- end
34
-
35
- def init_db
36
- sql = ''
37
- sql << 'CREATE TABLE IF NOT EXISTS rsched ('
38
- sql << ' ident VARCHAR(256) NOT NULL,'
39
- sql << ' time INT NOT NULL,'
40
- sql << ' host VARCHAR(256),'
41
- sql << ' timeout INT,'
42
- sql << ' finish INT,'
43
- sql << ' PRIMARY KEY (ident, time));'
44
- @db.execute(sql)
45
- end
46
-
47
- def aquire(ident, time)
48
- now = Time.now.to_i
49
- if try_insert(ident, time, now) || try_update(ident, time, now)
50
- return [ident, time]
51
- elsif check_finished(ident, time)
52
- return nil
53
- else
54
- return false
55
- end
56
- end
57
-
58
- def release(token)
59
- ident, time = *token
60
- n = @db.do('UPDATE rsched SET timeout=? WHERE ident = ? AND time = ? AND host = ?;',
61
- 0, ident, time, @hostname)
62
- return n > 0
63
- end
64
-
65
- def finish(token)
66
- ident, time = *token
67
- now = Time.now.to_i
68
- n = @db.do('UPDATE rsched SET finish=? WHERE ident = ? AND time = ? AND host = ?;',
69
- now, ident, time, @hostname)
70
- return n > 0
71
- end
72
-
73
- def delete_before(ident, time)
74
- @db.do('DELETE FROM rsched WHERE ident = ? AND time < ? AND finish IS NOT NULL;', ident, time)
75
- end
76
-
77
- private
78
- def try_insert(ident, time, now)
79
- n = @db.do('INSERT INTO rsched (ident, time, host, timeout) VALUES (?, ?, ?, ?);',
80
- ident, time, @hostname, now+@timeout)
81
- return n > 0
82
- rescue # TODO unique error
83
- return false
84
- end
85
-
86
- def try_update(ident, time, now)
87
- n = @db.do('UPDATE rsched SET host=?, timeout=? WHERE ident = ? AND time = ? AND finish IS NULL AND (timeout < ? OR host = ?);',
88
- @hostname, now+@timeout, ident, time, now, @hostname)
89
- return n > 0
90
- end
91
-
92
- def check_finished(ident, time)
93
- x = @db.select_one('SELECT finish FROM rsched WHERE ident = ? AND time = ? AND finish IS NOT NULL;',
94
- ident, time)
95
- return x != nil
96
- end
97
- end
98
-
99
-
100
- class Engine
101
- class Sched
102
- def initialize(cron, action, sched_start, from=Time.now.to_i, to=Time.now.to_i)
103
- @tab = CronSpec::CronSpecification.new(cron)
104
- @action = action
105
- @sched_start = sched_start
106
- @queue = []
107
- @last_time = from
108
- sched(to)
109
- end
110
-
111
- attr_reader :queue, :action
112
-
113
- def sched(now)
114
- while @last_time <= now
115
- t = Time.at(@last_time).utc
116
- if @tab.is_specification_in_effect?(t)
117
- time = create_time_key(t)
118
- @queue << time if time >= @sched_start
119
- end
120
- @last_time += 60
121
- end
122
- @queue.uniq!
123
- end
124
-
125
- private
126
- if Time.respond_to?(:strptime)
127
- def create_time_key(t)
128
- Time.strptime(t.strftime('%Y%m%d%H%M00UTC'), '%Y%m%d%H%M%S%Z').to_i
129
- end
130
- else
131
- require 'date'
132
- def create_time_key(t)
133
- Time.parse(DateTime.strptime(t.strftime('%Y%m%d%H%M00UTC'), '%Y%m%d%H%M%S').to_s).to_i
134
- end
135
- end
136
- end
137
-
138
- def initialize(lock, conf)
139
- require 'cron-spec'
140
- @lock = lock
141
- @resume = conf[:resume]
142
- @delay = conf[:delay]
143
- @interval = conf[:interval]
144
- @delete = conf[:delete]
145
- @sched_start = conf[:from] || 0
146
- @finished = false
147
- @ss = {}
148
-
149
- @mutex = Mutex.new
150
- @cond = ConditionVariable.new
151
- end
152
-
153
- # {cron => (ident,action)}
154
- def set_sched(ident, action, cron)
155
- now = Time.now.to_i
156
- @ss[ident] = Sched.new(cron, action, @sched_start, now-@resume, now-@delay)
157
- end
158
-
159
- def run(run_proc)
160
- until @finished
161
- one = false
162
-
163
- now = Time.now.to_i - @delay
164
- @ss.each_pair {|ident,s|
165
-
166
- s.sched(now)
167
- s.queue.delete_if {|time|
168
- next if @finished
169
-
170
- x = @lock.aquire(ident, time)
171
- case x
172
- when nil
173
- # already finished
174
- true
175
-
176
- when false
177
- # not finished but already locked
178
- false
179
-
180
- else
181
- one = true
182
- if process(ident, time, s.action, run_proc)
183
- # success
184
- @lock.finish(x)
185
- try_delete(ident)
186
- true
187
- else
188
- # fail
189
- @lock.release(x)
190
- false
191
- end
192
- end
193
- }
194
-
195
- break if @finished
196
- }
197
-
198
- return if @finished
199
-
200
- unless one
201
- cond_wait(@interval)
202
- end
203
-
204
- end
205
- end
206
-
207
- def shutdown
208
- @finished = true
209
- @mutex.synchronize {
210
- @cond.broadcast
211
- }
212
- end
213
-
214
- private
215
- if ConditionVariable.new.method(:wait).arity == 1
216
- require 'timeout'
217
- def cond_wait(sec)
218
- @mutex.synchronize {
219
- Timeout.timeout(sec) {
220
- @cond.wait(@mutex)
221
- }
222
- }
223
- rescue Timeout::Error
224
- end
225
- else
226
- def cond_wait(sec)
227
- @mutex.synchronize {
228
- @cond.wait(@mutex, sec)
229
- }
230
- end
231
- end
232
-
233
- def process(ident, time, action, run_proc)
234
- begin
235
- run_proc.call(ident, time, action)
236
- return true
237
- rescue
238
- puts "failed ident=#{ident} time=#{time}: #{$!}"
239
- $!.backtrace.each {|bt|
240
- puts " #{bt}"
241
- }
242
- return false
243
- end
244
- end
245
-
246
- def try_delete(ident)
247
- @lock.delete_before(ident, Time.now.to_i-@delete)
248
- end
249
- end
250
-
251
-
252
- class ExecRunner
253
- def initialize(cmd)
254
- @cmd = cmd + ' ' + ARGV.map {|a| Shellwords.escape(a) }.join(' ')
255
- @iobuf = ''
256
- end
257
-
258
- def call(ident, time, action)
259
- message = [ident, time, action].join("\t")
260
- IO.popen(@cmd, "r+") {|io|
261
- io.write(message) rescue nil
262
- io.close_write
263
- begin
264
- while true
265
- io.sysread(1024, @iobuf)
266
- print @iobuf
267
- end
268
- rescue EOFError
269
- end
270
- }
271
- if $?.to_i != 0
272
- raise "Command failed"
273
- end
274
- end
275
- end
276
-
277
-
278
- end # module RSched
279
-
280
-
281
1
  require 'optparse'
2
+ require 'rsched/engine'
282
3
 
283
4
  op = OptionParser.new
284
5
 
@@ -0,0 +1,78 @@
1
+
2
+ module RSched
3
+
4
+
5
+ class DBLock < Lock
6
+ def initialize(hostname, timeout, uri, user, pass)
7
+ require 'dbi'
8
+ @hostname = hostname
9
+ @timeout = timeout
10
+ @db = DBI.connect(uri, user, pass)
11
+ init_db
12
+ end
13
+
14
+ def init_db
15
+ sql = ''
16
+ sql << 'CREATE TABLE IF NOT EXISTS rsched ('
17
+ sql << ' ident VARCHAR(256) NOT NULL,'
18
+ sql << ' time INT NOT NULL,'
19
+ sql << ' host VARCHAR(256),'
20
+ sql << ' timeout INT,'
21
+ sql << ' finish INT,'
22
+ sql << ' PRIMARY KEY (ident, time));'
23
+ @db.execute(sql)
24
+ end
25
+
26
+ def acquire(ident, time, now=Time.now.to_i)
27
+ if try_insert(ident, time, now) || try_update(ident, time, now)
28
+ return [ident, time]
29
+ elsif check_finished(ident, time)
30
+ return nil
31
+ else
32
+ return false
33
+ end
34
+ end
35
+
36
+ def release(token)
37
+ ident, time = *token
38
+ n = @db.do('UPDATE rsched SET timeout=? WHERE ident = ? AND time = ? AND host = ?;',
39
+ 0, ident, time, @hostname)
40
+ return n > 0
41
+ end
42
+
43
+ def finish(token, now=Time.now.to_i)
44
+ ident, time = *token
45
+ n = @db.do('UPDATE rsched SET finish=? WHERE ident = ? AND time = ? AND host = ?;',
46
+ now, ident, time, @hostname)
47
+ return n > 0
48
+ end
49
+
50
+ def delete_before(ident, time)
51
+ @db.do('DELETE FROM rsched WHERE ident = ? AND time < ? AND finish IS NOT NULL;', ident, time)
52
+ end
53
+
54
+ private
55
+ def try_insert(ident, time, now)
56
+ n = @db.do('INSERT INTO rsched (ident, time, host, timeout) VALUES (?, ?, ?, ?);',
57
+ ident, time, @hostname, now+@timeout)
58
+ return n > 0
59
+ rescue # TODO unique error
60
+ return false
61
+ end
62
+
63
+ def try_update(ident, time, now)
64
+ n = @db.do('UPDATE rsched SET host=?, timeout=? WHERE ident = ? AND time = ? AND finish IS NULL AND (timeout < ? OR host = ?);',
65
+ @hostname, now+@timeout, ident, time, now, @hostname)
66
+ return n > 0
67
+ end
68
+
69
+ def check_finished(ident, time)
70
+ x = @db.select_one('SELECT finish FROM rsched WHERE ident = ? AND time = ? AND finish IS NOT NULL;',
71
+ ident, time)
72
+ return x != nil
73
+ end
74
+ end
75
+
76
+
77
+ end
78
+
@@ -0,0 +1,186 @@
1
+ require 'thread'
2
+ require 'time'
3
+ require 'rsched/lock'
4
+
5
+ module RSched
6
+
7
+
8
+ class Engine
9
+ class Sched
10
+ def initialize(cron, action, sched_start, from=Time.now.to_i, to=Time.now.to_i)
11
+ require 'cron-spec'
12
+ @tab = CronSpec::CronSpecification.new(cron)
13
+ @action = action
14
+ @sched_start = sched_start
15
+ @queue = []
16
+ @last_time = from
17
+ sched(to)
18
+ end
19
+
20
+ attr_reader :queue, :action
21
+
22
+ def sched(now)
23
+ while @last_time <= now
24
+ t = Time.at(@last_time).utc
25
+ if @tab.is_specification_in_effect?(t)
26
+ time = create_time_key(t)
27
+ @queue << time if time >= @sched_start
28
+ end
29
+ @last_time += 60
30
+ end
31
+ @queue.uniq!
32
+ end
33
+
34
+ private
35
+ if Time.respond_to?(:strptime)
36
+ def create_time_key(t)
37
+ Time.strptime(t.strftime('%Y%m%d%H%M00UTC'), '%Y%m%d%H%M%S%Z').to_i
38
+ end
39
+ else
40
+ require 'date'
41
+ def create_time_key(t)
42
+ Time.parse(DateTime.strptime(t.strftime('%Y%m%d%H%M00UTC'), '%Y%m%d%H%M%S').to_s).to_i
43
+ end
44
+ end
45
+ end
46
+
47
+ def initialize(lock, conf)
48
+ @lock = lock
49
+ @resume = conf[:resume]
50
+ @delay = conf[:delay]
51
+ @interval = conf[:interval]
52
+ @delete = conf[:delete]
53
+ @sched_start = conf[:from] || 0
54
+ @finished = false
55
+ @ss = {}
56
+
57
+ @mutex = Mutex.new
58
+ @cond = ConditionVariable.new
59
+ end
60
+
61
+ # {cron => (ident,action)}
62
+ def set_sched(ident, action, cron)
63
+ now = Time.now.to_i
64
+ @ss[ident] = Sched.new(cron, action, @sched_start, now-@resume, now-@delay)
65
+ end
66
+
67
+ def run(run_proc)
68
+ until @finished
69
+ one = false
70
+
71
+ now = Time.now.to_i - @delay
72
+ @ss.each_pair {|ident,s|
73
+
74
+ s.sched(now)
75
+ s.queue.delete_if {|time|
76
+ next if @finished
77
+
78
+ x = @lock.acquire(ident, time)
79
+ case x
80
+ when nil
81
+ # already finished
82
+ true
83
+
84
+ when false
85
+ # not finished but already locked
86
+ false
87
+
88
+ else
89
+ one = true
90
+ if process(ident, time, s.action, run_proc)
91
+ # success
92
+ @lock.finish(x)
93
+ try_delete(ident)
94
+ true
95
+ else
96
+ # fail
97
+ @lock.release(x)
98
+ false
99
+ end
100
+ end
101
+ }
102
+
103
+ break if @finished
104
+ }
105
+
106
+ return if @finished
107
+
108
+ unless one
109
+ cond_wait(@interval)
110
+ end
111
+
112
+ end
113
+ end
114
+
115
+ def shutdown
116
+ @finished = true
117
+ @mutex.synchronize {
118
+ @cond.broadcast
119
+ }
120
+ end
121
+
122
+ private
123
+ if ConditionVariable.new.method(:wait).arity == 1
124
+ require 'timeout'
125
+ def cond_wait(sec)
126
+ @mutex.synchronize {
127
+ Timeout.timeout(sec) {
128
+ @cond.wait(@mutex)
129
+ }
130
+ }
131
+ rescue Timeout::Error
132
+ end
133
+ else
134
+ def cond_wait(sec)
135
+ @mutex.synchronize {
136
+ @cond.wait(@mutex, sec)
137
+ }
138
+ end
139
+ end
140
+
141
+ def process(ident, time, action, run_proc)
142
+ begin
143
+ run_proc.call(ident, time, action)
144
+ return true
145
+ rescue
146
+ puts "failed ident=#{ident} time=#{time}: #{$!}"
147
+ $!.backtrace.each {|bt|
148
+ puts " #{bt}"
149
+ }
150
+ return false
151
+ end
152
+ end
153
+
154
+ def try_delete(ident)
155
+ @lock.delete_before(ident, Time.now.to_i-@delete)
156
+ end
157
+ end
158
+
159
+
160
+ class ExecRunner
161
+ def initialize(cmd)
162
+ @cmd = cmd + ' ' + ARGV.map {|a| Shellwords.escape(a) }.join(' ')
163
+ @iobuf = ''
164
+ end
165
+
166
+ def call(ident, time, action)
167
+ message = [ident, time, action].join("\t")
168
+ IO.popen(@cmd, "r+") {|io|
169
+ io.write(message) rescue nil
170
+ io.close_write
171
+ begin
172
+ while true
173
+ io.sysread(1024, @iobuf)
174
+ print @iobuf
175
+ end
176
+ rescue EOFError
177
+ end
178
+ }
179
+ if $?.to_i != 0
180
+ raise "Command failed"
181
+ end
182
+ end
183
+ end
184
+
185
+
186
+ end # module RSched
@@ -0,0 +1,27 @@
1
+
2
+ module RSched
3
+
4
+
5
+ class Lock
6
+ def initialize(hostname, timeout)
7
+ end
8
+
9
+ # acquired=token, locked=false, finished=nil
10
+ def acquire(ident, time)
11
+ end
12
+
13
+ def release(token)
14
+ end
15
+
16
+ def finish(token)
17
+ end
18
+
19
+ def delete_before(ident, time)
20
+ end
21
+ end
22
+
23
+
24
+ end
25
+
26
+ require 'rsched/dblock'
27
+
@@ -0,0 +1,5 @@
1
+ module RSched
2
+
3
+ VERSION = '0.2.0'
4
+
5
+ end
data/test/cat.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ cat > $1
@@ -0,0 +1,154 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+
3
+ class DBLockTest < Test::Unit::TestCase
4
+ TIMEOUT = 10
5
+ DB_PATH = File.dirname(__FILE__)+'/test.db'
6
+ DB_URI = "DBI:SQLite3:#{DB_PATH}"
7
+
8
+ def clean
9
+ FileUtils.rm_f DB_PATH
10
+ end
11
+
12
+ def test1_db
13
+ RSched::DBLock.new('test1', TIMEOUT, DB_URI, '', '')
14
+ end
15
+
16
+ def test2_db
17
+ RSched::DBLock.new('test2', TIMEOUT, DB_URI, '', '')
18
+ end
19
+
20
+ it 'acquire' do
21
+ clean
22
+
23
+ now = Time.now.to_i
24
+ time = Time.now.to_i / 60 * 60
25
+
26
+ db1 = test1_db
27
+ db2 = test2_db
28
+
29
+ token = db1.acquire('ident1', time, now)
30
+ assert_not_equal nil, token
31
+ assert_not_equal false, token
32
+
33
+ # different host can't lock
34
+ token = db2.acquire('ident1', time, now)
35
+ assert_equal false, token
36
+
37
+ # same host can relock
38
+ token = db1.acquire('ident1', time, now)
39
+ assert_not_equal nil, token
40
+ assert_not_equal false, token
41
+
42
+ # different identifier
43
+ token = db2.acquire('ident2', time, now)
44
+ assert_not_equal nil, token
45
+ assert_not_equal false, token
46
+
47
+ # different time
48
+ token = db2.acquire('ident1', time+60, now)
49
+ assert_not_equal nil, token
50
+ assert_not_equal false, token
51
+ end
52
+
53
+ it 'release' do
54
+ clean
55
+
56
+ now = Time.now.to_i
57
+ time = Time.now.to_i / 60 * 60
58
+
59
+ db1 = test1_db
60
+ db2 = test2_db
61
+
62
+ token = db1.acquire('ident1', time, now)
63
+ assert_not_equal nil, token
64
+ assert_not_equal false, token
65
+
66
+ db1.release(token)
67
+
68
+ # released
69
+ token = db2.acquire('ident1', time, now)
70
+ assert_not_equal nil, token
71
+ assert_not_equal false, token
72
+ end
73
+
74
+ it 'finish' do
75
+ clean
76
+
77
+ now = Time.now.to_i
78
+ time = Time.now.to_i / 60 * 60
79
+
80
+ db1 = test1_db
81
+ db2 = test2_db
82
+
83
+ token = db1.acquire('ident1', time, now)
84
+ assert_not_equal nil, token
85
+ assert_not_equal false, token
86
+
87
+ db1.finish(token, now)
88
+
89
+ # finished
90
+ token_ = db1.acquire('ident1', time, now)
91
+ assert_equal nil, token_
92
+
93
+ # finished
94
+ token_ = db2.acquire('ident1', time, now)
95
+ assert_equal nil, token_
96
+ end
97
+
98
+ it 'timeout' do
99
+ clean
100
+
101
+ now = Time.now.to_i
102
+ time = Time.now.to_i / 60 * 60
103
+
104
+ db1 = test1_db
105
+ db2 = test2_db
106
+
107
+ token = db1.acquire('ident1', time, now)
108
+ assert_not_equal nil, token
109
+ assert_not_equal false, token
110
+
111
+ # not timed out
112
+ token_ = db2.acquire('ident1', time, now+TIMEOUT)
113
+ assert_equal false, token_
114
+
115
+ # timed out
116
+ token = db2.acquire('ident1', time, now+TIMEOUT+1)
117
+ assert_not_equal nil, token
118
+ assert_not_equal false, token
119
+
120
+ # taken
121
+ token = db1.acquire('ident1', time, now+TIMEOUT+1)
122
+ assert_equal false, token
123
+ end
124
+
125
+ it 'extend' do
126
+ clean
127
+
128
+ now = Time.now.to_i
129
+ time = Time.now.to_i / 60 * 60
130
+
131
+ db1 = test1_db
132
+ db2 = test2_db
133
+
134
+ token = db1.acquire('ident1', time, now)
135
+ assert_not_equal nil, token
136
+ assert_not_equal false, token
137
+
138
+ # same host can relock
139
+ # + extend timeout
140
+ token = db1.acquire('ident1', time, now+TIMEOUT)
141
+ assert_not_equal nil, token
142
+ assert_not_equal false, token
143
+
144
+ # timeout is extended
145
+ token_ = db2.acquire('ident1', time, now+TIMEOUT+1)
146
+ assert_equal false, token_
147
+
148
+ # extended timeout is expired
149
+ token = db2.acquire('ident1', time, now+TIMEOUT*2+1)
150
+ assert_not_equal nil, token
151
+ assert_not_equal false, token
152
+ end
153
+ end
154
+
data/test/exec_test.rb ADDED
@@ -0,0 +1,57 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+
3
+ class ExecTest < Test::Unit::TestCase
4
+ it 'success' do
5
+ success_sh = File.expand_path File.dirname(__FILE__)+"/success.sh"
6
+ e = RSched::ExecRunner.new(success_sh)
7
+
8
+ ident = 'ident'
9
+ time = Time.parse("2010-02-02 00:00:00 UTC").to_i
10
+ action = 'act'
11
+
12
+ assert_nothing_raised do
13
+ e.call(ident, time, action)
14
+ end
15
+ end
16
+
17
+ it 'fail' do
18
+ fail_sh = File.expand_path File.dirname(__FILE__)+"/fail.sh"
19
+ e = RSched::ExecRunner.new(fail_sh)
20
+
21
+ ident = 'ident'
22
+ time = Time.parse("2010-02-02 00:00:00 UTC").to_i
23
+ action = 'act'
24
+
25
+ assert_raise(RuntimeError) do
26
+ e.call(ident, time, action)
27
+ end
28
+ end
29
+
30
+ it 'stdin' do
31
+ cat_sh = File.expand_path File.dirname(__FILE__)+"/cat.sh"
32
+ out_tmp = File.expand_path File.dirname(__FILE__)+"/cat.sh.tmp"
33
+ e = RSched::ExecRunner.new("#{cat_sh} #{out_tmp}")
34
+
35
+ ident = 'ident'
36
+ time = Time.parse("2010-02-02 00:00:00 UTC").to_i
37
+ action = 'act'
38
+
39
+ e.call(ident, time, action)
40
+
41
+ assert_equal [ident, time, action].join("\t"), File.read(out_tmp)
42
+ end
43
+
44
+ it 'huge' do
45
+ huge_sh = File.expand_path File.dirname(__FILE__)+"/huge.sh"
46
+ e = RSched::ExecRunner.new("#{huge_sh}")
47
+
48
+ ident = 'ident'
49
+ time = Time.parse("2010-02-02 00:00:00 UTC").to_i
50
+ action = 'act'
51
+
52
+ e.call(ident, time, action)
53
+
54
+ # should finish
55
+ end
56
+ end
57
+
data/test/fail.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ exit 1
data/test/huge.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ dd if=/dev/zero bs=1024 count=1024
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+
3
+ class SchedTest < Test::Unit::TestCase
4
+ MINUTE = 60
5
+ HOUR = 60*60
6
+ DAY = 60*60*24
7
+
8
+ it 'sched minutes' do
9
+ now = Time.parse("2010-02-02 00:00:00 UTC").to_i
10
+ sched_start = now
11
+
12
+ sched = RSched::Engine::Sched.new("* * * * *", "act", sched_start, now, now)
13
+ assert_equal [now], sched.queue
14
+
15
+ sched = RSched::Engine::Sched.new("* * * * *", "act", sched_start, now, now+MINUTE*2)
16
+ assert_equal [now, now+MINUTE, now+MINUTE*2], sched.queue
17
+
18
+ sched = RSched::Engine::Sched.new("*/2 * * * *", "act", sched_start, now, now+MINUTE*2)
19
+ assert_equal [now, now+MINUTE*2], sched.queue
20
+
21
+ sched = RSched::Engine::Sched.new("0,1,3 * * * *", "act", sched_start, now, now+MINUTE*4)
22
+ assert_equal [now, now+MINUTE, now+MINUTE*3], sched.queue
23
+ end
24
+
25
+ it 'sched hours' do
26
+ now = Time.parse("2010-02-02 00:00:00 UTC").to_i
27
+ sched_start = now
28
+
29
+ sched = RSched::Engine::Sched.new("0 * * * *", "act", sched_start, now, now)
30
+ assert_equal [now], sched.queue
31
+
32
+ sched = RSched::Engine::Sched.new("0 * * * *", "act", sched_start, now, now+HOUR*2)
33
+ assert_equal [now, now+HOUR, now+HOUR*2], sched.queue
34
+
35
+ sched = RSched::Engine::Sched.new("0 */2 * * *", "act", sched_start, now, now+HOUR*2)
36
+ assert_equal [now, now+HOUR*2], sched.queue
37
+
38
+ sched = RSched::Engine::Sched.new("0 0,1,3 * * *", "act", sched_start, now, now+HOUR*4)
39
+ assert_equal [now, now+HOUR, now+HOUR*3], sched.queue
40
+ end
41
+
42
+ it 'sched hours' do
43
+ now = Time.parse("2010-02-02 00:00:00 UTC").to_i
44
+ sched_start = now
45
+
46
+ sched = RSched::Engine::Sched.new("0 0 * * *", "act", sched_start, now, now)
47
+ assert_equal [now], sched.queue
48
+
49
+ sched = RSched::Engine::Sched.new("0 0 * * *", "act", sched_start, now, now+DAY*2)
50
+ assert_equal [now, now+DAY, now+DAY*2], sched.queue
51
+
52
+ sched = RSched::Engine::Sched.new("0 0 */2 * *", "act", sched_start, now, now+DAY*2)
53
+ assert_equal [now, now+DAY*2], sched.queue
54
+
55
+ sched = RSched::Engine::Sched.new("0 0 2,3,5 * *", "act", sched_start, now, now+DAY*4)
56
+ assert_equal [now, now+DAY, now+DAY*3], sched.queue
57
+ end
58
+ end
59
+
data/test/success.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ exit 0
@@ -0,0 +1,14 @@
1
+ require 'test/unit'
2
+ $LOAD_PATH << File.dirname(__FILE__)+"/../lib"
3
+ require 'rsched/engine'
4
+ require 'fileutils'
5
+
6
+ class Test::Unit::TestCase
7
+ #class << self
8
+ # alias_method :it, :test
9
+ #end
10
+ def self.it(name, &block)
11
+ define_method("test_#{name}", &block)
12
+ end
13
+ end
14
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsched
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sadayuki Furuhashi
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-11 00:00:00 +09:00
18
+ date: 2011-07-12 00:00:00 +09:00
19
19
  default_executable: rsched
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -61,7 +61,19 @@ extra_rdoc_files:
61
61
  files:
62
62
  - bin/rsched
63
63
  - lib/rsched/command/rsched.rb
64
+ - lib/rsched/dblock.rb
65
+ - lib/rsched/engine.rb
66
+ - lib/rsched/lock.rb
67
+ - lib/rsched/version.rb
68
+ - test/dblock_test.rb
69
+ - test/exec_test.rb
70
+ - test/sched_test.rb
71
+ - test/test_helper.rb
64
72
  - README.rdoc
73
+ - test/cat.sh
74
+ - test/fail.sh
75
+ - test/huge.sh
76
+ - test/success.sh
65
77
  has_rdoc: true
66
78
  homepage:
67
79
  licenses: []
@@ -96,5 +108,12 @@ rubygems_version: 1.3.7
96
108
  signing_key:
97
109
  specification_version: 3
98
110
  summary: Generic Reliable Scheduler
99
- test_files: []
100
-
111
+ test_files:
112
+ - test/dblock_test.rb
113
+ - test/exec_test.rb
114
+ - test/sched_test.rb
115
+ - test/test_helper.rb
116
+ - test/cat.sh
117
+ - test/fail.sh
118
+ - test/huge.sh
119
+ - test/success.sh