Class: OpenC3::ReactionModel
- Defined in:
- lib/openc3/models/reaction_model.rb
Constant Summary collapse
- PRIMARY_KEY =
'__openc3__reaction'.freeze
- SCRIPT_REACTION =
'script'.freeze
- COMMAND_REACTION =
'command'.freeze
- NOTIFY_REACTION =
'notify'.freeze
- ACTION_TYPES =
[SCRIPT_REACTION, COMMAND_REACTION, NOTIFY_REACTION]
Instance Attribute Summary collapse
-
#actions ⇒ Object
Returns the value of attribute actions.
-
#enabled ⇒ Object
readonly
Returns the value of attribute enabled.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#scope ⇒ Object
readonly
Returns the value of attribute scope.
-
#snooze ⇒ Object
Returns the value of attribute snooze.
-
#snoozed_until ⇒ Object
readonly
Returns the value of attribute snoozed_until.
-
#triggerLevel ⇒ Object
Returns the value of attribute triggerLevel.
-
#triggers ⇒ Object
Returns the value of attribute triggers.
-
#username ⇒ Object
Returns the value of attribute username.
Attributes inherited from Model
Class Method Summary collapse
-
.all(scope:) ⇒ Array<Hash>
All the Key, Values stored under the name key.
- .create_unique_name(scope:) ⇒ Object
-
.delete(name:, scope:) ⇒ Object
Check dependents before delete.
-
.from_json(json, name:, scope:) ⇒ ReactionModel
Model generated from the passed JSON.
-
.get(name:, scope:) ⇒ ReactionModel
Return the object with the name at.
-
.names(scope:) ⇒ Array<String>
All the uuids stored under the name key.
Instance Method Summary collapse
-
#as_json(*a) ⇒ Hash
Generated from the ReactionModel.
- #awaken ⇒ Object
- #create ⇒ Object
- #create_microservice(topics:) ⇒ Object
- #deploy ⇒ Object
-
#initialize(name:, scope:, snooze:, actions:, triggers:, triggerLevel:, enabled: true, snoozed_until: nil, username: nil, updated_at: nil) ⇒ ReactionModel
constructor
A new instance of ReactionModel.
-
#notify(kind:) ⇒ Object
-
update the redis stream / reaction topic that something has changed.
- #notify_disable ⇒ Object
- #notify_enable ⇒ Object
- #notify_execute ⇒ Object
- #sleep ⇒ Object
- #undeploy ⇒ Object
- #update ⇒ Object
- #validate_actions(actions) ⇒ Object
- #validate_level(level) ⇒ Object
- #validate_snooze(snooze) ⇒ Object
- #validate_triggers(triggers) ⇒ Object
- #verify_triggers ⇒ Object
Methods inherited from Model
#check_disable_erb, #destroy, #destroyed?, filter, find_all_by_plugin, get_all_models, get_model, handle_config, set, store, store_queued
Constructor Details
#initialize(name:, scope:, snooze:, actions:, triggers:, triggerLevel:, enabled: true, snoozed_until: nil, username: nil, updated_at: nil) ⇒ ReactionModel
Returns a new instance of ReactionModel.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/openc3/models/reaction_model.rb', line 87 def initialize( name:, scope:, snooze:, actions:, triggers:, triggerLevel:, enabled: true, snoozed_until: nil, username: nil, updated_at: nil ) super("#{scope}#{PRIMARY_KEY}", name: name, scope: scope) @microservice_name = "#{scope}__OPENC3__REACTION" @enabled = enabled @snoozed_until = snoozed_until @triggerLevel = validate_level(triggerLevel) @snooze = validate_snooze(snooze) @actions = validate_actions(actions) @triggers = validate_triggers(triggers) @username = username @updated_at = updated_at end |
Instance Attribute Details
#actions ⇒ Object
Returns the value of attribute actions.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def actions @actions end |
#enabled ⇒ Object (readonly)
Returns the value of attribute enabled.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def enabled @enabled end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def name @name end |
#scope ⇒ Object (readonly)
Returns the value of attribute scope.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def scope @scope end |
#snooze ⇒ Object
Returns the value of attribute snooze.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def snooze @snooze end |
#snoozed_until ⇒ Object (readonly)
Returns the value of attribute snoozed_until.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def snoozed_until @snoozed_until end |
#triggerLevel ⇒ Object
Returns the value of attribute triggerLevel.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def triggerLevel @triggerLevel end |
#triggers ⇒ Object
Returns the value of attribute triggers.
84 85 86 |
# File 'lib/openc3/models/reaction_model.rb', line 84 def triggers @triggers end |
#username ⇒ Object
Returns the value of attribute username.
85 86 87 |
# File 'lib/openc3/models/reaction_model.rb', line 85 def username @username end |
Class Method Details
.all(scope:) ⇒ Array<Hash>
Returns All the Key, Values stored under the name key.
57 58 59 |
# File 'lib/openc3/models/reaction_model.rb', line 57 def self.all(scope:) super("#{scope}#{PRIMARY_KEY}") end |
.create_unique_name(scope:) ⇒ Object
39 40 41 42 43 44 45 46 |
# File 'lib/openc3/models/reaction_model.rb', line 39 def self.create_unique_name(scope:) reaction_names = self.names(scope: scope) # comes back sorted num = 1 # Users count with 1 if reaction_names[-1] num = reaction_names[-1][5..-1].to_i + 1 end return "REACT#{num}" end |
.delete(name:, scope:) ⇒ Object
Check dependents before delete.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/openc3/models/reaction_model.rb', line 67 def self.delete(name:, scope:) model = self.get(name: name, scope: scope) if model.nil? raise ReactionInputError.new "reaction '#{name}' does not exist" end model.triggers.each do | trigger | trigger_model = TriggerModel.get(name: trigger['name'], group: trigger['group'], scope: scope) trigger_model.update_dependents(dependent: name, remove: true) trigger_model.update() end Store.hdel("#{scope}#{PRIMARY_KEY}", name) # No notification as this is only called via reaction_controller which already notifies # undeploy only actually runs if no reactions are left model.undeploy() end |
.from_json(json, name:, scope:) ⇒ ReactionModel
Returns Model generated from the passed JSON.
271 272 273 274 275 |
# File 'lib/openc3/models/reaction_model.rb', line 271 def self.from_json(json, name:, scope:) json = JSON.parse(json, :allow_nan => true, :create_additions => true) if String === json raise "json data is nil" if json.nil? self.new(**json.transform_keys(&:to_sym), name: name, scope: scope) end |
.get(name:, scope:) ⇒ ReactionModel
Return the object with the name at
49 50 51 52 53 54 |
# File 'lib/openc3/models/reaction_model.rb', line 49 def self.get(name:, scope:) json = super("#{scope}#{PRIMARY_KEY}", name: name) unless json.nil? self.from_json(json, name: name, scope: scope) end end |
.names(scope:) ⇒ Array<String>
Returns All the uuids stored under the name key.
62 63 64 |
# File 'lib/openc3/models/reaction_model.rb', line 62 def self.names(scope:) super("#{scope}#{PRIMARY_KEY}") end |
Instance Method Details
#as_json(*a) ⇒ Hash
Returns generated from the ReactionModel.
255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/openc3/models/reaction_model.rb', line 255 def as_json(*a) return { 'name' => @name, 'scope' => @scope, 'enabled' => @enabled, 'triggerLevel' => @triggerLevel, 'snooze' => @snooze, 'snoozed_until' => @snoozed_until, 'triggers' => @triggers, 'actions' => @actions, 'username' => @username, 'updated_at' => @updated_at } end |
#awaken ⇒ Object
247 248 249 250 251 252 |
# File 'lib/openc3/models/reaction_model.rb', line 247 def awaken @snoozed_until = nil @updated_at = Time.now.to_nsec_from_epoch Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true))) notify(kind: 'awakened') end |
#create ⇒ Object
201 202 203 204 205 206 207 208 209 |
# File 'lib/openc3/models/reaction_model.rb', line 201 def create unless Store.hget(@primary_key, @name).nil? raise ReactionInputError.new "existing reaction found: #{@name}" end verify_triggers() @updated_at = Time.now.to_nsec_from_epoch Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true))) notify(kind: 'created') end |
#create_microservice(topics:) ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/openc3/models/reaction_model.rb', line 287 def create_microservice(topics:) # reaction Microservice microservice = MicroserviceModel.new( name: @microservice_name, folder_name: nil, cmd: ['ruby', 'reaction_microservice.rb', @microservice_name], work_dir: '/openc3/lib/openc3/microservices', options: [], topics: topics, target_names: [], plugin: nil, scope: @scope ) microservice.create end |
#deploy ⇒ Object
303 304 305 306 307 308 |
# File 'lib/openc3/models/reaction_model.rb', line 303 def deploy topics = ["#{@scope}__openc3_autonomic"] if MicroserviceModel.get_model(name: @microservice_name, scope: @scope).nil? create_microservice(topics: topics) end end |
#notify(kind:) ⇒ Object
Returns [] update the redis stream / reaction topic that something has changed.
278 279 280 281 282 283 284 285 |
# File 'lib/openc3/models/reaction_model.rb', line 278 def notify(kind:) notification = { 'kind' => kind, 'type' => 'reaction', 'data' => JSON.generate(as_json(:allow_nan => true)), } AutonomicTopic.write_notification(notification, scope: @scope) end |
#notify_disable ⇒ Object
224 225 226 227 228 229 230 |
# File 'lib/openc3/models/reaction_model.rb', line 224 def notify_disable @enabled = false # disabling clears the snooze so when it's enabled it can immediately run @snoozed_until = nil notify(kind: 'disabled') # update() will be called by the reaction_microservice end |
#notify_enable ⇒ Object
218 219 220 221 222 |
# File 'lib/openc3/models/reaction_model.rb', line 218 def notify_enable @enabled = true notify(kind: 'enabled') # update() will be called by the reaction_microservice end |
#notify_execute ⇒ Object
232 233 234 235 236 |
# File 'lib/openc3/models/reaction_model.rb', line 232 def notify_execute # Set updated_at because the event is all we get ... no update later @updated_at = Time.now.to_nsec_from_epoch notify(kind: 'executed') end |
#sleep ⇒ Object
238 239 240 241 242 243 244 245 |
# File 'lib/openc3/models/reaction_model.rb', line 238 def sleep if @snooze > 0 @snoozed_until = Time.now.to_i + @snooze @updated_at = Time.now.to_nsec_from_epoch Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true))) notify(kind: 'snoozed') end end |
#undeploy ⇒ Object
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/openc3/models/reaction_model.rb', line 310 def undeploy return unless ReactionModel.names(scope: @scope).empty? model = MicroserviceModel.get_model(name: @microservice_name, scope: @scope) if model # Let the frontend know that the microservice is shutting down # Custom event which matches the 'deployed' event in ReactionMicroservice notification = { 'kind' => 'undeployed', 'type' => 'reaction', # name and updated_at fields are required for Event formatting 'data' => JSON.generate({ 'name' => @microservice_name, 'updated_at' => Time.now.to_nsec_from_epoch, }), } AutonomicTopic.write_notification(notification, scope: @scope) model.destroy end end |
#update ⇒ Object
211 212 213 214 215 216 |
# File 'lib/openc3/models/reaction_model.rb', line 211 def update verify_triggers() @updated_at = Time.now.to_nsec_from_epoch Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true))) # No notification as this is only called via reaction_controller which already notifies end |
#validate_actions(actions) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/openc3/models/reaction_model.rb', line 162 def validate_actions(actions) unless actions.is_a?(Array) raise ReactionInputError.new "invalid actions, must be array of hashes: #{actions}" end actions.each do | action | unless action.is_a?(Hash) raise ReactionInputError.new "invalid action, must be a hash: #{action}" end action_type = action['type'] if action_type.nil? raise ReactionInputError.new "invalid action, must contain 'type': #{action}" elsif action['value'].nil? raise ReactionInputError.new "invalid action, must contain 'value': #{action}" end unless ACTION_TYPES.include?(action_type) raise ReactionInputError.new "invalid action type '#{action_type}', must be one of #{ACTION_TYPES}" end end return actions end |
#validate_level(level) ⇒ Object
125 126 127 128 129 130 131 132 |
# File 'lib/openc3/models/reaction_model.rb', line 125 def validate_level(level) case level when 'EDGE', 'LEVEL' return level else raise ReactionInputError.new "invalid triggerLevel, must be EDGE or LEVEL: #{level}" end end |
#validate_snooze(snooze) ⇒ Object
134 135 136 137 138 |
# File 'lib/openc3/models/reaction_model.rb', line 134 def validate_snooze(snooze) Integer(snooze) rescue raise ReactionInputError.new "invalid snooze value: #{snooze}" end |
#validate_triggers(triggers) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/openc3/models/reaction_model.rb', line 140 def validate_triggers(triggers) unless triggers.is_a?(Array) raise ReactionInputError.new "invalid triggers, must be array of hashes: #{triggers}" end trigger_hash = Hash.new() triggers.each do | trigger | unless trigger.is_a?(Hash) raise ReactionInputError.new "invalid trigger, must be hash: #{trigger}" end if trigger['name'].nil? || trigger['group'].nil? raise ReactionInputError.new "invalid trigger, must contain 'name' and 'group' keys: #{trigger}" end trigger_name = trigger['name'] unless trigger_hash[trigger_name].nil? raise ReactionInputError.new "no duplicate triggers allowed: #{triggers}" else trigger_hash[trigger_name] = 1 end end return triggers end |
#verify_triggers ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/openc3/models/reaction_model.rb', line 183 def verify_triggers trigger_models = [] @triggers.each do | trigger | model = TriggerModel.get(name: trigger['name'], group: trigger['group'], scope: @scope) if model.nil? raise ReactionInputError.new "failed to find trigger: #{trigger}" end trigger_models << model end if trigger_models.empty? raise ReactionInputError.new "reaction must contain at least one valid trigger: #{@triggers}" end trigger_models.each do | trigger_model | trigger_model.update_dependents(dependent: @name) trigger_model.update() end end |