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
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
require 'perfectsched'
|
4
|
+
|
5
|
+
if ENV['SIMPLE_COV']
|
6
|
+
require 'simplecov'
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter 'spec/'
|
9
|
+
add_filter 'pkg/'
|
10
|
+
add_filter 'vendor/'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'fileutils'
|
15
|
+
|
16
|
+
def test_sched_config
|
17
|
+
{:type=>'rdb_compat', :url=>'sqlite://spec/test.db', :table=>'test_scheds'}
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_test_sched
|
21
|
+
FileUtils.rm_f 'spec/test.db'
|
22
|
+
sc = PerfectSched.open(test_sched_config)
|
23
|
+
|
24
|
+
sql = %[
|
25
|
+
CREATE TABLE IF NOT EXISTS `test_scheds` (
|
26
|
+
id VARCHAR(256) NOT NULL,
|
27
|
+
timeout INT NOT NULL,
|
28
|
+
next_time INT NOT NULL,
|
29
|
+
cron VARCHAR(128) NOT NULL,
|
30
|
+
delay INT NOT NULL,
|
31
|
+
data BLOB NOT NULL,
|
32
|
+
timezone VARCHAR(256) NULL,
|
33
|
+
PRIMARY KEY (id)
|
34
|
+
);]
|
35
|
+
|
36
|
+
sc.client.backend.db.run sql
|
37
|
+
|
38
|
+
return sc
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_test_sched
|
42
|
+
PerfectSched.open(test_sched_config)
|
43
|
+
end
|
44
|
+
|
45
|
+
include PerfectSched
|
46
|
+
|
data/spec/worker_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestHandler < PerfectSched::Application::Base
|
4
|
+
def run
|
5
|
+
puts "TestHandler: #{task}"
|
6
|
+
if task.data['raise_error']
|
7
|
+
raise "expected error test"
|
8
|
+
end
|
9
|
+
if num = task.data['sleep']
|
10
|
+
sleep num
|
11
|
+
end
|
12
|
+
puts "Task finished"
|
13
|
+
end
|
14
|
+
|
15
|
+
def kill(reason)
|
16
|
+
puts "kill: #{reason.class}: #{reason}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class TestApp < PerfectSched::Application::Dispatch
|
21
|
+
route 'test' => TestHandler
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Worker do
|
25
|
+
before do
|
26
|
+
create_test_sched.close
|
27
|
+
@worker = Worker.new(TestApp, test_sched_config)
|
28
|
+
@thread = Thread.new {
|
29
|
+
@worker.run
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
@worker.stop
|
35
|
+
@thread.join
|
36
|
+
end
|
37
|
+
|
38
|
+
def add(*args)
|
39
|
+
sc = get_test_sched
|
40
|
+
sc.add(*args)
|
41
|
+
sc.close
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'run' do
|
45
|
+
TestHandler.any_instance.should_receive(:run).once
|
46
|
+
add('key', 'test', {:cron=>'* * * * *', :next_time=>Time.now.to_i-60})
|
47
|
+
sleep 2
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
metadata
CHANGED
@@ -1,123 +1,169 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perfectsched
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Sadayuki Furuhashi
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2012-05-23 00:00:00.000000000Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: cron-spec
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70253331590900 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- -
|
19
|
+
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: 0.1.2
|
20
|
-
- -
|
22
|
+
- - <=
|
21
23
|
- !ruby/object:Gem::Version
|
22
24
|
version: 0.1.2
|
23
25
|
type: :runtime
|
24
26
|
prerelease: false
|
25
|
-
version_requirements:
|
26
|
-
requirements:
|
27
|
-
- - "<="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 0.1.2
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 0.1.2
|
27
|
+
version_requirements: *70253331590900
|
33
28
|
- !ruby/object:Gem::Dependency
|
34
29
|
name: sequel
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirement: &70253331589420 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
36
32
|
requirements:
|
37
|
-
- -
|
33
|
+
- - ~>
|
38
34
|
- !ruby/object:Gem::Version
|
39
|
-
version: 3.
|
35
|
+
version: 3.26.0
|
40
36
|
type: :runtime
|
41
37
|
prerelease: false
|
42
|
-
version_requirements:
|
38
|
+
version_requirements: *70253331589420
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: tzinfo
|
41
|
+
requirement: &70253331588280 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
43
|
requirements:
|
44
|
-
- -
|
44
|
+
- - ~>
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 3.
|
46
|
+
version: 0.3.29
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: *70253331588280
|
47
50
|
- !ruby/object:Gem::Dependency
|
48
51
|
name: perfectqueue
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
52
|
+
requirement: &70253331587400 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
50
54
|
requirements:
|
51
|
-
- -
|
55
|
+
- - ~>
|
52
56
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.8.
|
57
|
+
version: 0.8.0
|
54
58
|
type: :runtime
|
55
59
|
prerelease: false
|
56
|
-
version_requirements:
|
60
|
+
version_requirements: *70253331587400
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake
|
63
|
+
requirement: &70253331576220 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.9.2
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: *70253331576220
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: rspec
|
74
|
+
requirement: &70253331573960 !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
57
76
|
requirements:
|
58
|
-
- -
|
77
|
+
- - ~>
|
59
78
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
79
|
+
version: 2.10.0
|
80
|
+
type: :development
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: *70253331573960
|
61
83
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
84
|
+
name: simplecov
|
85
|
+
requirement: &70253331573320 !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
64
87
|
requirements:
|
65
|
-
- -
|
88
|
+
- - ~>
|
66
89
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
68
|
-
type: :
|
90
|
+
version: 0.5.4
|
91
|
+
type: :development
|
69
92
|
prerelease: false
|
70
|
-
version_requirements:
|
93
|
+
version_requirements: *70253331573320
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: sqlite3
|
96
|
+
requirement: &70253331572160 !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
71
98
|
requirements:
|
72
|
-
- -
|
99
|
+
- - ~>
|
73
100
|
- !ruby/object:Gem::Version
|
74
|
-
version: 1.
|
75
|
-
|
101
|
+
version: 1.3.3
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: *70253331572160
|
105
|
+
description: Highly available distributed cron built on RDBMS
|
76
106
|
email: frsyuki@gmail.com
|
77
107
|
executables:
|
78
108
|
- perfectsched
|
79
109
|
extensions: []
|
80
|
-
extra_rdoc_files:
|
81
|
-
- ChangeLog
|
82
|
-
- README.rdoc
|
110
|
+
extra_rdoc_files: []
|
83
111
|
files:
|
112
|
+
- .gitignore
|
84
113
|
- ChangeLog
|
85
|
-
-
|
114
|
+
- Gemfile
|
115
|
+
- README.md
|
116
|
+
- Rakefile
|
86
117
|
- bin/perfectsched
|
87
118
|
- lib/perfectsched.rb
|
119
|
+
- lib/perfectsched/application.rb
|
88
120
|
- lib/perfectsched/backend.rb
|
89
|
-
- lib/perfectsched/backend/
|
90
|
-
- lib/perfectsched/
|
91
|
-
- lib/perfectsched/
|
121
|
+
- lib/perfectsched/backend/rdb_compat.rb
|
122
|
+
- lib/perfectsched/blocking_flag.rb
|
123
|
+
- lib/perfectsched/client.rb
|
92
124
|
- lib/perfectsched/command/perfectsched.rb
|
93
|
-
- lib/perfectsched/
|
125
|
+
- lib/perfectsched/daemons_logger.rb
|
94
126
|
- lib/perfectsched/engine.rb
|
127
|
+
- lib/perfectsched/error.rb
|
128
|
+
- lib/perfectsched/model.rb
|
129
|
+
- lib/perfectsched/runner.rb
|
130
|
+
- lib/perfectsched/schedule.rb
|
131
|
+
- lib/perfectsched/schedule_collection.rb
|
132
|
+
- lib/perfectsched/schedule_metadata.rb
|
133
|
+
- lib/perfectsched/signal_queue.rb
|
134
|
+
- lib/perfectsched/task.rb
|
95
135
|
- lib/perfectsched/version.rb
|
96
|
-
-
|
97
|
-
-
|
136
|
+
- lib/perfectsched/worker.rb
|
137
|
+
- perfectsched.gemspec
|
138
|
+
- spec/schedule_collection_spec.rb
|
139
|
+
- spec/spec_helper.rb
|
140
|
+
- spec/worker_spec.rb
|
98
141
|
homepage: https://github.com/treasure-data/perfectsched
|
99
142
|
licenses: []
|
100
|
-
metadata: {}
|
101
143
|
post_install_message:
|
102
144
|
rdoc_options: []
|
103
145
|
require_paths:
|
104
146
|
- lib
|
105
147
|
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
106
149
|
requirements:
|
107
|
-
- -
|
150
|
+
- - ! '>='
|
108
151
|
- !ruby/object:Gem::Version
|
109
152
|
version: '0'
|
110
153
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
111
155
|
requirements:
|
112
|
-
- -
|
156
|
+
- - ! '>='
|
113
157
|
- !ruby/object:Gem::Version
|
114
158
|
version: '0'
|
115
159
|
requirements: []
|
116
160
|
rubyforge_project:
|
117
|
-
rubygems_version:
|
161
|
+
rubygems_version: 1.8.12
|
118
162
|
signing_key:
|
119
|
-
specification_version:
|
120
|
-
summary: Highly available distributed cron built on RDBMS
|
163
|
+
specification_version: 3
|
164
|
+
summary: Highly available distributed cron built on RDBMS
|
121
165
|
test_files:
|
122
|
-
-
|
123
|
-
-
|
166
|
+
- spec/schedule_collection_spec.rb
|
167
|
+
- spec/spec_helper.rb
|
168
|
+
- spec/worker_spec.rb
|
169
|
+
has_rdoc: false
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 8368bea395e050789e24c5cfac1861032ef1515e
|
4
|
-
data.tar.gz: 499a74de525e644337ab9a30506b1dc6d014c1e3
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 12c73b8b590f7dd1aa4f169443a7ac529f61d4ebbb77021c35c65d8bf687c4ffe84f324a8029e096a7ce1da87cb76ddad5017015a7c38813707168c9a7729225
|
7
|
-
data.tar.gz: 838a6ca0136d781497412609b62dbc6e0f5d5527b23d22d05d09e4c1b1c7e063dc85d225f889eae11a6d89abf09580c9eddb05360d3f9ce9a90df2e2f103659e
|
data/README.rdoc
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
= PerfectSched
|
2
|
-
|
3
|
-
Highly available distributed cron works with PerfectQueue.
|
4
|
-
|
5
|
-
It provides exactly-once semantics unless backend database fails. Registered schedules are surely pushed to a queue provided by PerfectQueue every time in order.
|
6
|
-
|
7
|
-
You can register, modify and delete schedules using the command line utility or library API.
|
8
|
-
|
9
|
-
Backend database is pluggable. PerfectSched supports RDBMS and Amazon SimpleDB for now.
|
10
|
-
|
11
|
-
|
12
|
-
== Architecture
|
13
|
-
|
14
|
-
PerfectSched uses following database schema:
|
15
|
-
|
16
|
-
(
|
17
|
-
id:string -- unique identifier of the schedule
|
18
|
-
data:blob -- additional attributes to be pushed to PerfectQueue
|
19
|
-
next_time:int -- unix time of the next schedule
|
20
|
-
cron:string -- description of the schedule
|
21
|
-
delay:int -- delay time before running a schedule
|
22
|
-
timeout:int
|
23
|
-
)
|
24
|
-
|
25
|
-
1. list: lists tasks whose timeout column is old enough.
|
26
|
-
2. lock: updates timeout column of the first task
|
27
|
-
3. push: push a message to the PerfectQueue
|
28
|
-
4. update: if it succeeded, updates the next_time and timeout columns
|
29
|
-
5. or leave: if it failed, leave the row and expect to be retried.
|
30
|
-
|
31
|
-
|
32
|
-
=== Cooperation with PerfectQueue
|
33
|
-
|
34
|
-
PerfectSched pushes a task to PerfectQueue every time on schedule. The ID of the task becomes "<id of the scuedule>.<unix time of the schedule>". For example, the identifier of the schedule is "my-sched", and a schedule runs at "2011-08-30 00:00:00 UTC" (1314662400 in UNIX TIME), the ID of the task is "my-sched.1314662400". The data of the task is same as the schedule.
|
35
|
-
|
36
|
-
|
37
|
-
== Library usage
|
38
|
-
|
39
|
-
=== Adding a schedule
|
40
|
-
|
41
|
-
require 'perfectsched'
|
42
|
-
|
43
|
-
# RDBMS
|
44
|
-
require 'perfectsched/backend/rdb'
|
45
|
-
sched = PerfectSched::Backend::RDBBackend.new(
|
46
|
-
'mysql://user:password@localhost/mydb', table='perfectsched')
|
47
|
-
|
48
|
-
# SimpleDB
|
49
|
-
require 'perfectsched/backend/simpledb'
|
50
|
-
sched = PerfectSched::Backend::SimpleDBBackend.new(
|
51
|
-
'AWS_KEY_ID', 'AWS_SECRET_KEY', 'your-simpledb-domain-name')
|
52
|
-
|
53
|
-
id = 'unique-key-id'
|
54
|
-
cron = "* * * * *"
|
55
|
-
delay = 0
|
56
|
-
data = '{"any":"data"}'
|
57
|
-
start = Time.now.to_i
|
58
|
-
sched.add(id, cron, delay, data, start)
|
59
|
-
|
60
|
-
=== Deleting a schedule
|
61
|
-
|
62
|
-
sched.delete(id)
|
63
|
-
|
64
|
-
=== Modifying a schedule
|
65
|
-
|
66
|
-
cron = "* * * * 0"
|
67
|
-
delay = 10
|
68
|
-
sched.modify_sched(id, cron, delay)
|
69
|
-
|
70
|
-
data = '{"user":1}'
|
71
|
-
sched.modify_data(id, data)
|
72
|
-
|
73
|
-
sched.modify(id, cron, delay, data)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
== Command line usage
|
78
|
-
|
79
|
-
Usage: perfectsched [options]
|
80
|
-
--setup PATH.yaml Write example configuration file
|
81
|
-
-f, --file PATH.yaml Set path to the configuration file
|
82
|
-
|
83
|
-
--list Show registered schedule
|
84
|
-
--delete ID Delete a registered schedule
|
85
|
-
|
86
|
-
--add <ID> <CRON> <DATA> Register a schedule
|
87
|
-
-d, --delay SEC Delay time before running a schedule (default: 0)
|
88
|
-
-s, --start UNIXTIME Start time to run a schedule (default: now)
|
89
|
-
|
90
|
-
-S, --modify-sched <ID> <CRON> Modify schedule of a registered schedule
|
91
|
-
-D, --modify-delay <ID> <DELAY> Modify delay of a registered schedule
|
92
|
-
-J, --modify-data <ID> <DATA> Modify data of a registered schedule
|
93
|
-
|
94
|
-
-b, --daemon PIDFILE Daemonize (default: foreground)
|
95
|
-
-o, --log PATH log file path
|
96
|
-
-v, --verbose verbose mode
|
97
|
-
|
98
|
-
|
99
|
-
=== Configuration
|
100
|
-
|
101
|
-
First of all, create a configuration file:
|
102
|
-
|
103
|
-
$ perfectsched --setup config.yaml
|
104
|
-
$ edit config.yaml
|
105
|
-
|
106
|
-
|
107
|
-
=== Adding a schedule
|
108
|
-
|
109
|
-
$ perfectsched -f config.yaml --add unique-key-id "* * * * *" '{"any":"data"}'
|
110
|
-
|
111
|
-
|
112
|
-
=== Deleting a schedule
|
113
|
-
|
114
|
-
$ perfectsched -f config.yaml --delete unique-key-id
|
115
|
-
|
116
|
-
|
117
|
-
=== Modifying a schedule
|
118
|
-
|
119
|
-
$ perfectsched -f config.yaml --modify-sched unique-key-id "* * * * 0"
|
120
|
-
$ perfectsched -f config.yaml --modify-delay unique-key-id 10
|
121
|
-
$ perfectsched -f config.yaml --modify-data unique-key-id '{"user":1}'
|
122
|
-
|
123
|
-
|
124
|
-
=== Listing registered schedules
|
125
|
-
|
126
|
-
$ perfectsched -f config.yaml --list
|
127
|
-
id schedule delay next time next run data
|
128
|
-
test1 * * * * * 0 2011-08-30 01:29:42 +0900 2011-08-30 01:29:42 +0900 {"attr1":"val1","attr":"val2"}
|
129
|
-
1 entries.
|
130
|
-
|
131
|
-
|
132
|
-
=== Running a scheduler
|
133
|
-
|
134
|
-
$ perfectsched -f config.yaml
|
135
|
-
|
136
|
-
It's recommended to run the scheduler on several servers for availability.
|
137
|
-
|