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.
@@ -1,69 +1,68 @@
1
1
  require 'cylons/associations'
2
2
 
3
3
  module Cylons
4
-
4
+
5
5
  #this is the local application remote which is dynamically built, from the registry
6
- class RemoteProxy
6
+ class Agent
7
7
  include ::ActiveModel::Dirty
8
8
  include ::ActiveModel::AttributeMethods
9
- include ActiveAttr::Model
10
- include ActiveAttr::MassAssignment
9
+ include ::ActiveAttr::Model
10
+ include ::ActiveAttr::MassAssignment
11
11
  include ::Cylons::Attributes
12
- extend ::Cylons::Associations::ClassMethods
13
-
12
+ include ::Cylons::Associations
13
+
14
+ class_attribute :unsucessful_remote_connection_attempts
15
+ self.unsucessful_remote_connection_attempts ||= 0
16
+
17
+ class << self
18
+ attr_accessor :schema, :built
19
+ end
20
+
21
+ @built = false
22
+
23
+ def self.inherited(subklass)
24
+ ::Cylons.connect unless ::Cylons.connected?
25
+ end
26
+
27
+ def self.build_agent
28
+ load_schema
29
+ @built = true
30
+ end
31
+
32
+ def self.service_class_name
33
+ "#{name}Service"
34
+ end
35
+
14
36
  def self.load_schema
15
- @schema = ::Cylons::RemoteRegistry.get_remote_schema(self.name.downcase)
16
-
37
+ ::Cylons.logger.debug { "Loading schema for #{name}" }
38
+
39
+ @schema = ::Cylons::RemoteRegistry.get_remote_schema(name.downcase)
40
+
17
41
  @schema.remote_attributes.each do |remote_attribute|
18
42
  attribute remote_attribute.to_sym
19
43
  end
20
-
44
+
21
45
  @schema.remote_associations.each do |association_hash|
22
46
  __send__("build_remote_#{association_hash[:association_type]}_association", association_hash)
23
47
  end
24
48
  end
25
-
26
- class << self
27
- attr_accessor :remote, :schema
28
- end
29
-
30
- attr_accessor :errors
31
-
32
- def destroy
33
- return unless self.attributes["id"]
34
- result = self.class.remote.destroy(self.attributes["id"])
35
- end
36
-
37
- #have to manually update attributes if id wasnt set, i believe attr_accessible oddity so maybe can rip out later
38
- def save
39
- if self.attributes["id"]
40
- result = self.class.remote.save(self.attributes["id"], self.attributes.with_indifferent_access.slice(*self.changed))
41
- self.changed_attributes.clear
42
- else
43
- result = self.class.remote.save(nil, self.attributes.with_indifferent_access.slice(*self.changed))
44
-
45
- if result.errors.messages.present?
46
- self.assign_attributes({:errors => result.errors})
47
- else
48
- self.assign_attributes(result.attributes)
49
- end
50
- end
51
-
52
- result
53
- end
54
49
 
55
50
  def self.all
56
51
  remote.all
57
52
  end
58
-
53
+
54
+ def self.agent_namespace
55
+ @agent_namespace ||= ::Cylons::RemoteDiscovery.namespace_for_agent(self.name)
56
+ end
57
+
59
58
  def self.count
60
59
  remote.count
61
60
  end
62
-
61
+
63
62
  def self.first
64
63
  remote.first
65
64
  end
66
-
65
+
67
66
  def self.find(id)
68
67
  remote.find(id)
69
68
  end
@@ -71,29 +70,87 @@ module Cylons
71
70
  def self.last
72
71
  remote.last
73
72
  end
74
-
73
+
75
74
  def self.create(params)
76
75
  remote.create(params)
77
76
  end
78
-
77
+
79
78
  def self.search(params)
80
79
  remote.search(params)
81
80
  end
82
-
81
+
83
82
  def self.scope_by(params)
84
83
  remote.scope_by(params)
85
84
  end
86
-
85
+
87
86
  def self.first_or_create(params)
88
87
  result = remote.scope_by(params).first
89
88
  result = remote.create(params) unless result.present?
90
89
  result
91
90
  end
92
-
91
+
93
92
  def self.first_or_initialize(params)
94
93
  result = remote.scope_by(params).first
95
94
  result ||= remote.new(params) unless result.present?
96
95
  result
97
96
  end
97
+
98
+ def self.remote
99
+ remote_connection_failed! unless remote?
100
+
101
+ build_agent unless built
102
+
103
+ ::DCell::Node[agent_namespace][service_class_name.to_sym]
104
+ end
105
+
106
+ def self.remote?
107
+ agent_namespace && remote_application? && remote_service?
108
+ end
109
+
110
+ def self.remote_application?
111
+ ::DCell::Node.all.any?{ |node|
112
+ node.id == agent_namespace
113
+ }
114
+ end
115
+
116
+ def self.remote_service?
117
+ ::DCell::Node[agent_namespace].actors.include?(service_class_name.to_sym)
118
+ end
119
+
120
+ def self.remote_connection_failed!
121
+ if self.unsucessful_remote_connection_attempts > ::Cylons.config.remote_connection_failure_threshold
122
+ self.unsucessful_remote_connection_attempts = 0
123
+ raise ::Cylons::CylonsRemoteServiceNotFound, "#{service_class_name} not found"
124
+ else
125
+ sleep(::Cylons.config.remote_connection_failure_timeout)
126
+ self.unsucessful_remote_connection_attempts += 1
127
+ remote_connection_failed! unless remote?
128
+ end
129
+ end
130
+
131
+ attr_accessor :errors
132
+
133
+ def destroy
134
+ return unless self.attributes["id"]
135
+ result = self.class.remote.destroy(self.attributes["id"])
136
+ end
137
+
138
+ #have to manually update attributes if id wasnt set, i believe attr_accessible oddity so maybe can rip out later
139
+ def save
140
+ if self.attributes["id"]
141
+ result = self.class.remote.save(self.attributes["id"], self.attributes.with_indifferent_access.slice(*self.changed))
142
+ self.changed_attributes.clear
143
+ else
144
+ result = self.class.remote.save(nil, self.attributes.with_indifferent_access.slice(*self.changed))
145
+
146
+ if result.errors.messages.present?
147
+ self.assign_attributes({:errors => result.errors})
148
+ else
149
+ self.assign_attributes(result.attributes)
150
+ end
151
+ end
152
+
153
+ result
154
+ end
98
155
  end
99
- end
156
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_support/ordered_options'
2
+ require 'cylons'
3
+ require 'cylons/registry_adapter'
4
+
5
+ module Cylons
6
+ class Config < ::ActiveSupport::InheritableOptions
7
+ def initialize(*args)
8
+ super(*args)
9
+
10
+ self[:address] ||= ::Cylons::Interface.primary
11
+ self[:port] ||= (9000 + rand(100))
12
+ self[:logger] ||= ::Cylons::Logging.logger
13
+ self[:model_paths] ||= nil
14
+ self[:registry] ||= nil
15
+ self[:registry_adapter] ||= :zk
16
+ self[:registry_port] ||= nil
17
+ self[:remote_namespace] ||= nil
18
+ self[:remote_connection_failure_timeout] ||= 10
19
+ self[:remote_connection_failure_threshold] ||= 2
20
+ end
21
+
22
+ def registry
23
+ @registry ||= ::Cylons::RegistryAdapter.send(self[:registry_adapter])
24
+ end
25
+ end
26
+ end
@@ -5,40 +5,36 @@ module Cylons
5
5
  class << self
6
6
  @connected ||= false
7
7
  attr_accessor :connected
8
-
8
+
9
9
  alias_method :connected?, :connected
10
10
  end
11
-
11
+
12
12
  def self.validate_configuration
13
13
  raise ::Cylons::RemoteNamespaceNotSet unless ::Cylons.configuration.remote_namespace.present?
14
14
  end
15
-
16
- #todo: FixMe
17
- #super hacky.. pass in SKIP_CYLONS=true when running rake tasks for now, ew
18
- def self.connect?
19
- ENV['SKIP_CYLONS'].present?
20
- end
21
-
15
+
22
16
  def self.connect
23
- return if connect?
17
+ return if ::Cylons.silence?
18
+
24
19
  validate_configuration
20
+
25
21
  ::Cylons.logger.info "STARTING DCELL FOR #{::Cylons.configuration.remote_namespace} NOW"
26
-
22
+
27
23
  ::Cylons.logger.info "Cylons attempting to connect to registry at #{node_address}"
28
24
 
29
25
  ::DCell.start :id => ::Cylons.configuration.remote_namespace,
30
26
  :addr => node_address,
31
27
  :registry => registry_hash
32
-
28
+
33
29
  @connected = true
34
30
  end
35
-
31
+
36
32
  def self.node_address
37
33
  "tcp://#{::Cylons.configuration.address}:#{::Cylons.configuration.port}"
38
34
  end
39
-
35
+
40
36
  def self.registry_hash
41
37
  ::Cylons.configuration.registry
42
38
  end
43
39
  end
44
- end
40
+ end
@@ -2,10 +2,11 @@ module Cylons
2
2
  class CylonsError < StandardError; end
3
3
  class CylonsConfigurationError < CylonsError; end
4
4
  class CylonsRemoteError < CylonsError; end
5
+ class CylonsRemoteServiceNotFound < CylonsError; end
5
6
  class CylonsRemoteProxyError < CylonsError; end
6
7
  class CylonsRecordNotFound < CylonsRemoteError; end
7
8
  class InvalidRegistryAdapter < CylonsConfigurationError; end
8
9
  class CouldNotConnectToRegistry < CylonsConfigurationError; end
9
10
  class RemoteNamespaceNotSet < CylonsConfigurationError; end
10
11
  class HowDoYouKillThatWhichHasNoLife < CylonsRemoteProxyError; end
11
- end
12
+ end
@@ -4,27 +4,21 @@ require 'cylons/remote_registry'
4
4
 
5
5
  module Cylons
6
6
  class LocalRegistry
7
-
8
7
  @remotes ||= []
9
8
  @loaded_remotes ||= []
10
-
9
+
11
10
  class << self
12
11
  attr_accessor :remotes, :loaded_remotes
13
12
  end
14
-
13
+
15
14
  def self.register(klass)
16
15
  @remotes << klass
17
16
  end
18
-
19
- def self.register_class?(namespaced_class_name)
20
- !defined?(namespaced_class_name.constantize)
21
- end
22
-
17
+
23
18
  def self.register_remote_schemas
24
19
  @remotes.each do |remote|
25
20
  ::Cylons::RemoteRegistry.register_remote_schema(remote)
26
21
  end
27
22
  end
28
-
29
- end
30
- end
23
+ end
24
+ end
@@ -0,0 +1,41 @@
1
+ require 'logger'
2
+
3
+ module Cylons
4
+ module Logging
5
+ def self.initialize_logger(log_target=$stdout, log_level=::Logger::INFO)
6
+ @counter ||= 0
7
+ @counter = @counter + 1
8
+ @logger = ::Logger.new(log_target)
9
+ @logger.level = log_level
10
+ @logger
11
+ end
12
+
13
+ def self.logger
14
+ defined?(@logger) ? @logger : initialize_logger
15
+ end
16
+
17
+ def self.logger=(new_logger)
18
+ @logger = new_logger
19
+ end
20
+
21
+ def logger
22
+ ::Cylons::Logging.logger
23
+ end
24
+
25
+ def log_exception(ex)
26
+ logger.error { ex.message }
27
+ logger.error { ex.backtrace[0..5].join("\n") }
28
+ logger.debug { ex.backtrace.join("\n") }
29
+ end
30
+
31
+ def log_signature
32
+ @_log_signature ||= "[#{self.class == Class ? self.name : self.class.name}]"
33
+ end
34
+
35
+ def sign_message(message)
36
+ "#{log_signature} #{message}"
37
+ end
38
+ end
39
+ end
40
+
41
+ # Taken from [protobuf](https://github.com/localshred/protobuf)
@@ -2,37 +2,16 @@ require 'cylons'
2
2
  require 'rails'
3
3
  require 'rails/railtie'
4
4
  require 'active_record'
5
- require 'ransack'
6
- require 'ransack/search'
7
- require 'ransack/adapters/active_record/base'
8
- require 'will_paginate'
5
+ require 'will_paginate/array'
9
6
 
10
7
  module Cylons
11
8
  class Railtie < ::Rails::Railtie
12
- config.after_initialize do
13
- ::Cylons::RemoteDiscovery.load_remotes unless ::Cylons.silence? || ::Cylons::RemoteDiscovery.loaded?
14
- end
15
-
16
9
  ::ActiveSupport.on_load(:cylons) do
17
10
  ::Cylons::Connection.connect unless ::Cylons.silence? || ::Cylons::RemoteDiscovery.loaded? || ::Cylons::Connection.connected?
18
- ::Cylons::RemoteDiscovery.load_remotes unless ::Cylons.silence? || ::Cylons::RemoteDiscovery.loaded?
19
- end
20
-
21
- #todo: overwrite ransack search method to auto paginate by default, or pull ransack out..
11
+ end if ::Cylons.connect?
12
+
22
13
  ::ActiveSupport.on_load(:active_record) do
23
- ::ActiveRecord::Base.extend ::Ransack::Adapters::ActiveRecord::Base
24
14
  require 'will_paginate/active_record'
25
-
26
- case ::ActiveRecord::VERSION::STRING
27
- when /^3\.0\./
28
- require 'ransack/adapters/active_record/3.0/context'
29
- when /^3\.1\./
30
- require 'ransack/adapters/active_record/3.1/context'
31
- when /^3\.2\./
32
- require 'ransack/adapters/active_record/3.2/context'
33
- else
34
- require 'ransack/adapters/active_record/context'
35
- end
36
15
  end
37
16
  end
38
- end
17
+ end
@@ -15,8 +15,17 @@ module Cylons
15
15
  def self.zk(options = {})
16
16
  zk_registry_hash = zk_defaults.dup
17
17
  zk_registry_hash[:server] = ::Cylons.configuration.registry_address if ::Cylons.configuration.registry_address
18
- zk_registry_hash[:server] = ::Cylons.configuration.registry_port if ::Cylons.configuration.registry_port
18
+ zk_registry_hash[:registry_port] = ::Cylons.configuration.registry_port if ::Cylons.configuration.registry_port
19
19
  zk_registry_hash
20
20
  end
21
+
22
+ def self.redis_defaults
23
+ {:adapter => 'redis', :port => 6379, :address => "127.0.0.1"}
24
+ end
25
+
26
+ def self.redis(options = {})
27
+ redis_registry_hash = redis_defaults.dup
28
+ redis_registry_hash
29
+ end
21
30
  end
22
31
  end
@@ -1,29 +1,18 @@
1
1
  require 'cylons/remote_registry'
2
2
  require 'cylons/active_record_extensions'
3
3
 
4
- #todo: fix
5
- #think RemoteRegistry needs to be split into a local registry, which the remote registry
6
- #is pushed information to, or pulls information from, because the damn dcell wont stop
7
- #trying to connect or throwing not configured errors when rake tasks and what not,
8
- #need complete separation of local/remote
9
- #update, think I mostly fixed issue but leaving note here becaue better separation
10
- #still needs to be done.
11
4
  module Cylons
12
5
  module Remote
13
-
14
- def self.included(klass)
15
- klass.class_eval do
16
- @remote_associations ||= []
17
-
18
- class << self
19
- attr_accessor :remote_associations
20
- end
21
-
22
- extend ::Cylons::ActiveRecordExtensions::ClassMethods
23
- extend ::Cylons::Associations::ClassMethods
24
-
25
- ::Cylons::RemoteRegistry.register(klass)
26
- end
6
+ extend ::ActiveSupport::Concern
7
+
8
+ include ::Cylons::ActiveRecordExtensions
9
+ include ::Cylons::Associations
10
+
11
+ included do
12
+ class_attribute :remote_associations
13
+ self.remote_associations = []
14
+
15
+ ::Cylons::RemoteRegistry.register(self)
27
16
  end
28
17
  end
29
- end
18
+ end