cylons 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  require 'dcell'
2
- require 'cylons/remote_proxy'
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.load_remotes
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
- puts "Building Remote For: #{remote_class_name}"
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
- @loaded = true
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.has_key? "#{name}_schema".to_sym
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
@@ -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
@@ -1,86 +1,78 @@
1
- require 'ransack'
2
1
  module Cylons
3
2
  module RPC
4
3
  extend ::ActiveSupport::Concern
5
-
6
- included do
7
- include ::ActiveModel::Dirty
8
- include ::Cylons::Attributes
9
-
10
- def all
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
- def execute_with_args(rpc_method, *args)
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
- @last_response = self.class.model.send(rpc_method.to_sym, *args)
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
- def last
55
- execute(:last)
56
- end
57
-
58
- #todo: Refactor this, hacky
59
- def search(params)
60
- response = execute(:search, params)
61
-
62
- if response.respond_to?(:result)
63
- return response.result.to_a
64
- else
65
- return response
66
- end
67
- end
68
-
69
- def scope_by(params)
70
- execute(:scope_by, params).to_a
71
- end
72
-
73
- def save(id = nil, attributes)
74
- if(id)
75
- execute_with_args(:update, id, attributes)
76
- else
77
- execute(:create, attributes)
78
- end
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
- def update(attributes)
82
- execute_with_args(:update, attributes.keys, attributes.values)
83
- end
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 "LOADING REMOTES"
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
- service_klass = build_service(model_klass)
17
- service_klass.supervise_as service_klass.name.to_sym
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
- puts "REGISTERING_SERVICE_FOR #{model_klass}"
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
@@ -1,3 +1,3 @@
1
1
  module Cylons
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Cylons::Interface do
4
+ subject { described_class }
5
+
6
+ its(:primary) { should eq ::IPSocket.getaddress(::Socket.gethostname) }
7
+ end