perfectsched 0.7.14 → 0.7.15
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.
- checksums.yaml +15 -0
- data/ChangeLog +5 -0
- data/README.md.html +153 -0
- data/lib/perfectsched/backend/rdb.rb +21 -4
- data/lib/perfectsched/version.rb +1 -1
- metadata +9 -17
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NjkxNTY3NTA4Yjg0YTQ1ZmVlNTFkYjE2NDhlNTIyNmFhZjAyODlhNA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NGZkMGVmMTVhMTQwMDFjYTFmMGE2ZTZmYjRjMzM1YzJiNThmMjZlNg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MzFkYWI1MTc5ODllY2ZkMjZlYTg5MGVmOGU1M2ZhMGM3MTQxMWJiYzFhNDJh
|
10
|
+
ZWNjMTBjMzY1MzVkMTM1ZDQyYThmMWUwNTkyYTNlZjRmMGNjOThmNDZiOWFm
|
11
|
+
NmQwMWZkYjg2Zjk0NzU3ZjAzOTcwMGM0ZjBhMWFmOTZiNzVlZjY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MGZjMzRlNDkzYWZkMmFjMWFkMzRjMWNjNDc0Y2Y0NzY5YTg4ZDQ0OTA2YzYw
|
14
|
+
ZTMyZTRhODliMmM4ODc5YjRiYTNjNDE1MjJhN2EyMzRhNTQ4NWVmODUxMmRi
|
15
|
+
Yjc5NDhiN2ZkZTk4OTYxYWZmMWI2YzllMGY3MmE5YjhkZDFkZDQ=
|
data/ChangeLog
CHANGED
data/README.md.html
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
|
2
|
+
<html>
|
3
|
+
<head><title>-</title></head>
|
4
|
+
<body>
|
5
|
+
<h1>PerfectSched</h1>
|
6
|
+
|
7
|
+
<p>PerfectSched is a highly available distributed cron built on top of RDBMS.</p>
|
8
|
+
|
9
|
+
<p>It provides at-least-once semantics; Even if a worker node fails during process a task, the task is retried by another worker.</p>
|
10
|
+
|
11
|
+
<p>PerfectSched also guarantees that only one worker server processes a task if the server is alive.</p>
|
12
|
+
|
13
|
+
<p>All you have to consider is implementing idempotent worker programs. It's recommended to use <a href="https://github.com/treasure-data/perfectqueue">PerfectQueue</a> with PerfectSched.</p>
|
14
|
+
|
15
|
+
<h2>API overview</h2>
|
16
|
+
|
17
|
+
<p>```ruby</p>
|
18
|
+
|
19
|
+
<h1>open a schedule collection</h1>
|
20
|
+
|
21
|
+
<p>PerfectSched.open(config, &block) #=> #<ScheduleCollection></p>
|
22
|
+
|
23
|
+
<h1>add a schedule</h1>
|
24
|
+
|
25
|
+
<p>ScheduleCollection#add(task_id, type, options)</p>
|
26
|
+
|
27
|
+
<h1>poll a scheduled task</h1>
|
28
|
+
|
29
|
+
<h1>(you don't have to use this method directly. see following sections)</h1>
|
30
|
+
|
31
|
+
<p>ScheduleCollection#poll #=> #<Task></p>
|
32
|
+
|
33
|
+
<h1>get data associated with a task</h1>
|
34
|
+
|
35
|
+
<p>Task#data #=> #<Hash></p>
|
36
|
+
|
37
|
+
<h1>finish a task</h1>
|
38
|
+
|
39
|
+
<p>Task#finish!</p>
|
40
|
+
|
41
|
+
<h1>retry a task</h1>
|
42
|
+
|
43
|
+
<p>Task#retry!
|
44
|
+
```</p>
|
45
|
+
|
46
|
+
<p>Example:</p>
|
47
|
+
|
48
|
+
<p>```ruby</p>
|
49
|
+
|
50
|
+
<h1>submit a task</h1>
|
51
|
+
|
52
|
+
<p>PerfectSched.open(config) {|sc|
|
53
|
+
data = {'key'=>"value"}
|
54
|
+
options = {</p>
|
55
|
+
|
56
|
+
<pre><code>:cron => '0 * * * *',
|
57
|
+
:delay => 30,
|
58
|
+
:timezone => 'Asia/Tokyo',
|
59
|
+
:next_time => Time.parse('2013-01-01 00:00:00 +0900').to_i,
|
60
|
+
:data => data,
|
61
|
+
</code></pre>
|
62
|
+
|
63
|
+
<p> }
|
64
|
+
sc.submit("sched-id", "type1", options)
|
65
|
+
}
|
66
|
+
```</p>
|
67
|
+
|
68
|
+
<h2>Writing a worker application</h2>
|
69
|
+
|
70
|
+
<h3>1. Implement PerfectSched::Application::Base</h3>
|
71
|
+
|
72
|
+
<p>```ruby
|
73
|
+
class TestHandler < PerfectSched::Application::Base
|
74
|
+
# implement run method
|
75
|
+
def run</p>
|
76
|
+
|
77
|
+
<pre><code># do something ...
|
78
|
+
puts "acquired task: #{task.inspect}"
|
79
|
+
|
80
|
+
# call task.finish!, task.retry! or task.release!
|
81
|
+
task.finish!
|
82
|
+
</code></pre>
|
83
|
+
|
84
|
+
<p> end
|
85
|
+
end</p>
|
86
|
+
|
87
|
+
<h3>2. Implement PerfectSched::Application::Dispatch</h3>
|
88
|
+
|
89
|
+
<p><code>ruby
|
90
|
+
class Dispatch < PerfectSched::Application::Dispatch
|
91
|
+
# describe routing
|
92
|
+
route "type1" => TestHandler
|
93
|
+
route /^regexp-.*$/ => :TestHandler # String or Regexp => Class or Symbol
|
94
|
+
end
|
95
|
+
</code></p>
|
96
|
+
|
97
|
+
<h3>3. Run the worker</h3>
|
98
|
+
|
99
|
+
<p>In a launcher script or rake file:</p>
|
100
|
+
|
101
|
+
<p>```</p>
|
102
|
+
|
103
|
+
<h1>run PerfectSched::Worker with the dispatcher</h1>
|
104
|
+
|
105
|
+
<p>system('perfectsched run -I. -rapp/schedules/dispatch Dispatch')
|
106
|
+
```</p>
|
107
|
+
|
108
|
+
<p>or:</p>
|
109
|
+
|
110
|
+
<p><code>ruby
|
111
|
+
require 'app/schedules/dispatch'
|
112
|
+
PerfectSched::Worker.run(Dispatch) {
|
113
|
+
# this method is called when the worker process is restarted
|
114
|
+
raw = File.read('config/perfectsched.yml')
|
115
|
+
yml = YAJL.load(raw)
|
116
|
+
yml[ENV['RAILS_ENV'] || 'development']
|
117
|
+
}
|
118
|
+
</code></p>
|
119
|
+
|
120
|
+
<h3>Signal handlers</h3>
|
121
|
+
|
122
|
+
<ul>
|
123
|
+
<li><em>TERM,INT,QUIT:</em> shutdown</li>
|
124
|
+
<li><em>USR1,HUP:</em> restart</li>
|
125
|
+
<li><em>USR2:</em> reopen log files</li>
|
126
|
+
</ul>
|
127
|
+
|
128
|
+
|
129
|
+
<h2>Configuration</h2>
|
130
|
+
|
131
|
+
<ul>
|
132
|
+
<li><em>type:</em> backend type (required; see following sections)</li>
|
133
|
+
<li><em>log:</em> log file path (default: use stderr)</li>
|
134
|
+
<li><em>poll_interval:</em> interval to poll tasks in seconds (default: 1.0 sec)</li>
|
135
|
+
<li><em>timezone:</em> default timezone (default: 'UTC')</li>
|
136
|
+
<li><em>alive_time:</em> duration to continue a heartbeat request (default: 300 sec)</li>
|
137
|
+
<li><em>retry_wait:</em> duration to retry a retried task (default: 300 sec)</li>
|
138
|
+
</ul>
|
139
|
+
|
140
|
+
|
141
|
+
<h2>Backend types</h2>
|
142
|
+
|
143
|
+
<h3>rdb_compat</h3>
|
144
|
+
|
145
|
+
<p>additional configuration:</p>
|
146
|
+
|
147
|
+
<ul>
|
148
|
+
<li><strong>url:</strong> URL to the RDBMS (example: 'mysql://user:password@host:port/database')</li>
|
149
|
+
<li><strong>table:</strong> name of the table to use</li>
|
150
|
+
</ul>
|
151
|
+
|
152
|
+
</body>
|
153
|
+
</html>
|
@@ -119,17 +119,34 @@ class RDBBackend < Backend
|
|
119
119
|
return nil
|
120
120
|
}
|
121
121
|
end
|
122
|
+
|
123
|
+
# Overrides parent method in order to pass the calculated next run time into modify_checked
|
124
|
+
def modify(id, cron, delay, data, timezone)
|
125
|
+
cron = cron.strip
|
126
|
+
next_time = @croncalc.next_time(cron, Time.now.to_i/60*60, timezone)
|
127
|
+
modify_checked(id, cron, delay, data, timezone, next_time)
|
128
|
+
return next_time, next_time + delay
|
129
|
+
end
|
130
|
+
|
131
|
+
# Overrides parent method in order to pass the calculated next run time into modify_sched_checked
|
132
|
+
def modify_sched(id, cron, delay)
|
133
|
+
cron_, delay_, data_, timezone, next_time = get(id)
|
134
|
+
cron = cron.strip
|
135
|
+
next_time = @croncalc.next_time(cron, Time.now.to_i/60*60, timezone)
|
136
|
+
modify_sched_checked(id, cron, delay, next_time)
|
137
|
+
return next_time, next_time + delay
|
138
|
+
end
|
122
139
|
|
123
|
-
def modify_checked(id, cron, delay, data, timezone)
|
140
|
+
def modify_checked(id, cron, delay, data, timezone, next_time)
|
124
141
|
connect {
|
125
|
-
n = @db["UPDATE `#{@table}` SET cron=?, delay=?, data=?, timezone=? WHERE id=?;", cron, delay, data, timezone, id].update
|
142
|
+
n = @db["UPDATE `#{@table}` SET cron=?, delay=?, data=?, timezone=?, next_time=?, timeout=? WHERE id=?;", cron, delay, data, timezone, next_time, next_time + delay, id].update
|
126
143
|
return n > 0
|
127
144
|
}
|
128
145
|
end
|
129
146
|
|
130
|
-
def modify_sched_checked(id, cron, delay)
|
147
|
+
def modify_sched_checked(id, cron, delay, next_time)
|
131
148
|
connect {
|
132
|
-
n = @db["UPDATE `#{@table}` SET cron=?, delay=? WHERE id=?;", cron, delay, id].update
|
149
|
+
n = @db["UPDATE `#{@table}` SET cron=?, delay=?, next_time=?, timeout=? WHERE id=?;", cron, delay, next_time, next_time + delay, id].update
|
133
150
|
return n > 0
|
134
151
|
}
|
135
152
|
end
|
data/lib/perfectsched/version.rb
CHANGED
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perfectsched
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
5
|
-
prerelease:
|
4
|
+
version: 0.7.15
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Sadayuki Furuhashi
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-
|
11
|
+
date: 2014-06-11 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: cron-spec
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - <=
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -25,7 +23,6 @@ dependencies:
|
|
25
23
|
type: :runtime
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
26
|
requirements:
|
30
27
|
- - <=
|
31
28
|
- !ruby/object:Gem::Version
|
@@ -36,7 +33,6 @@ dependencies:
|
|
36
33
|
- !ruby/object:Gem::Dependency
|
37
34
|
name: sequel
|
38
35
|
requirement: !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
36
|
requirements:
|
41
37
|
- - ~>
|
42
38
|
- !ruby/object:Gem::Version
|
@@ -44,7 +40,6 @@ dependencies:
|
|
44
40
|
type: :runtime
|
45
41
|
prerelease: false
|
46
42
|
version_requirements: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
43
|
requirements:
|
49
44
|
- - ~>
|
50
45
|
- !ruby/object:Gem::Version
|
@@ -52,7 +47,6 @@ dependencies:
|
|
52
47
|
- !ruby/object:Gem::Dependency
|
53
48
|
name: perfectqueue
|
54
49
|
requirement: !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
50
|
requirements:
|
57
51
|
- - ~>
|
58
52
|
- !ruby/object:Gem::Version
|
@@ -60,7 +54,6 @@ dependencies:
|
|
60
54
|
type: :runtime
|
61
55
|
prerelease: false
|
62
56
|
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
57
|
requirements:
|
65
58
|
- - ~>
|
66
59
|
- !ruby/object:Gem::Version
|
@@ -68,7 +61,6 @@ dependencies:
|
|
68
61
|
- !ruby/object:Gem::Dependency
|
69
62
|
name: tzinfo
|
70
63
|
requirement: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
64
|
requirements:
|
73
65
|
- - ~>
|
74
66
|
- !ruby/object:Gem::Version
|
@@ -76,7 +68,6 @@ dependencies:
|
|
76
68
|
type: :runtime
|
77
69
|
prerelease: false
|
78
70
|
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
71
|
requirements:
|
81
72
|
- - ~>
|
82
73
|
- !ruby/object:Gem::Version
|
@@ -88,8 +79,12 @@ executables:
|
|
88
79
|
extensions: []
|
89
80
|
extra_rdoc_files:
|
90
81
|
- ChangeLog
|
82
|
+
- README.md.html
|
91
83
|
- README.rdoc
|
92
84
|
files:
|
85
|
+
- ChangeLog
|
86
|
+
- README.md.html
|
87
|
+
- README.rdoc
|
93
88
|
- bin/perfectsched
|
94
89
|
- lib/perfectsched.rb
|
95
90
|
- lib/perfectsched/backend.rb
|
@@ -100,33 +95,30 @@ files:
|
|
100
95
|
- lib/perfectsched/croncalc.rb
|
101
96
|
- lib/perfectsched/engine.rb
|
102
97
|
- lib/perfectsched/version.rb
|
103
|
-
- ChangeLog
|
104
|
-
- README.rdoc
|
105
98
|
- test/backend_test.rb
|
106
99
|
- test/test_helper.rb
|
107
100
|
homepage: https://github.com/treasure-data/perfectsched
|
108
101
|
licenses: []
|
102
|
+
metadata: {}
|
109
103
|
post_install_message:
|
110
104
|
rdoc_options: []
|
111
105
|
require_paths:
|
112
106
|
- lib
|
113
107
|
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
108
|
requirements:
|
116
109
|
- - ! '>='
|
117
110
|
- !ruby/object:Gem::Version
|
118
111
|
version: '0'
|
119
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
-
none: false
|
121
113
|
requirements:
|
122
114
|
- - ! '>='
|
123
115
|
- !ruby/object:Gem::Version
|
124
116
|
version: '0'
|
125
117
|
requirements: []
|
126
118
|
rubyforge_project:
|
127
|
-
rubygems_version:
|
119
|
+
rubygems_version: 2.2.2
|
128
120
|
signing_key:
|
129
|
-
specification_version:
|
121
|
+
specification_version: 4
|
130
122
|
summary: Highly available distributed cron built on RDBMS or SimpleDB
|
131
123
|
test_files:
|
132
124
|
- test/backend_test.rb
|