cylons 0.0.1 → 0.0.2
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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/Gemfile +3 -2
- data/Guardfile +39 -0
- data/README.md +93 -39
- data/bin/cylons +11 -12
- data/cylons.gemspec +13 -8
- data/lib/cylons.rb +43 -14
- data/lib/cylons/active_record_extensions.rb +20 -27
- data/lib/cylons/{remote_proxy.rb → agent.rb} +104 -47
- data/lib/cylons/config.rb +26 -0
- data/lib/cylons/connection.rb +11 -15
- data/lib/cylons/errors.rb +2 -1
- data/lib/cylons/local_registry.rb +5 -11
- data/lib/cylons/logging.rb +41 -0
- data/lib/cylons/railtie.rb +4 -25
- data/lib/cylons/registry_adapter.rb +10 -1
- data/lib/cylons/remote.rb +11 -22
- data/lib/cylons/remote_discovery.rb +29 -18
- data/lib/cylons/remote_pagination.rb +32 -0
- data/lib/cylons/remote_registry.rb +12 -15
- data/lib/cylons/remote_schema.rb +2 -2
- data/lib/cylons/rpc.rb +64 -72
- data/lib/cylons/service_manager.rb +30 -20
- data/lib/cylons/version.rb +1 -1
- data/spec/inventory_test_app.rb +24 -0
- data/spec/lib/cylons/connection_spec.rb +15 -0
- data/spec/lib/cylons/interface_spec.rb +7 -0
- data/spec/lib/cylons/remote_registry_spec.rb +57 -0
- data/spec/lib/cylons/service_manager_spec.rb +40 -4
- data/spec/spec_helper.rb +30 -2
- data/spec/support/inventory_test_node.rb +49 -0
- data/spec/support/schema.rb +24 -0
- metadata +181 -150
- data/lib/cylons/configuration.rb +0 -38
- data/spec/lib/cylons/remote_registry.rb +0 -7
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'dcell'
|
2
|
-
|
2
|
+
|
3
3
|
module Cylons
|
4
4
|
class RemoteDiscovery
|
5
5
|
class << self
|
@@ -7,33 +7,44 @@ module Cylons
|
|
7
7
|
attr_accessor :loaded, :loaded_remote_class_names
|
8
8
|
alias_method :loaded?, :loaded
|
9
9
|
end
|
10
|
-
|
11
|
-
def self.
|
10
|
+
|
11
|
+
def self.service_mappings
|
12
|
+
service_mapping_hash = {}
|
13
|
+
|
14
|
+
::DCell::Node.all.each do |node|
|
15
|
+
namespace = node.id
|
16
|
+
filtered_nodes = (node.actors - [:node_manager, :dcell_server, :info])
|
17
|
+
|
18
|
+
remote_class_names = filtered_nodes.select{|name| name.to_s.include?("Service") }.each do |remote_class_name|
|
19
|
+
service_mapping_hash[remote_class_name] = node.id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
service_mapping_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.namespace_for_agent(agent_name)
|
27
|
+
service_mappings["#{agent_name}Service".to_sym]
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.remote_class_names
|
31
|
+
discovered_remote_class_names = []
|
32
|
+
|
12
33
|
::DCell::Node.all.each do |node|
|
13
34
|
if node.id != ::Cylons.configuration.remote_namespace
|
14
35
|
namespace = node.id
|
15
36
|
remote_class_names = node.actors - [:node_manager, :dcell_server, :info]
|
16
37
|
remote_class_names.select{|name| name.to_s.include?("Service") }.each do |remote_class_name|
|
17
|
-
|
18
|
-
build_remote(namespace, remote_class_name)
|
38
|
+
discovered_remote_class_names << remote_class_name
|
19
39
|
end if remote_class_names.any?
|
20
40
|
end
|
21
41
|
end
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.build_remote(namespace, remote_class_name)
|
27
|
-
proxy_class_name = remote_class_name.to_s.gsub('Service', '')
|
28
|
-
Object.const_set(proxy_class_name, Class.new(Cylons::RemoteProxy))
|
29
|
-
|
30
|
-
proxy_class = proxy_class_name.constantize
|
31
|
-
proxy_class.load_schema
|
32
|
-
proxy_class.remote = ::DCell::Node[namespace][remote_class_name]
|
42
|
+
|
43
|
+
discovered_remote_class_names
|
33
44
|
end
|
34
|
-
|
45
|
+
|
35
46
|
def self.remote_proxy_class_name(namespace, remote_class_name)
|
36
47
|
"#{namespace}::#{remote_class_name.to_s}".gsub('Service', '')
|
37
48
|
end
|
38
49
|
end
|
39
|
-
end
|
50
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Cylons
|
2
|
+
module RemotePagination
|
3
|
+
extend ::ActiveSupport::Concern
|
4
|
+
|
5
|
+
META_METHODS = [
|
6
|
+
:total_pages,
|
7
|
+
:current_page
|
8
|
+
].freeze
|
9
|
+
|
10
|
+
SEARCH_OPTION_KEYS = [:opts, :options].freeze
|
11
|
+
MAX_PER_PAGE = 1000
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def search(params = {})
|
15
|
+
search_options = params.extract!(*SEARCH_OPTION_KEYS)
|
16
|
+
|
17
|
+
search_options.delete_if {|k,v| v.nil? }
|
18
|
+
|
19
|
+
query_scope = params.inject(all) do |query, hash_pair|
|
20
|
+
query.__send__("by_#{hash_pair[0]}", hash_pair[1]).all
|
21
|
+
end.all
|
22
|
+
|
23
|
+
if search_options.present?
|
24
|
+
query_scope.paginate(:page => search_options[:options][:page], :per_page => search_options[:options][:per_page])
|
25
|
+
else
|
26
|
+
query_scope.paginate(:page => 1, :per_page => MAX_PER_PAGE)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -6,44 +6,41 @@ module Cylons
|
|
6
6
|
@remotes ||= []
|
7
7
|
@loaded_remotes ||= []
|
8
8
|
@remote_schemas ||= {}
|
9
|
-
|
9
|
+
|
10
10
|
class << self
|
11
11
|
attr_accessor :remotes, :loaded_remotes
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def self.clear_registry
|
15
15
|
::DCell.registry.instance_variable_get("@global_registry").clear
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def self.register(klass)
|
19
|
+
::Cylons::Connection.connect unless ::Cylons::Connection.connected?
|
19
20
|
@remotes << klass
|
20
21
|
end
|
21
|
-
|
22
|
-
def self.register_class?(namespaced_class_name)
|
23
|
-
!defined?(namespaced_class_name.constantize)
|
24
|
-
end
|
25
|
-
|
22
|
+
|
26
23
|
def self.register_schemas
|
27
24
|
@remotes.each do |remote|
|
28
25
|
::Cylons.logger.info remote
|
29
26
|
register_remote_schema(remote)
|
30
27
|
end
|
31
28
|
end
|
32
|
-
|
29
|
+
|
33
30
|
def self.remote_schemas
|
34
31
|
::DCell::Global.keys
|
35
32
|
end
|
36
|
-
|
33
|
+
|
37
34
|
def self.register_remote_schema(klass)
|
38
35
|
::DCell::Global["#{klass.name.downcase}_schema".to_sym] = ::Cylons::RemoteSchema.new(klass)
|
39
36
|
end
|
40
|
-
|
37
|
+
|
41
38
|
def self.remote_schema?(name)
|
42
|
-
::DCell::Global.
|
39
|
+
::DCell::Global.keys.include? "#{name}_schema".to_sym
|
43
40
|
end
|
44
|
-
|
41
|
+
|
45
42
|
def self.get_remote_schema(name)
|
46
43
|
::DCell::Global["#{name}_schema".to_sym]
|
47
44
|
end
|
48
|
-
end
|
49
|
-
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/cylons/remote_schema.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Cylons
|
2
2
|
class RemoteSchema
|
3
3
|
attr_accessor :remote_associations, :remote_attributes, :remote_search_scopes, :remote_klass
|
4
|
-
|
4
|
+
|
5
5
|
def initialize(klass)
|
6
6
|
@remote_attributes ||= klass.attribute_names
|
7
7
|
@remote_associations ||= klass.remote_associations
|
@@ -9,4 +9,4 @@ module Cylons
|
|
9
9
|
@remote_klass ||= klass.name.downcase.to_sym
|
10
10
|
end
|
11
11
|
end
|
12
|
-
end
|
12
|
+
end
|
data/lib/cylons/rpc.rb
CHANGED
@@ -1,86 +1,78 @@
|
|
1
|
-
require 'ransack'
|
2
1
|
module Cylons
|
3
2
|
module RPC
|
4
3
|
extend ::ActiveSupport::Concern
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
execute(:all)
|
12
|
-
end
|
13
|
-
|
14
|
-
def create(params)
|
15
|
-
execute(:create, params)
|
16
|
-
end
|
17
|
-
|
18
|
-
def destroy(id)
|
19
|
-
execute(:destroy, id)
|
20
|
-
end
|
21
|
-
|
22
|
-
def execute(rpc_method, request_params = {})
|
23
|
-
begin
|
24
|
-
@last_response = self.class.model.send(rpc_method.to_sym, request_params)
|
25
|
-
rescue => e
|
26
|
-
puts e.inspect
|
27
|
-
@last_response = {:error => e.message}
|
28
|
-
end
|
4
|
+
include ::ActiveModel::Dirty
|
5
|
+
include ::Cylons::Attributes
|
6
|
+
|
7
|
+
#need to wrap because to_a will leak connections otherwise
|
8
|
+
def all
|
9
|
+
::ActiveRecord::Base.connection_pool.with_connection do
|
10
|
+
execute(:all).to_a
|
29
11
|
end
|
30
|
-
|
31
|
-
|
12
|
+
end
|
13
|
+
|
14
|
+
def create(params)
|
15
|
+
execute(:create, params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def destroy(id)
|
19
|
+
execute(:destroy, id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute(rpc_method, *args)
|
23
|
+
puts Thread.current.object_id
|
24
|
+
|
25
|
+
::ActiveRecord::Base.connection_pool.with_connection do
|
26
|
+
puts ::ActiveRecord::Base.connection_pool.instance_variable_get("@connections").size
|
32
27
|
begin
|
33
|
-
|
28
|
+
if args.any?
|
29
|
+
@last_response = self.class.model.send(rpc_method.to_sym, *args)
|
30
|
+
else
|
31
|
+
@last_response = self.class.model.send(rpc_method.to_sym)
|
32
|
+
end
|
33
|
+
|
34
|
+
@last_response
|
34
35
|
rescue => e
|
35
36
|
puts e.inspect
|
36
|
-
puts e.message
|
37
|
-
puts @last_response.inspect
|
38
37
|
@last_response = {:error => e.message}
|
39
38
|
end
|
40
39
|
end
|
41
|
-
|
42
|
-
def find(id)
|
43
|
-
execute(:find, id)
|
44
|
-
end
|
45
|
-
|
46
|
-
def first
|
47
|
-
execute(:first)
|
48
|
-
end
|
49
|
-
|
50
|
-
def first_or_create(params)
|
51
|
-
execute(:first_or_create, params)
|
52
|
-
end
|
40
|
+
end
|
53
41
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
42
|
+
def find(id)
|
43
|
+
execute(:find, id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def first
|
47
|
+
execute(:first)
|
48
|
+
end
|
49
|
+
|
50
|
+
def first_or_create(params)
|
51
|
+
execute(:first_or_create, params)
|
52
|
+
end
|
53
|
+
|
54
|
+
def last
|
55
|
+
execute(:last)
|
56
|
+
end
|
57
|
+
|
58
|
+
def search(params)
|
59
|
+
response = execute(:search, params)
|
60
|
+
end
|
61
|
+
|
62
|
+
def scope_by(params)
|
63
|
+
execute(:scope_by, params)
|
64
|
+
end
|
65
|
+
|
66
|
+
def save(id = nil, attributes)
|
67
|
+
if(id)
|
68
|
+
execute(:update, id, attributes)
|
69
|
+
else
|
70
|
+
execute(:create, attributes)
|
79
71
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
72
|
+
end
|
73
|
+
|
74
|
+
def update(attributes)
|
75
|
+
execute(:update, attributes.keys, attributes.values)
|
84
76
|
end
|
85
77
|
end
|
86
|
-
end
|
78
|
+
end
|
@@ -4,41 +4,51 @@ require 'cylons/remote_registry'
|
|
4
4
|
module Cylons
|
5
5
|
class ServiceManager
|
6
6
|
def self.start
|
7
|
-
::Cylons.logger.info "
|
8
|
-
puts "LOADING REMOTES"
|
9
|
-
::Cylons::RemoteDiscovery.load_remotes unless ::Cylons::RemoteDiscovery.loaded?
|
10
|
-
puts "STARTING LOCAL REMOTE SERVICES"
|
11
|
-
::Cylons.logger.info "STARTING LOCAL REMOTE SERVICES"
|
7
|
+
::Cylons.logger.info "STARTING CYLON SERVICES"
|
12
8
|
start_services
|
13
9
|
end
|
14
|
-
|
10
|
+
|
11
|
+
#todo: split supervision and building
|
15
12
|
def self.start_service(model_klass)
|
16
|
-
|
17
|
-
|
13
|
+
unless service_defined?(model_klass)
|
14
|
+
service_klass = build_service(model_klass)
|
15
|
+
|
16
|
+
service_klass.supervise_as service_klass.name.to_sym
|
17
|
+
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def self.build_service(model_klass)
|
21
21
|
proxy_service_class_name = "#{model_klass.name}Service"
|
22
|
-
Object.const_set(proxy_service_class_name, Class.new(::Cylons::Service))
|
22
|
+
::Object.const_set(proxy_service_class_name, ::Class.new(::Cylons::Service))
|
23
23
|
service_klass = proxy_service_class_name.constantize
|
24
|
-
|
25
24
|
service_klass.model = model_klass
|
26
|
-
|
25
|
+
|
26
|
+
::Cylons.logger.info "REGISTERING_SERVICE_FOR #{model_klass}"
|
27
|
+
|
27
28
|
service_klass
|
28
29
|
end
|
29
|
-
|
30
|
+
|
31
|
+
def self.service_defined?(model_klass)
|
32
|
+
proxy_service_class_name = "#{model_klass.name}Service"
|
33
|
+
|
34
|
+
const_defined?(:"#{proxy_service_class_name}")
|
35
|
+
end
|
36
|
+
|
30
37
|
def self.start_services
|
31
38
|
::Cylons::RemoteRegistry.remotes.each do |remote|
|
32
39
|
start_service(remote)
|
33
40
|
end if remotes?
|
34
41
|
end
|
35
|
-
|
36
|
-
def self.service_klass_name
|
37
|
-
"#{klass.name}Service"
|
38
|
-
end
|
39
|
-
|
42
|
+
|
40
43
|
def self.remotes?
|
41
44
|
::Cylons::RemoteRegistry.remotes.any?
|
42
|
-
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.stop
|
48
|
+
::Cylons::RemoteRegistry.remotes.each do |remote|
|
49
|
+
::Cylons.logger.info{ "Shutting Down #{remote.name}"}
|
50
|
+
remote.stop
|
51
|
+
end
|
52
|
+
end
|
43
53
|
end
|
44
|
-
end
|
54
|
+
end
|
data/lib/cylons/version.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
# The DCell specs start a completely separate Ruby VM running this code
|
2
|
+
# for complete integration testing using 0MQ over TCP
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
require 'active_record'
|
7
|
+
Bundler.setup
|
8
|
+
|
9
|
+
require 'cylons'
|
10
|
+
|
11
|
+
ENV["RPC"] = "1"
|
12
|
+
|
13
|
+
::Cylons.configure do |config|
|
14
|
+
#if you are running multiple machines, connect to the ZK registry machine via:
|
15
|
+
# config.registry_address = "X.X.X.X"
|
16
|
+
config.remote_namespace = "InventoryTest"
|
17
|
+
# config.registry_adapter = :zk
|
18
|
+
end
|
19
|
+
|
20
|
+
class Product < ActiveRecord::Base
|
21
|
+
include ::Cylons::Remote
|
22
|
+
end
|
23
|
+
|
24
|
+
::Cylons::ServiceManager.start
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ::Cylons::Connection do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
its(:connected) { should be true }
|
7
|
+
|
8
|
+
describe ".validate_configuration" do
|
9
|
+
it "should raise error if no remote namespace present" do
|
10
|
+
::Cylons.configuration.remote_namespace.stub(:present?).and_return(false)
|
11
|
+
expect{ subject.validate_configuration }.to raise_error ::Cylons::RemoteNamespaceNotSet
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|