perfectsched 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +14 -0
- data/lib/perfectsched/backend/rdb_compat.rb +21 -13
- data/lib/perfectsched/error.rb +16 -0
- data/lib/perfectsched/version.rb +1 -1
- data/lib/perfectsched.rb +1 -0
- data/spec/rdb_compat_backend_spec.rb +41 -0
- data/spec/schedule_collection_spec.rb +44 -44
- metadata +20 -18
data/ChangeLog
CHANGED
@@ -1,4 +1,18 @@
|
|
1
1
|
|
2
|
+
== 2012-06-25 version 0.8.1
|
3
|
+
|
4
|
+
* Added autoload for PerfectSched::VERSION
|
5
|
+
* Fixed rdb_compat backend to use Integer type for time fields
|
6
|
+
* Added IdempotentAlreadyFinishedError and IdempotentAlreadyExistsError
|
7
|
+
which should be ignored for idempotency
|
8
|
+
|
9
|
+
|
10
|
+
== 2012-05-23 version 0.8.0
|
11
|
+
|
12
|
+
* New major version
|
13
|
+
* Redesigned API
|
14
|
+
|
15
|
+
|
2
16
|
== 2012-02-21 version 0.7.10
|
3
17
|
|
4
18
|
* Fixed NullBackend#modify_checked
|
@@ -71,7 +71,7 @@ module PerfectSched
|
|
71
71
|
|
72
72
|
def get_schedule_metadata(key, options={})
|
73
73
|
connect {
|
74
|
-
row = @db.fetch("SELECT id, timeout, next_time, cron, delay, data, timezone FROM `#{@table}` LIMIT 1").first
|
74
|
+
row = @db.fetch("SELECT id, timeout, next_time, cron, delay, data, timezone FROM `#{@table}` WHERE id=? LIMIT 1", key).first
|
75
75
|
unless row
|
76
76
|
raise NotFoundError, "schedule key=#{key} does not exist"
|
77
77
|
end
|
@@ -91,14 +91,14 @@ module PerfectSched
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def add(key, type, cron, delay, timezone, data, next_time, next_run_time, options)
|
94
|
-
data = data.dup
|
95
|
-
data[
|
94
|
+
data = data ? data.dup : {}
|
95
|
+
data['type'] = type
|
96
96
|
connect {
|
97
97
|
begin
|
98
98
|
n = @db["INSERT INTO `#{@table}` (id, timeout, next_time, cron, delay, data, timezone) VALUES (?, ?, ?, ?, ?, ?, ?);", key, next_run_time, next_time, cron, delay, data.to_json, timezone].insert
|
99
99
|
return Schedule.new(@client, key)
|
100
100
|
rescue Sequel::DatabaseError
|
101
|
-
raise
|
101
|
+
raise IdempotentAlreadyExistsError, "schedule key=#{key} already exists"
|
102
102
|
end
|
103
103
|
}
|
104
104
|
end
|
@@ -107,7 +107,7 @@ module PerfectSched
|
|
107
107
|
connect {
|
108
108
|
n = @db["DELETE FROM `#{@table}` WHERE id=?;", key].delete
|
109
109
|
if n <= 0
|
110
|
-
raise
|
110
|
+
raise IdempotentNotFoundError, "schedule key=#{key} does no exist"
|
111
111
|
end
|
112
112
|
}
|
113
113
|
end
|
@@ -150,7 +150,7 @@ module PerfectSched
|
|
150
150
|
|
151
151
|
n = @db["UPDATE `#{@table}` SET timeout=? WHERE id=? AND timeout=?;", next_timeout, row[:id], row[:timeout]].update
|
152
152
|
if n > 0
|
153
|
-
scheduled_time =
|
153
|
+
scheduled_time = row[:next_time]
|
154
154
|
attributes = create_attributes(row)
|
155
155
|
task_token = Token.new(row[:id], row[:next_time], attributes[:cron], attributes[:delay], attributes[:timezone])
|
156
156
|
task = Task.new(@client, row[:id], attributes, scheduled_time, task_token)
|
@@ -189,7 +189,7 @@ module PerfectSched
|
|
189
189
|
connect {
|
190
190
|
n = @db["UPDATE `#{@table}` SET timeout=?, next_time=? WHERE id=? AND next_time=?;", next_run_time, next_time, row_id, scheduled_time].update
|
191
191
|
if n < 0
|
192
|
-
raise
|
192
|
+
raise IdempotentAlreadyFinishedError, "task time=#{Time.at(scheduled_time).utc} is already finished"
|
193
193
|
end
|
194
194
|
}
|
195
195
|
end
|
@@ -224,16 +224,24 @@ module PerfectSched
|
|
224
224
|
timezone = row[:timezone] || 'UTC'
|
225
225
|
delay = row[:delay] || 0
|
226
226
|
cron = row[:cron]
|
227
|
-
next_time =
|
228
|
-
next_run_time =
|
227
|
+
next_time = row[:next_time]
|
228
|
+
next_run_time = row[:timeout]
|
229
229
|
|
230
|
-
|
231
|
-
|
232
|
-
rescue
|
230
|
+
d = row[:data]
|
231
|
+
if d == nil || d == ''
|
233
232
|
data = {}
|
233
|
+
else
|
234
|
+
begin
|
235
|
+
data = JSON.parse(d)
|
236
|
+
rescue
|
237
|
+
data = {}
|
238
|
+
end
|
234
239
|
end
|
235
240
|
|
236
|
-
type = data.delete('type')
|
241
|
+
type = data.delete('type')
|
242
|
+
if type == nil || type.empty?
|
243
|
+
type = row[:id].split(/\./, 2)[0]
|
244
|
+
end
|
237
245
|
|
238
246
|
attributes = {
|
239
247
|
:timezone => timezone,
|
data/lib/perfectsched/error.rb
CHANGED
@@ -40,4 +40,20 @@ module PerfectSched
|
|
40
40
|
|
41
41
|
class ProcessStopError < RuntimeError
|
42
42
|
end
|
43
|
+
|
44
|
+
# Applications can ignore these errors to achieve idempotency
|
45
|
+
module IdempotentError
|
46
|
+
end
|
47
|
+
|
48
|
+
class IdempotentAlreadyFinishedError < AlreadyFinishedError
|
49
|
+
include IdempotentError
|
50
|
+
end
|
51
|
+
|
52
|
+
class IdempotentAlreadyExistsError < AlreadyExistsError
|
53
|
+
include IdempotentError
|
54
|
+
end
|
55
|
+
|
56
|
+
class IdempotentNotFoundError < NotFoundError
|
57
|
+
include IdempotentError
|
58
|
+
end
|
43
59
|
end
|
data/lib/perfectsched/version.rb
CHANGED
data/lib/perfectsched.rb
CHANGED
@@ -38,6 +38,7 @@ module PerfectSched
|
|
38
38
|
:SignalQueue => 'perfectsched/signal_queue',
|
39
39
|
:Task => 'perfectsched/task',
|
40
40
|
:Worker => 'perfectsched/worker',
|
41
|
+
:VERSION => 'perfectsched/version',
|
41
42
|
}.each_pair {|k,v|
|
42
43
|
autoload k, File.expand_path(v, File.dirname(__FILE__))
|
43
44
|
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'perfectsched/backend/rdb_compat'
|
3
|
+
|
4
|
+
describe Backend::RDBCompatBackend do
|
5
|
+
let :sc do
|
6
|
+
FileUtils.rm_f 'spec/test.db'
|
7
|
+
sc = PerfectSched.open({:type=>'rdb_compat', :url=>'sqlite://spec/test.db', :table=>'test_scheds'})
|
8
|
+
sc.client.init_database
|
9
|
+
sc
|
10
|
+
end
|
11
|
+
|
12
|
+
let :client do
|
13
|
+
sc.client
|
14
|
+
end
|
15
|
+
|
16
|
+
let :backend do
|
17
|
+
client.backend
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'backward compatibility 1' do
|
21
|
+
backend.db["INSERT INTO test_scheds (id, timeout, next_time, cron, delay, data, timezone) VALUES (?, ?, ?, ?, ?, ?, ?)", "maint_sched.1.do_hourly", 1339812000, 1339812000, "0 * * * *", 0, {"account_id"=>1}.to_json, "UTC"].insert
|
22
|
+
ts = backend.acquire(60, 1, {:now=>1339812003})
|
23
|
+
ts.should_not == nil
|
24
|
+
t = ts[0]
|
25
|
+
t.data.should == {'account_id'=>1}
|
26
|
+
t.type.should == 'maint_sched'
|
27
|
+
t.key.should == 'maint_sched.1.do_hourly'
|
28
|
+
t.next_time.should == 1339812000
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'backward compatibility 2' do
|
32
|
+
backend.db["INSERT INTO test_scheds (id, timeout, next_time, cron, delay, data, timezone) VALUES (?, ?, ?, ?, ?, ?, ?)", "merge", 1339812060, 1339812000, "@hourly", 60, '', "Asia/Tokyo"].insert
|
33
|
+
ts = backend.acquire(60, 1, {:now=>1339812060})
|
34
|
+
t = ts[0]
|
35
|
+
t.data.should == {}
|
36
|
+
t.type.should == 'merge'
|
37
|
+
t.key.should == 'merge'
|
38
|
+
t.next_time.should == 1339812000
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -1,142 +1,142 @@
|
|
1
1
|
|
2
2
|
describe ScheduleCollection do
|
3
|
-
|
4
|
-
|
3
|
+
let :sc do
|
4
|
+
create_test_sched
|
5
5
|
end
|
6
6
|
|
7
7
|
after do
|
8
|
-
|
8
|
+
sc.client.close
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'is a ScheduleCollection' do
|
12
|
-
|
12
|
+
sc.class.should == PerfectSched::ScheduleCollection
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'succeess add' do
|
16
|
-
|
16
|
+
sc.add('sched01', 't01', {:cron=>'* * * * *', :timezone=>'UTC'})
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'fail duplicated add' do
|
20
|
-
|
20
|
+
sc.add('sched01', 't01', {:cron=>'* * * * *', :timezone=>'UTC'})
|
21
21
|
|
22
22
|
lambda {
|
23
|
-
|
23
|
+
sc.add('sched01', 't01', {:cron=>'* * * * *', :timezone=>'UTC'})
|
24
24
|
}.should raise_error AlreadyExistsError
|
25
25
|
|
26
|
-
|
26
|
+
sc['sched01'].delete!
|
27
27
|
|
28
|
-
|
28
|
+
sc.add('sched01', 't01', {:cron=>'* * * * *', :timezone=>'UTC'})
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'acquire' do
|
32
32
|
time = 1323820800 # 2011-12-14 00:00:00 UTC
|
33
33
|
|
34
|
-
s01 =
|
34
|
+
s01 = sc.add('sched01', 't01', :cron=>"* * * * *", :data=>{'k'=>1}, :next_time=>time)
|
35
35
|
|
36
|
-
t01 =
|
36
|
+
t01 = sc.poll(:alive_time=>120, :now=>time)
|
37
37
|
t01.key.should == 'sched01'
|
38
38
|
t01.type.should == 't01'
|
39
39
|
t01.cron.should == "* * * * *"
|
40
40
|
t01.delay.should == 0
|
41
41
|
t01.data.should == {'k'=>1}
|
42
|
-
t01.scheduled_time.should ==
|
42
|
+
t01.scheduled_time.should == time
|
43
43
|
|
44
|
-
t02 =
|
44
|
+
t02 = sc.poll(:alive_time=>120, :now=>time+60)
|
45
45
|
t02.should == nil
|
46
46
|
|
47
47
|
t01.finish!
|
48
48
|
|
49
|
-
t04 =
|
49
|
+
t04 = sc.poll(:alive_time=>120, :now=>time+60)
|
50
50
|
t04.key.should == 'sched01'
|
51
51
|
t01.type.should == 't01'
|
52
52
|
t04.cron.should == "* * * * *"
|
53
53
|
t04.delay.should == 0
|
54
54
|
t04.data.should == {'k'=>1}
|
55
|
-
t04.scheduled_time.should ==
|
55
|
+
t04.scheduled_time.should == time+60
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'timezone' do
|
59
59
|
time = 1323820800 # 2011-12-14 00:00:00 UTC
|
60
60
|
|
61
|
-
s01 =
|
61
|
+
s01 = sc.add('sched01', 't01', :cron=>"0 0 * * *", :next_time=>time-60, :timezone=>'UTC')
|
62
62
|
#s01.class.should == Schedule
|
63
63
|
#s01.key.should == 'sched01'
|
64
64
|
|
65
|
-
s02 =
|
65
|
+
s02 = sc.add('sched02', 't01', :cron=>"0 0 * * *", :next_time=>time-60, :timezone=>'Asia/Tokyo')
|
66
66
|
#s02.class.should == Schedule
|
67
67
|
#s02.key.should == 'sched02'
|
68
68
|
|
69
|
-
t01 =
|
69
|
+
t01 = sc.poll(:alive_time=>86400, :now=>time)
|
70
70
|
t01.class.should == Task
|
71
71
|
t01.key.should == 'sched01'
|
72
72
|
t01.type.should == 't01'
|
73
|
-
t01.scheduled_time.should ==
|
73
|
+
t01.scheduled_time.should == time
|
74
74
|
|
75
|
-
t02 =
|
75
|
+
t02 = sc.poll(:alive_time=>86400, :now=>time+54000)
|
76
76
|
t02.class.should == Task
|
77
77
|
t02.key.should == 'sched02'
|
78
78
|
t02.type.should == 't01'
|
79
|
-
t02.scheduled_time.should ==
|
79
|
+
t02.scheduled_time.should == time+54000
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'delay' do
|
83
83
|
time = 1323820800 # 2011-12-14 00:00:00 UTC
|
84
84
|
|
85
|
-
s01 =
|
85
|
+
s01 = sc.add('sched01', 't01', :cron=>"0 * * * *", :delay=>30, :next_time=>time, :timezone=>'UTC')
|
86
86
|
|
87
|
-
t01 =
|
87
|
+
t01 = sc.poll(:alive_time=>86400, :now=>time)
|
88
88
|
t01.should == nil
|
89
89
|
|
90
|
-
t02 =
|
90
|
+
t02 = sc.poll(:alive_time=>86400, :now=>time+30)
|
91
91
|
t02.class.should == Task
|
92
92
|
t02.key.should == 'sched01'
|
93
93
|
t02.type.should == 't01'
|
94
|
-
t02.scheduled_time.should ==
|
94
|
+
t02.scheduled_time.should == time
|
95
95
|
t02.delay.should == 30
|
96
96
|
|
97
97
|
t02.finish!
|
98
98
|
|
99
|
-
t03 =
|
99
|
+
t03 = sc.poll(:alive_time=>86400, :now=>time+3600)
|
100
100
|
t03.should == nil
|
101
101
|
|
102
|
-
t04 =
|
102
|
+
t04 = sc.poll(:alive_time=>86400, :now=>time+3630)
|
103
103
|
t04.class.should == Task
|
104
104
|
t04.key.should == 'sched01'
|
105
105
|
t04.type.should == 't01'
|
106
|
-
t04.scheduled_time.should ==
|
106
|
+
t04.scheduled_time.should == time+3600
|
107
107
|
t04.delay.should == 30
|
108
108
|
end
|
109
109
|
|
110
110
|
it 'invalid cron format' do
|
111
111
|
lambda {
|
112
|
-
|
112
|
+
sc.add('sched01', 't01', :cron=>'???')
|
113
113
|
}.should raise_error ArgumentError
|
114
114
|
|
115
115
|
lambda {
|
116
|
-
|
116
|
+
sc.add('sched01', 't01', :cron=>'* * * * * *')
|
117
117
|
}.should raise_error ArgumentError
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'fail duplicated add' do
|
121
|
-
|
121
|
+
sc.add('sched01', 't01', :cron=>"0 * * * *")
|
122
122
|
lambda {
|
123
|
-
|
123
|
+
sc.add('sched01', 't01', :cron=>"0 * * * *")
|
124
124
|
}.should raise_error AlreadyExistsError
|
125
125
|
|
126
|
-
|
126
|
+
sc['sched01'].delete!
|
127
127
|
|
128
|
-
|
128
|
+
sc.add('sched01', 't01', :cron=>"0 * * * *")
|
129
129
|
end
|
130
130
|
|
131
131
|
it 'list' do
|
132
132
|
time = 1323820800 # 2011-12-14 00:00:00 UTC
|
133
133
|
|
134
|
-
|
135
|
-
|
136
|
-
|
134
|
+
sc.add('sched01', 't01', :cron=>"0 * * * *", :next_time=>time, :delay=>1)
|
135
|
+
sc.add('sched02', 't02', :cron=>"0 * * * *", :next_time=>time, :delay=>2)
|
136
|
+
sc.add('sched03', 't03', :cron=>"0 * * * *", :next_time=>time, :delay=>3, :next_run_time=>time+3600)
|
137
137
|
|
138
138
|
a = []
|
139
|
-
|
139
|
+
sc.list {|s|
|
140
140
|
a << s
|
141
141
|
}
|
142
142
|
a.sort_by! {|s| s.key }
|
@@ -147,8 +147,8 @@ describe ScheduleCollection do
|
|
147
147
|
s01.type.should == 't01'
|
148
148
|
s01.cron.should == '0 * * * *'
|
149
149
|
s01.delay.should == 1
|
150
|
-
s01.next_time.should ==
|
151
|
-
s01.next_run_time.should ==
|
150
|
+
s01.next_time.should == time
|
151
|
+
s01.next_run_time.should == time+1
|
152
152
|
|
153
153
|
s02 = a.shift
|
154
154
|
s02.class.should == ScheduleWithMetadata
|
@@ -156,8 +156,8 @@ describe ScheduleCollection do
|
|
156
156
|
s02.type.should == 't02'
|
157
157
|
s02.cron.should == '0 * * * *'
|
158
158
|
s02.delay.should == 2
|
159
|
-
s02.next_time.should ==
|
160
|
-
s02.next_run_time.should ==
|
159
|
+
s02.next_time.should == time
|
160
|
+
s02.next_run_time.should == time+2
|
161
161
|
|
162
162
|
s03 = a.shift
|
163
163
|
s03.class.should == ScheduleWithMetadata
|
@@ -165,8 +165,8 @@ describe ScheduleCollection do
|
|
165
165
|
s03.type.should == 't03'
|
166
166
|
s03.cron.should == '0 * * * *'
|
167
167
|
s03.delay.should == 3
|
168
|
-
s03.next_time.should ==
|
169
|
-
s03.next_run_time.should ==
|
168
|
+
s03.next_time.should == time
|
169
|
+
s03.next_run_time.should == time+3600
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perfectsched
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-25 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cron-spec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70165887081720 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -24,10 +24,10 @@ dependencies:
|
|
24
24
|
version: 0.1.2
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *70165887081720
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: sequel
|
30
|
-
requirement: &
|
30
|
+
requirement: &70165887079760 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ~>
|
@@ -35,10 +35,10 @@ dependencies:
|
|
35
35
|
version: 3.26.0
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
|
-
version_requirements: *
|
38
|
+
version_requirements: *70165887079760
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: tzinfo
|
41
|
-
requirement: &
|
41
|
+
requirement: &70165887078760 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ~>
|
@@ -46,10 +46,10 @@ dependencies:
|
|
46
46
|
version: 0.3.29
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
|
-
version_requirements: *
|
49
|
+
version_requirements: *70165887078760
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: perfectqueue
|
52
|
-
requirement: &
|
52
|
+
requirement: &70165887077360 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
55
|
- - ~>
|
@@ -57,10 +57,10 @@ dependencies:
|
|
57
57
|
version: 0.8.0
|
58
58
|
type: :runtime
|
59
59
|
prerelease: false
|
60
|
-
version_requirements: *
|
60
|
+
version_requirements: *70165887077360
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: rake
|
63
|
-
requirement: &
|
63
|
+
requirement: &70165887076440 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
@@ -68,10 +68,10 @@ dependencies:
|
|
68
68
|
version: 0.9.2
|
69
69
|
type: :development
|
70
70
|
prerelease: false
|
71
|
-
version_requirements: *
|
71
|
+
version_requirements: *70165887076440
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: rspec
|
74
|
-
requirement: &
|
74
|
+
requirement: &70165887075580 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
77
|
- - ~>
|
@@ -79,10 +79,10 @@ dependencies:
|
|
79
79
|
version: 2.10.0
|
80
80
|
type: :development
|
81
81
|
prerelease: false
|
82
|
-
version_requirements: *
|
82
|
+
version_requirements: *70165887075580
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: simplecov
|
85
|
-
requirement: &
|
85
|
+
requirement: &70165887074140 !ruby/object:Gem::Requirement
|
86
86
|
none: false
|
87
87
|
requirements:
|
88
88
|
- - ~>
|
@@ -90,10 +90,10 @@ dependencies:
|
|
90
90
|
version: 0.5.4
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
|
-
version_requirements: *
|
93
|
+
version_requirements: *70165887074140
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: sqlite3
|
96
|
-
requirement: &
|
96
|
+
requirement: &70165887069320 !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
99
|
- - ~>
|
@@ -101,7 +101,7 @@ dependencies:
|
|
101
101
|
version: 1.3.3
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
|
-
version_requirements: *
|
104
|
+
version_requirements: *70165887069320
|
105
105
|
description: Highly available distributed cron built on RDBMS
|
106
106
|
email: frsyuki@gmail.com
|
107
107
|
executables:
|
@@ -135,6 +135,7 @@ files:
|
|
135
135
|
- lib/perfectsched/version.rb
|
136
136
|
- lib/perfectsched/worker.rb
|
137
137
|
- perfectsched.gemspec
|
138
|
+
- spec/rdb_compat_backend_spec.rb
|
138
139
|
- spec/schedule_collection_spec.rb
|
139
140
|
- spec/spec_helper.rb
|
140
141
|
- spec/worker_spec.rb
|
@@ -163,6 +164,7 @@ signing_key:
|
|
163
164
|
specification_version: 3
|
164
165
|
summary: Highly available distributed cron built on RDBMS
|
165
166
|
test_files:
|
167
|
+
- spec/rdb_compat_backend_spec.rb
|
166
168
|
- spec/schedule_collection_spec.rb
|
167
169
|
- spec/spec_helper.rb
|
168
170
|
- spec/worker_spec.rb
|