isono 0.2.13 → 0.2.14
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/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:
|