isono 0.2.13 → 0.2.14
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -2
- data/isono.gemspec +3 -6
- data/lib/isono/models/job_state.rb +1 -8
- data/lib/isono/models/node_state.rb +20 -41
- data/lib/isono/node_modules/base.rb +5 -0
- data/lib/isono/node_modules/job_channel.rb +8 -3
- data/lib/isono/node_modules/job_worker.rb +7 -1
- data/lib/isono/node_modules/node_collector.rb +6 -8
- data/lib/isono/node_modules/rpc_channel.rb +3 -8
- data/lib/isono/rack/job.rb +1 -0
- data/lib/isono/runner/rpc_server.rb +54 -24
- data/lib/isono/version.rb +1 -1
- metadata +3 -19
data/Rakefile
CHANGED
@@ -16,7 +16,7 @@ task :gem do
|
|
16
16
|
s.summary = 'Messaging and agent fabric'
|
17
17
|
s.name = 'isono'
|
18
18
|
s.require_path = 'lib'
|
19
|
-
s.required_ruby_version = '>= 1.
|
19
|
+
s.required_ruby_version = '>= 1.9.2'
|
20
20
|
s.rubyforge_project = 'isono'
|
21
21
|
|
22
22
|
s.files = `git ls-files -c`.split("\n")
|
@@ -26,7 +26,6 @@ task :gem do
|
|
26
26
|
|
27
27
|
s.add_dependency "amqp", "0.7.4"
|
28
28
|
s.add_dependency "eventmachine", "1.0.0.beta.4"
|
29
|
-
s.add_dependency "statemachine", ">= 1.0.0"
|
30
29
|
s.add_dependency "log4r"
|
31
30
|
|
32
31
|
s.add_development_dependency 'bacon'
|
data/isono.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "isono"
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.14"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["axsh Ltd.", "Masahiro Fujiwara"]
|
9
|
-
s.date = "2012-08-
|
9
|
+
s.date = "2012-08-30"
|
10
10
|
s.email = ["dev@axsh.net", "m-fujiwara@axsh.net"]
|
11
11
|
s.executables = ["cli"]
|
12
12
|
s.files = [".gitignore", "LICENSE", "NOTICE", "Rakefile", "bin/cli", "isono.gemspec", "lib/ext/shellwords.rb", "lib/isono.rb", "lib/isono/amqp_client.rb", "lib/isono/daemonize.rb", "lib/isono/event_delegate_context.rb", "lib/isono/event_observable.rb", "lib/isono/logger.rb", "lib/isono/manifest.rb", "lib/isono/messaging_client.rb", "lib/isono/models/event_log.rb", "lib/isono/models/job_state.rb", "lib/isono/models/node_state.rb", "lib/isono/models/resource_instance.rb", "lib/isono/node.rb", "lib/isono/node_modules/base.rb", "lib/isono/node_modules/data_store.rb", "lib/isono/node_modules/event_channel.rb", "lib/isono/node_modules/event_logger.rb", "lib/isono/node_modules/job_channel.rb", "lib/isono/node_modules/job_collector.rb", "lib/isono/node_modules/job_worker.rb", "lib/isono/node_modules/node_collector.rb", "lib/isono/node_modules/node_heartbeat.rb", "lib/isono/node_modules/rpc_channel.rb", "lib/isono/rack.rb", "lib/isono/rack/builder.rb", "lib/isono/rack/data_store.rb", "lib/isono/rack/job.rb", "lib/isono/rack/map.rb", "lib/isono/rack/object_method.rb", "lib/isono/rack/proc.rb", "lib/isono/rack/sequel.rb", "lib/isono/rack/thread_pass.rb", "lib/isono/resource_manifest.rb", "lib/isono/runner/base.rb", "lib/isono/runner/cli.rb", "lib/isono/runner/rpc_server.rb", "lib/isono/serializer.rb", "lib/isono/thread_pool.rb", "lib/isono/util.rb", "lib/isono/version.rb", "spec/amqp_client_spec.rb", "spec/event_observable_spec.rb", "spec/file_channel_spec.rb", "spec/job_channel_spec.rb", "spec/logger_spec.rb", "spec/manifest_spec.rb", "spec/node_spec.rb", "spec/resource_loader_spec.rb", "spec/rpc_channel_spec.rb", "spec/spec_helper.rb", "spec/thread_pool_spec.rb", "spec/util_spec.rb", "tasks/load_resource_manifest.rake"]
|
13
13
|
s.homepage = "http://github.com/axsh/isono"
|
14
14
|
s.require_paths = ["lib"]
|
15
|
-
s.required_ruby_version = Gem::Requirement.new(">= 1.
|
15
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.9.2")
|
16
16
|
s.rubyforge_project = "isono"
|
17
17
|
s.rubygems_version = "1.8.24"
|
18
18
|
s.summary = "Messaging and agent fabric"
|
@@ -23,14 +23,12 @@ Gem::Specification.new do |s|
|
|
23
23
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
24
24
|
s.add_runtime_dependency(%q<amqp>, ["= 0.7.4"])
|
25
25
|
s.add_runtime_dependency(%q<eventmachine>, ["= 1.0.0.beta.4"])
|
26
|
-
s.add_runtime_dependency(%q<statemachine>, [">= 1.0.0"])
|
27
26
|
s.add_runtime_dependency(%q<log4r>, [">= 0"])
|
28
27
|
s.add_development_dependency(%q<bacon>, [">= 0"])
|
29
28
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
30
29
|
else
|
31
30
|
s.add_dependency(%q<amqp>, ["= 0.7.4"])
|
32
31
|
s.add_dependency(%q<eventmachine>, ["= 1.0.0.beta.4"])
|
33
|
-
s.add_dependency(%q<statemachine>, [">= 1.0.0"])
|
34
32
|
s.add_dependency(%q<log4r>, [">= 0"])
|
35
33
|
s.add_dependency(%q<bacon>, [">= 0"])
|
36
34
|
s.add_dependency(%q<rake>, [">= 0"])
|
@@ -38,7 +36,6 @@ Gem::Specification.new do |s|
|
|
38
36
|
else
|
39
37
|
s.add_dependency(%q<amqp>, ["= 0.7.4"])
|
40
38
|
s.add_dependency(%q<eventmachine>, ["= 1.0.0.beta.4"])
|
41
|
-
s.add_dependency(%q<statemachine>, [">= 1.0.0"])
|
42
39
|
s.add_dependency(%q<log4r>, [">= 0"])
|
43
40
|
s.add_dependency(%q<bacon>, [">= 0"])
|
44
41
|
s.add_dependency(%q<rake>, [">= 0"])
|
@@ -7,7 +7,7 @@ module Isono
|
|
7
7
|
class JobState < Sequel::Model
|
8
8
|
include Logger
|
9
9
|
plugin :schema
|
10
|
-
plugin :
|
10
|
+
plugin :timestamps, :update_on_create=>true
|
11
11
|
|
12
12
|
set_schema {
|
13
13
|
primary_key :id, :type => Integer, :auto_increment=>true, :unsigned=>true
|
@@ -25,13 +25,6 @@ module Isono
|
|
25
25
|
index :job_id, {:unique=>true}
|
26
26
|
}
|
27
27
|
|
28
|
-
before_create(:set_created_at) do
|
29
|
-
self.created_at = self.updated_at= Time.now
|
30
|
-
end
|
31
|
-
before_update(:set_updated_at) do
|
32
|
-
self.updated_at= Time.now
|
33
|
-
end
|
34
|
-
|
35
28
|
end
|
36
29
|
end
|
37
30
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
require 'sequel/model'
|
4
|
-
require 'statemachine'
|
5
4
|
|
6
5
|
module Isono
|
7
6
|
module Models
|
8
7
|
class NodeState < Sequel::Model
|
9
8
|
include Logger
|
10
9
|
plugin :schema
|
11
|
-
plugin :
|
10
|
+
plugin :timestamps, :update_on_create=>true
|
12
11
|
|
13
12
|
set_schema {
|
14
13
|
primary_key :id, :type => Integer, :auto_increment=>true, :unsigned=>true
|
@@ -21,48 +20,28 @@ module Isono
|
|
21
20
|
index :node_id, {:unique=>true}
|
22
21
|
}
|
23
22
|
|
24
|
-
|
25
|
-
self
|
23
|
+
def after_initialize
|
24
|
+
self[:state] = :init
|
26
25
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
trans :timeout, :on_timeout, :timeout
|
44
|
-
|
45
|
-
on_entry_of :online, proc {
|
46
|
-
model.state = :online
|
47
|
-
}
|
48
|
-
on_entry_of :timeout, proc {
|
49
|
-
model.state = :timeout
|
50
|
-
}
|
51
|
-
on_entry_of :offline, proc {
|
52
|
-
model.state = :offline
|
53
|
-
}
|
54
|
-
end
|
55
|
-
|
56
|
-
if self[:state]
|
57
|
-
if st.has_state(self[:state].to_sym)
|
58
|
-
st.state = self[:state].to_sym
|
59
|
-
else
|
60
|
-
raise "Unknown state: #{self[:state]}"
|
61
|
-
end
|
26
|
+
|
27
|
+
def process_event(ev, *args)
|
28
|
+
case [ev, self.state.to_sym]
|
29
|
+
when [:on_ping, :online], [:on_ping, :init], [:on_ping, :timeout]
|
30
|
+
self.state = :online
|
31
|
+
self.last_ping_at = Time.now
|
32
|
+
when [:on_unmonitor, :online]
|
33
|
+
self.state = :offline
|
34
|
+
when [:on_unmonitor, :timeout]
|
35
|
+
self.state = :offline
|
36
|
+
when [:on_unmonitor, :init]
|
37
|
+
self.state = :offline
|
38
|
+
when [:on_timeout, :online], [:on_timeout, :timeout]
|
39
|
+
self.state = :timeout
|
40
|
+
when [:on_timeout, :init]
|
41
|
+
# Do nothing
|
62
42
|
else
|
63
|
-
|
43
|
+
raise "Unknown state transition: #{ev}, #{self.state}"
|
64
44
|
end
|
65
|
-
st
|
66
45
|
end
|
67
46
|
|
68
47
|
end
|
@@ -12,6 +12,7 @@ module Isono
|
|
12
12
|
|
13
13
|
raise "Module initializer_hook is not run yet" if self.value_object.nil?
|
14
14
|
value_object.copy_instance_variables(self)
|
15
|
+
after_initialize
|
15
16
|
end
|
16
17
|
|
17
18
|
# Delegate methods used in subclass frequently.
|
@@ -75,6 +76,10 @@ module Isono
|
|
75
76
|
@node_hooks = {}
|
76
77
|
}
|
77
78
|
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
def after_initialize
|
82
|
+
end
|
78
83
|
|
79
84
|
end
|
80
85
|
end
|
@@ -72,10 +72,15 @@ module Isono
|
|
72
72
|
|
73
73
|
def cancel(job_id)
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
def register_endpoint(endpoint, app, opts={})
|
77
|
-
|
78
|
-
|
77
|
+
raise ArgumentError unless endpoint.is_a?(String)
|
78
|
+
raise ArgumentError unless app.respond_to?(:call)
|
79
|
+
opts = {
|
80
|
+
:concurrency=>config_section.concurrency,
|
81
|
+
:thread_pool => nil,
|
82
|
+
}.merge(opts)
|
83
|
+
rpc.register_endpoint("job.#{endpoint}", Rack::Job.new(app, JobWorker.new(@node, opts[:thread_pool])), {:prefetch=>opts[:concurrency]})
|
79
84
|
end
|
80
85
|
|
81
86
|
private
|
@@ -14,7 +14,7 @@ module Isono
|
|
14
14
|
end
|
15
15
|
|
16
16
|
initialize_hook do
|
17
|
-
@
|
17
|
+
@default_thread_pool = ThreadPool.new(config_section.concurrency.to_i, 'JobWorker')
|
18
18
|
@active_jobs = {}
|
19
19
|
|
20
20
|
RpcChannel.new(node).register_endpoint("job-stats.#{node.node_id}", proc { |req, res|
|
@@ -31,6 +31,12 @@ module Isono
|
|
31
31
|
@thread_pool.shutdown
|
32
32
|
end
|
33
33
|
|
34
|
+
def initialize(node, thread_pool=nil)
|
35
|
+
super(node)
|
36
|
+
raise ArgumentError unless thread_pool.nil? || thread_pool.is_a?(ThreadPool)
|
37
|
+
@thread_pool = thread_pool || @default_thread_pool
|
38
|
+
end
|
39
|
+
|
34
40
|
# Start a new long term job.
|
35
41
|
#
|
36
42
|
# @yield The block to setup JobContext object.
|
@@ -30,22 +30,20 @@ module Isono
|
|
30
30
|
# http://www.mail-archive.com/sqlite-users@sqlite.org/msg03328.html
|
31
31
|
# TODO: paging support for the large result set.
|
32
32
|
Models::NodeState.dataset.all.each { |row|
|
33
|
-
|
34
|
-
sm = row.state_machine
|
35
|
-
next if sm.state == :offline
|
33
|
+
next if row.state == :offline
|
36
34
|
|
37
35
|
diff_time = Time.now - row[:last_ping_at]
|
38
|
-
if
|
39
|
-
|
36
|
+
if row.state != :timeout && diff_time > config_section.timeout_sec
|
37
|
+
row.process_event(:on_timeout)
|
40
38
|
row.save_changes
|
41
39
|
event.publish('node_collector/timedout', :args=>[row.values])
|
42
40
|
end
|
43
41
|
|
44
42
|
if diff_time > config_section.kill_sec
|
45
|
-
|
43
|
+
row.process_event(:on_unmonitor)
|
46
44
|
|
47
45
|
event.publish('node_collector/killed', :args=>[row.values])
|
48
|
-
row.
|
46
|
+
row.destroy
|
49
47
|
end
|
50
48
|
}
|
51
49
|
}
|
@@ -71,7 +69,7 @@ module Isono
|
|
71
69
|
event = EventChannel.new(node)
|
72
70
|
|
73
71
|
a = Models::NodeState.find(:node_id=>node_id) || Models::NodeState.new(:node_id=>node_id)
|
74
|
-
a.
|
72
|
+
a.process_event(:on_ping)
|
75
73
|
if a.new?
|
76
74
|
a.boot_token = boot_token
|
77
75
|
a.save
|
@@ -164,7 +164,7 @@ module Isono
|
|
164
164
|
# :prefetch
|
165
165
|
def register_endpoint(endpoint, app, opts={})
|
166
166
|
raise TypeError unless app.respond_to?(:call)
|
167
|
-
opts = {:exclusive=>true, :prefetch=>
|
167
|
+
opts = {:exclusive=>true, :prefetch=>1}.merge(opts)
|
168
168
|
|
169
169
|
# create receive queue for new RPC endpoint.
|
170
170
|
endpoint_proc = proc { |header, data|
|
@@ -190,13 +190,8 @@ module Isono
|
|
190
190
|
|
191
191
|
|
192
192
|
EventMachine.schedule {
|
193
|
-
ch =
|
194
|
-
|
195
|
-
node.create_channel
|
196
|
-
else
|
197
|
-
# use default channel
|
198
|
-
@amq
|
199
|
-
end
|
193
|
+
ch = node.create_channel
|
194
|
+
|
200
195
|
ch.instance_eval %Q{
|
201
196
|
def endpoint_queue
|
202
197
|
self.queue("isono.rpc.endpoint.#{endpoint}", {:exclusive=>false, :auto_delete=>true})
|
data/lib/isono/rack/job.rb
CHANGED
@@ -80,36 +80,44 @@ module Isono
|
|
80
80
|
add(:rpc, command, &blk)
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
unless builders.empty?
|
88
|
-
map_app = Rack::Map.new
|
89
|
-
builders.each { |b|
|
90
|
-
b.call(map_app, helper_context)
|
91
|
-
}
|
92
|
-
map_app
|
93
|
-
end
|
94
|
-
}
|
83
|
+
def concurrency(num)
|
84
|
+
raise ArgumentError unless num.is_a?(Fixnum)
|
85
|
+
@concurrency = num
|
86
|
+
end
|
95
87
|
|
88
|
+
def job_thread_pool(thread_pool)
|
89
|
+
raise ArgumentError unless thread_pool.is_a?(Isono::ThreadPool)
|
90
|
+
@job_thread_pool = thread_pool
|
91
|
+
end
|
92
|
+
|
93
|
+
def setup(endpoint_name, builder)
|
94
|
+
app_builder = lambda { |builder_hooks|
|
95
|
+
return nil if builder_hooks.empty?
|
96
|
+
map_app = Rack::Map.new
|
97
|
+
builder_hooks.each { |b|
|
98
|
+
b.call(map_app, builder)
|
99
|
+
}
|
100
|
+
map_app
|
101
|
+
}
|
102
|
+
|
96
103
|
app = app_builder.call(@builders[:job])
|
97
104
|
if app
|
98
|
-
|
99
|
-
|
100
|
-
|
105
|
+
builder.job_channel.register_endpoint(endpoint_name,
|
106
|
+
Rack.build do
|
107
|
+
run app
|
108
|
+
end,
|
109
|
+
{:concurrency=>@concurrency,
|
110
|
+
:thread_pool=>@job_thread_pool})
|
101
111
|
end
|
102
112
|
|
103
113
|
app = app_builder.call(@builders[:rpc])
|
104
114
|
if app
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
)
|
115
|
+
builder.rpc_channel.register_endpoint(endpoint, Rack.build do
|
116
|
+
run app
|
117
|
+
end, {:prefetch=>@concurrency})
|
109
118
|
end
|
110
119
|
end
|
111
120
|
|
112
|
-
|
113
121
|
protected
|
114
122
|
def add(type, command, &blk)
|
115
123
|
@builders[type] << lambda { |rack_map, ctx|
|
@@ -121,15 +129,33 @@ module Isono
|
|
121
129
|
def self.inherited(klass)
|
122
130
|
klass.class_eval {
|
123
131
|
@builders = {:job=>[], :rpc=>[]}
|
132
|
+
@concurrency = 1
|
133
|
+
@job_thread_pool = nil
|
124
134
|
extend BuildMethods
|
125
135
|
}
|
126
136
|
end
|
127
137
|
|
128
138
|
def initialize(node)
|
129
139
|
@node = node
|
140
|
+
@rpc_channel = NodeModules::RpcChannel.new(@node)
|
141
|
+
@job_channel = NodeModules::JobChannel.new(@node)
|
142
|
+
after_initialize
|
143
|
+
end
|
144
|
+
|
145
|
+
def job_channel
|
146
|
+
@job_channel
|
147
|
+
end
|
148
|
+
alias :job :job_channel
|
149
|
+
|
150
|
+
def rpc_channel
|
151
|
+
@rpc_channel
|
152
|
+
end
|
153
|
+
alias :rpc :rpc_channel
|
154
|
+
|
155
|
+
protected
|
156
|
+
def after_initialize
|
130
157
|
end
|
131
158
|
end
|
132
|
-
|
133
159
|
|
134
160
|
DEFAULT_MANIFEST = Manifest.new(Dir.pwd) do
|
135
161
|
load_module NodeModules::EventChannel
|
@@ -147,13 +173,15 @@ module Isono
|
|
147
173
|
class Server < Base
|
148
174
|
def initialize(builder_block)
|
149
175
|
super()
|
176
|
+
@endpoints = {}
|
150
177
|
@builder_block = builder_block
|
151
178
|
end
|
152
179
|
|
153
180
|
# DSL method
|
154
|
-
def endpoint(endpoint,
|
155
|
-
raise
|
156
|
-
|
181
|
+
def endpoint(endpoint, builder_class, *args)
|
182
|
+
raise ArgumentError unless builder_class.is_a?(Class) && builder_class < EndpointBuilder
|
183
|
+
raise "Duplicate endpoint name: #{endpoint}" if @endpoints[endpoint.to_s]
|
184
|
+
@endpoints[endpoint.to_s] = builder_class.new(@node, *args)
|
157
185
|
end
|
158
186
|
|
159
187
|
protected
|
@@ -161,6 +189,8 @@ module Isono
|
|
161
189
|
@node = Isono::Node.new(manifest)
|
162
190
|
@node.connect(@options[:amqp_server_uri]) do
|
163
191
|
self.instance_eval(&@builder_block) if @builder_block
|
192
|
+
|
193
|
+
@endpoints.each {|name, i| i.class.setup(name, i) }
|
164
194
|
end
|
165
195
|
end
|
166
196
|
|
data/lib/isono/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isono
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.14
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-08-
|
13
|
+
date: 2012-08-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: amqp
|
@@ -44,22 +44,6 @@ dependencies:
|
|
44
44
|
- - '='
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 1.0.0.beta.4
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: statemachine
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
|
-
requirements:
|
52
|
-
- - ! '>='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 1.0.0
|
55
|
-
type: :runtime
|
56
|
-
prerelease: false
|
57
|
-
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
|
-
requirements:
|
60
|
-
- - ! '>='
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: 1.0.0
|
63
47
|
- !ruby/object:Gem::Dependency
|
64
48
|
name: log4r
|
65
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,7 +172,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
188
172
|
requirements:
|
189
173
|
- - ! '>='
|
190
174
|
- !ruby/object:Gem::Version
|
191
|
-
version: 1.
|
175
|
+
version: 1.9.2
|
192
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
177
|
none: false
|
194
178
|
requirements:
|