Class: Orchestrator::Core::ModuleManager
- Inherits:
-
Object
- Object
- Orchestrator::Core::ModuleManager
- Defined in:
- lib/orchestrator/core/module_manager.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#current_user ⇒ Object
Returns the value of attribute current_user.
-
#instance ⇒ Object
readonly
Returns the value of attribute instance.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#settings ⇒ Object
readonly
Returns the value of attribute settings.
-
#stattrak ⇒ Object
readonly
Returns the value of attribute stattrak.
-
#status ⇒ Object
readonly
Returns the value of attribute status.
-
#thread ⇒ Object
readonly
Returns the value of attribute thread.
Instance Method Summary collapse
-
#add_subscription(sub) ⇒ Object
Called from subscribe and SystemProxy.subscribe always on the module thread.
-
#define_setting(name, value) ⇒ Object
Called from Core::Mixin on any thread.
- #get_scheduler ⇒ Object
-
#get_system(name) ⇒ ::Orchestrator::Core::SystemProxy
- This is called from Core::Mixin on the thread pool as the DB query will be blocking NOTE
-
Couchbase does support non-blocking gets although I think this is simpler.
-
#initialize(thread, klass, settings) ⇒ ModuleManager
constructor
A new instance of ModuleManager.
-
#inspect ⇒ Object
override the default inspect method This provides relevant information and won’t blow the stack on an error.
- #reloaded(mod) ⇒ Object
-
#setting(name) ⇒ Object
Called from Core::Mixin on any thread For Logics: instance -> system -> zones -> dependency For Device: instance -> dependency.
- #start ⇒ Object
-
#stop ⇒ Object
Should always be called on the module thread.
-
#subscribe(status, callback) ⇒ Object
Subscribe to status updates from status in the same module Called from Core::Mixin always on the module thread.
-
#trak(name, value) ⇒ Object
Called from Core::Mixin - thread safe.
-
#unsubscribe(sub) ⇒ Object
Called from Core::Mixin always on the module thread.
Constructor Details
#initialize(thread, klass, settings) ⇒ ModuleManager
Returns a new instance of ModuleManager.
4 5 6 7 8 9 10 11 12 13 14 15 |
# File 'lib/orchestrator/core/module_manager.rb', line 4 def initialize(thread, klass, settings) @thread = thread # Libuv Loop @settings = settings # Database model @klass = klass # Bit of a hack - should make testing pretty easy though @status = ::ThreadSafe::Cache.new @stattrak = @thread.observer @logger = ::Orchestrator::Logger.new(@thread, @settings) @updating = Mutex.new end |
Instance Attribute Details
#current_user ⇒ Object
Returns the value of attribute current_user.
20 21 22 |
# File 'lib/orchestrator/core/module_manager.rb', line 20 def current_user @current_user end |
#instance ⇒ Object (readonly)
Returns the value of attribute instance.
18 19 20 |
# File 'lib/orchestrator/core/module_manager.rb', line 18 def instance @instance end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
19 20 21 |
# File 'lib/orchestrator/core/module_manager.rb', line 19 def logger @logger end |
#settings ⇒ Object (readonly)
Returns the value of attribute settings.
18 19 20 |
# File 'lib/orchestrator/core/module_manager.rb', line 18 def settings @settings end |
#stattrak ⇒ Object (readonly)
Returns the value of attribute stattrak.
19 20 21 |
# File 'lib/orchestrator/core/module_manager.rb', line 19 def stattrak @stattrak end |
#status ⇒ Object (readonly)
Returns the value of attribute status.
19 20 21 |
# File 'lib/orchestrator/core/module_manager.rb', line 19 def status @status end |
#thread ⇒ Object (readonly)
Returns the value of attribute thread.
18 19 20 |
# File 'lib/orchestrator/core/module_manager.rb', line 18 def thread @thread end |
Instance Method Details
#add_subscription(sub) ⇒ Object
Called from subscribe and SystemProxy.subscribe always on the module thread
131 132 133 134 135 136 137 138 139 |
# File 'lib/orchestrator/core/module_manager.rb', line 131 def add_subscription(sub) if sub.is_a? ::Libuv::Q::Promise # Promise recursion? sub.then method(:add_subscription) else @subsciptions ||= Set.new @subsciptions.add sub end end |
#define_setting(name, value) ⇒ Object
Called from Core::Mixin on any thread
Settings updates are done on the thread pool We have to replace the structure as other threads may be reading from the old structure and the settings hash is not thread safe
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/orchestrator/core/module_manager.rb', line 175 def define_setting(name, value) defer = thread.defer thread.schedule do defer.resolve(thread.work(proc { mod = Orchestrator::Module.find(@settings.id) mod.settings[name] = value mod.save! mod })) end defer.promise.then do |db_model| @settings = db_model value # Don't leak direct access to the database model end end |
#get_scheduler ⇒ Object
79 80 81 |
# File 'lib/orchestrator/core/module_manager.rb', line 79 def get_scheduler @scheduler ||= ::Orchestrator::Core::ScheduleProxy.new(@thread) end |
#get_system(name) ⇒ ::Orchestrator::Core::SystemProxy
This is called from Core::Mixin on the thread pool as the DB query will be blocking
- NOTE
-
Couchbase does support non-blocking gets although I think this is simpler
87 88 89 90 |
# File 'lib/orchestrator/core/module_manager.rb', line 87 def get_system(name) id = ::Orchestrator::ControlSystem.bucket.get("sysname-#{name.downcase}", {quiet: true}) || name ::Orchestrator::Core::SystemProxy.new(@thread, id.to_sym, self) end |
#inspect ⇒ Object
override the default inspect method This provides relevant information and won’t blow the stack on an error
194 195 196 |
# File 'lib/orchestrator/core/module_manager.rb', line 194 def inspect "#<#{self.class}:0x#{self.__id__.to_s(16)} @thread=#{@thread.inspect} running=#{!@instance.nil?} managing=#{@klass.to_s} id=#{@settings.id}>" end |
#reloaded(mod) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/orchestrator/core/module_manager.rb', line 64 def reloaded(mod) @thread.schedule do # pass in any updated settings @settings = mod if @instance.respond_to? :on_update, true begin @instance.__send__(:on_update) rescue => e @logger.print_error(e, 'error in module update callback') end end end end |
#setting(name) ⇒ Object
Called from Core::Mixin on any thread For Logics: instance -> system -> zones -> dependency For Device: instance -> dependency
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/orchestrator/core/module_manager.rb', line 144 def setting(name) res = @settings.settings[name] if res.nil? if @settings.control_system_id sys = System.get(@settings.control_system_id) res = sys.settings[name] # Check if zones have the setting if res.nil? sys.zones.each do |zone| res = zone.settings[name] return res unless res.nil? end # Fallback to the dependency res = @settings.dependency.settings[name] end else # Fallback to the dependency res = @settings.dependency.settings[name] end end res end |
#start ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/orchestrator/core/module_manager.rb', line 45 def start return true unless @instance.nil? config = self @instance = @klass.new @instance.instance_eval { @__config__ = config } if @instance.respond_to? :on_load, true begin @instance.__send__(:on_load) rescue => e @logger.print_error(e, 'error in module load callback') end end update_running_status(true) true # for REST API rescue => e @logger.print_error(e, 'module failed to start') false end |
#stop ⇒ Object
Should always be called on the module thread
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/orchestrator/core/module_manager.rb', line 24 def stop return if @instance.nil? begin if @instance.respond_to? :on_unload, true @instance.__send__(:on_unload) end rescue => e @logger.print_error(e, 'error in module unload callback') ensure # Clean up @instance = nil @scheduler.clear if @scheduler if @subsciptions unsub = @stattrak.method(:unsubscribe) @subsciptions.each &unsub @subsciptions = nil end update_running_status(false) end end |
#subscribe(status, callback) ⇒ Object
Subscribe to status updates from status in the same module Called from Core::Mixin always on the module thread
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/orchestrator/core/module_manager.rb', line 107 def subscribe(status, callback) sub = @stattrak.subscribe({ on_thread: @thread, callback: callback, status: status.to_sym, mod_id: @settings.id.to_sym, mod: self }) add_subscription sub sub end |
#trak(name, value) ⇒ Object
Called from Core::Mixin - thread safe
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/orchestrator/core/module_manager.rb', line 93 def trak(name, value) if @status[name] != value @status[name] = value # Allows status to be updated in workers # For the most part this will run straight away @thread.schedule do @stattrak.update(@settings.id.to_sym, name, value) end end end |
#unsubscribe(sub) ⇒ Object
Called from Core::Mixin always on the module thread
120 121 122 123 124 125 126 127 128 |
# File 'lib/orchestrator/core/module_manager.rb', line 120 def unsubscribe(sub) if sub.is_a? ::Libuv::Q::Promise # Promise recursion? sub.then method(:unsubscribe) else @subsciptions.delete sub @stattrak.unsubscribe(sub) end end |