rsched 0.1.0 → 0.2.0

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