perfectsched 0.7.19 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/ChangeLog +0 -36
- data/Gemfile +3 -0
- data/README.md +219 -0
- data/Rakefile +19 -0
- data/lib/perfectsched/application.rb +25 -0
- data/lib/perfectsched/backend/rdb_compat.rb +254 -0
- data/lib/perfectsched/backend.rb +44 -82
- data/lib/perfectsched/blocking_flag.rb +25 -0
- data/lib/perfectsched/client.rb +129 -0
- data/lib/perfectsched/command/perfectsched.rb +103 -290
- data/lib/perfectsched/daemons_logger.rb +24 -0
- data/lib/perfectsched/engine.rb +54 -54
- data/lib/perfectsched/error.rb +43 -0
- data/lib/perfectsched/model.rb +37 -0
- data/lib/perfectsched/runner.rb +35 -0
- data/lib/perfectsched/schedule.rb +65 -0
- data/lib/perfectsched/schedule_collection.rb +62 -0
- data/lib/perfectsched/schedule_metadata.rb +76 -0
- data/lib/perfectsched/signal_queue.rb +25 -0
- data/lib/perfectsched/task.rb +46 -0
- data/lib/perfectsched/version.rb +1 -3
- data/lib/perfectsched/worker.rb +163 -0
- data/lib/perfectsched.rb +98 -4
- data/perfectsched.gemspec +27 -0
- data/spec/schedule_collection_spec.rb +172 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/worker_spec.rb +51 -0
- metadata +98 -52
- checksums.yaml +0 -7
- data/README.rdoc +0 -137
- data/lib/perfectsched/backend/null.rb +0 -45
- data/lib/perfectsched/backend/rdb.rb +0 -165
- data/lib/perfectsched/backend/simpledb.rb +0 -174
- data/lib/perfectsched/croncalc.rb +0 -29
- data/test/backend_test.rb +0 -217
- data/test/test_helper.rb +0 -19
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module PerfectSched
|
20
|
+
|
21
|
+
require 'perfectqueue/daemons_logger'
|
22
|
+
DaemonsLogger = PerfectQueue::DaemonsLogger
|
23
|
+
|
24
|
+
end
|
data/lib/perfectsched/engine.rb
CHANGED
@@ -1,71 +1,71 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
1
18
|
|
2
19
|
module PerfectSched
|
3
20
|
|
21
|
+
class Engine
|
22
|
+
def initialize(runner, config)
|
23
|
+
@runner = runner
|
4
24
|
|
5
|
-
|
6
|
-
|
7
|
-
require 'time'
|
8
|
-
@backend = backend
|
9
|
-
@queue = queue
|
10
|
-
@log = log
|
25
|
+
@poll_interval = config[:poll_interval] || 1.0
|
26
|
+
@log = config[:logger] || Logger.new(STDERR)
|
11
27
|
|
12
|
-
|
13
|
-
|
28
|
+
@running_flag = BlockingFlag.new
|
29
|
+
@finish_flag = BlockingFlag.new
|
14
30
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def finished?
|
20
|
-
@finished
|
21
|
-
end
|
22
|
-
|
23
|
-
def run
|
24
|
-
until finished?
|
25
|
-
@log.debug "polling... #{@timeout} #{@poll_interval}"
|
26
|
-
token, task = @backend.acquire(Time.now.to_i+@timeout)
|
31
|
+
@scheds = PerfectSched.open(config)
|
32
|
+
end
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
def run
|
35
|
+
@running_flag.set_region do
|
36
|
+
until @finish_flag.set?
|
37
|
+
task = @scheds.poll
|
38
|
+
if task
|
39
|
+
r = @runner.new(task)
|
40
|
+
r.run
|
41
|
+
else
|
42
|
+
@finish_flag.wait(@poll_interval)
|
43
|
+
end
|
44
|
+
end
|
31
45
|
end
|
32
|
-
|
33
|
-
process(token, task)
|
46
|
+
self
|
34
47
|
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def process(token, task)
|
38
|
-
@log.info "processing schedule id=#{task.id} time=#{Time.at(task.time).iso8601} at #{Time.now.iso8601}"
|
39
|
-
|
40
|
-
begin
|
41
|
-
id = gen_id(task)
|
42
|
-
@queue.submit(id, task.data)
|
43
|
-
# ignore already exists error
|
44
|
-
|
45
|
-
next_time = @croncalc.next_time(task.cron, task.time, task.timezone)
|
46
|
-
next_run = next_time + task.delay
|
47
|
-
@backend.finish(token, next_time, next_run)
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
@log.info "failed schedule id=#{task.id}: #{$!}"
|
49
|
+
def stop
|
50
|
+
@finish_flag.set!
|
51
|
+
self
|
53
52
|
end
|
54
|
-
end
|
55
53
|
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
def join
|
55
|
+
@running_flag.wait while @running_flag.set?
|
56
|
+
self
|
57
|
+
end
|
59
58
|
|
60
|
-
|
61
|
-
|
59
|
+
def close
|
60
|
+
@scheds.close
|
61
|
+
self
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
def shutdown
|
65
|
+
stop
|
66
|
+
join
|
67
|
+
close
|
68
|
+
end
|
66
69
|
end
|
67
|
-
end
|
68
|
-
|
69
70
|
|
70
71
|
end
|
71
|
-
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module PerfectSched
|
20
|
+
class ScheduleError < StandardError
|
21
|
+
end
|
22
|
+
|
23
|
+
class AlreadyFinishedError < ScheduleError
|
24
|
+
end
|
25
|
+
|
26
|
+
class NotFoundError < ScheduleError
|
27
|
+
end
|
28
|
+
|
29
|
+
class AlreadyExistsError < ScheduleError
|
30
|
+
end
|
31
|
+
|
32
|
+
class PreemptedError < ScheduleError
|
33
|
+
end
|
34
|
+
|
35
|
+
class NotSupportedError < ScheduleError
|
36
|
+
end
|
37
|
+
|
38
|
+
class ConfigError < RuntimeError
|
39
|
+
end
|
40
|
+
|
41
|
+
class ProcessStopError < RuntimeError
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module PerfectSched
|
20
|
+
module Model
|
21
|
+
def initialize(client)
|
22
|
+
@client = client
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :client
|
26
|
+
|
27
|
+
def config
|
28
|
+
@client.config
|
29
|
+
end
|
30
|
+
|
31
|
+
## TODO
|
32
|
+
#def inspect
|
33
|
+
# "<#{self.class}>"
|
34
|
+
#end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module PerfectSched
|
20
|
+
class Runner
|
21
|
+
def initialize(task)
|
22
|
+
@task = task
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :task
|
26
|
+
|
27
|
+
def schedules
|
28
|
+
ScheduleCollection.new(task.client)
|
29
|
+
end
|
30
|
+
|
31
|
+
#def run
|
32
|
+
#end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module PerfectSched
|
20
|
+
|
21
|
+
class Schedule
|
22
|
+
include Model
|
23
|
+
|
24
|
+
def initialize(client, key)
|
25
|
+
super(client)
|
26
|
+
@key = key
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :key
|
30
|
+
|
31
|
+
def delete!(options={})
|
32
|
+
@client.delete(@key, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def metadata(options={})
|
36
|
+
@client.get_schedule_metadata(@key, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def exists?(options={})
|
40
|
+
metadata(options)
|
41
|
+
true
|
42
|
+
rescue NotFoundError
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
"#<#{self.class} @key=#{@key.inspect}>"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ScheduleWithMetadata < Schedule
|
52
|
+
def initialize(client, key, attributes)
|
53
|
+
super(client, key)
|
54
|
+
@attributes = attributes
|
55
|
+
end
|
56
|
+
|
57
|
+
def inspect
|
58
|
+
"#<#{self.class} @key=#{@key.inspect} @attributes=#{@attributes.inspect}>"
|
59
|
+
end
|
60
|
+
|
61
|
+
include ScheduleMetadataAccessors
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module PerfectSched
|
20
|
+
|
21
|
+
class ScheduleCollection
|
22
|
+
include Model
|
23
|
+
|
24
|
+
def initialize(client)
|
25
|
+
super(client)
|
26
|
+
end
|
27
|
+
|
28
|
+
# => Schedule
|
29
|
+
def [](key)
|
30
|
+
Schedule.new(@client, key)
|
31
|
+
end
|
32
|
+
|
33
|
+
def list(options={}, &block)
|
34
|
+
@client.list(options, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def poll(options={})
|
38
|
+
options = options.merge({:max_acquire=>1})
|
39
|
+
if acquired = poll_multi(options)
|
40
|
+
return acquired[0]
|
41
|
+
end
|
42
|
+
return nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def poll_multi(options={})
|
46
|
+
@client.acquire(options)
|
47
|
+
end
|
48
|
+
|
49
|
+
# :data => Hash
|
50
|
+
# :cron
|
51
|
+
# :timezone
|
52
|
+
def add(key, type, options={})
|
53
|
+
@client.add(key, type, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
def close
|
57
|
+
client.close
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# PerfectSched
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012 FURUHASHI Sadayuki
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module PerfectSched
|
20
|
+
|
21
|
+
module ScheduleMetadataAccessors
|
22
|
+
attr_reader :attributes
|
23
|
+
|
24
|
+
def type
|
25
|
+
@attributes[:type]
|
26
|
+
end
|
27
|
+
|
28
|
+
def data
|
29
|
+
@attributes[:data]
|
30
|
+
end
|
31
|
+
|
32
|
+
def cron
|
33
|
+
@attributes[:cron]
|
34
|
+
end
|
35
|
+
|
36
|
+
def delay
|
37
|
+
@attributes[:delay]
|
38
|
+
end
|
39
|
+
|
40
|
+
def timezone
|
41
|
+
@attributes[:timezone]
|
42
|
+
end
|
43
|
+
|
44
|
+
def next_time
|
45
|
+
@attributes[:next_time]
|
46
|
+
end
|
47
|
+
|
48
|
+
def next_run_time
|
49
|
+
@attributes[:next_run_time]
|
50
|
+
end
|
51
|
+
|
52
|
+
def message
|
53
|
+
@attributes[:message]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class ScheduleMetadata
|
58
|
+
include Model
|
59
|
+
|
60
|
+
def initialize(client, key, attributes)
|
61
|
+
super(client)
|
62
|
+
@key = key
|
63
|
+
end
|
64
|
+
|
65
|
+
def schedule
|
66
|
+
Schedule.new(@client, @key)
|
67
|
+
end
|
68
|
+
|
69
|
+
def inspect
|
70
|
+
"#<#{self.class} @key=#{@key.inspect} @attributes=#{@attributes.inspect}>"
|
71
|
+
end
|
72
|
+
|
73
|
+
include ScheduleMetadataAccessors
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|