perfectsched 0.7.19 → 0.8.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.
- 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
|