Class: Maestro::MaestroWorker
- Inherits:
-
Object
- Object
- Maestro::MaestroWorker
- Defined in:
- lib/maestro_plugin/maestro_worker.rb
Overview
Helper Class for Maestro Plugins written in Ruby. The lifecycle of the plugin starts with a call to the main entry point perform called by the Maestro agent, all the other methods are helpers that can be used to deal with parsing, errors, etc. The lifecycle ends with a call to run_callbacks which can be customized by specifying an on_complete_handler_method, or on_complete_handler_block.
Constant Summary collapse
- CONTEXT_OUTPUTS_META =
Workitem constants
'__context_outputs__'- OUTPUT_META =
'__output__'- PREVIOUS_CONTEXT_OUTPUTS_META =
'__previous_context_outputs__'- STREAMING_META =
'__streaming__'- ERROR_META =
'__error__'- WAITING_META =
'__waiting__'- CANCEL_META =
'__cancel__'- NOT_NEEDED =
'__not_needed__'- LINKS_META =
'__links__'- PERSIST_META =
'__persist__'- MODEL_META =
'__model__'- RECORD_ID_META =
'__record_id__'- RECORD_FIELD_META =
'__record_field__'- RECORD_VALUE_META =
'__record_value__'- RECORD_FIELDS_META =
'__record_fields__'- RECORD_VALUES_META =
'__record_values__'- FILTER_META =
'__filter__'- NAME_META =
'__name__'- CREATE_META =
'__create__'- UPDATE_META =
'__update__'- DELETE_META =
'__delete__'
Class Attribute Summary collapse
-
.exception_handler_block ⇒ Object
readonly
Returns the value of attribute exception_handler_block.
-
.exception_handler_method ⇒ Object
readonly
Returns the value of attribute exception_handler_method.
-
.on_complete_handler_block ⇒ Object
readonly
Returns the value of attribute on_complete_handler_block.
-
.on_complete_handler_method ⇒ Object
readonly
Returns the value of attribute on_complete_handler_method.
Instance Attribute Summary collapse
-
#action ⇒ Object
Returns the value of attribute action.
-
#workitem ⇒ Object
Returns the value of attribute workitem.
Class Method Summary collapse
-
.mock! ⇒ Object
Call this to mock calls to outbound systems.
- .mock? ⇒ Boolean
-
.on_complete(handler = nil, &block) ⇒ Object
Register a callback method or block that gets called when the action was successfully completed.
-
.on_exception(handler = nil, &block) ⇒ Object
Register a callback method or block that gets called when an exception occurs during the processing of an action.
-
.unmock! ⇒ Object
Call this to unmock calls to outbound systems.
Instance Method Summary collapse
-
#add_link(name, url) ⇒ Object
Adds a link to be displayed in the Maestro UI.
-
#as_boolean(value) ⇒ Object
Return boolean version of a value.
-
#as_int(value, default = 0) ⇒ Object
Return numeric version of value.
-
#cancel ⇒ Object
Send the “cancel” message to the server.
- #create_record_with_fields(model, record_fields, record_values = nil) ⇒ Object
- #delete_record(model, filter) ⇒ Object
- #error ⇒ Object
- #error? ⇒ Boolean
- #fields ⇒ Object (also: #get_fields)
-
#get_boolean_field(field) ⇒ Object
Helper that renders a field as a boolean.
-
#get_field(field, default = nil) ⇒ Object
Get a field from workitem, supporting default value.
-
#get_int_field(field, default = 0) ⇒ Object
Helper that renders a field as an int.
-
#handle_exception(e) ⇒ Object
Fire supplied exception handlers if supplied, otherwise do nothing.
- #is_json?(string) ⇒ Boolean (also: #is_json)
-
#not_needed ⇒ Object
Send the “not needed” message to the server.
- #output ⇒ Object
-
#perform(action, workitem) ⇒ Object
Perform the specified action with the provided workitem.
-
#read_output_value(name) ⇒ Object
Read a value from the context output.
- #reset_buffered_output ⇒ Object
- #run_callbacks ⇒ Object
-
#save_output_value(name, value) ⇒ Object
Set a value in the context output.
- #set_error(error) ⇒ Object
- #set_field(field, value) ⇒ Object
-
#set_waiting(should_wait) ⇒ Object
Sets the current task as waiting.
-
#update_fields_in_record(model, name_or_id, record_field, record_value) ⇒ Object
persistence.
-
#write_output(output, options = {}) ⇒ Object
Sends the specified ouput string to the server for persistence If called with :buffer as an option, the output will be queued up until a number of writes has occurred, or a reasonable period since the last sent occurred.
Class Attribute Details
.exception_handler_block ⇒ Object (readonly)
Returns the value of attribute exception_handler_block.
51 52 53 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 51 def exception_handler_block @exception_handler_block end |
.exception_handler_method ⇒ Object (readonly)
Returns the value of attribute exception_handler_method.
51 52 53 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 51 def exception_handler_method @exception_handler_method end |
.on_complete_handler_block ⇒ Object (readonly)
Returns the value of attribute on_complete_handler_block.
51 52 53 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 51 def on_complete_handler_block @on_complete_handler_block end |
.on_complete_handler_method ⇒ Object (readonly)
Returns the value of attribute on_complete_handler_method.
51 52 53 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 51 def on_complete_handler_method @on_complete_handler_method end |
Instance Attribute Details
#action ⇒ Object
Returns the value of attribute action.
87 88 89 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 87 def action @action end |
#workitem ⇒ Object
Returns the value of attribute workitem.
87 88 89 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 87 def workitem @workitem end |
Class Method Details
.mock! ⇒ Object
Call this to mock calls to outbound systems.
72 73 74 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 72 def mock! @mock = true end |
.mock? ⇒ Boolean
81 82 83 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 81 def mock? @mock end |
.on_complete(handler = nil, &block) ⇒ Object
Register a callback method or block that gets called when the action was successfully completed. Block callbacks get the workitem as parameter.
66 67 68 69 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 66 def on_complete(handler = nil, &block) @on_complete_handler_method = handler @on_complete_handler_block = block end |
.on_exception(handler = nil, &block) ⇒ Object
Register a callback method or block that gets called when an exception occurs during the processing of an action. handler can be a symbol or string with a method name, or a block. Both will get the exception as the first parameter, and the block handler will receive the participant instance as the second parameter
58 59 60 61 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 58 def on_exception(handler = nil, &block) @exception_handler_method = handler @exception_handler_block = block end |
.unmock! ⇒ Object
Call this to unmock calls to outbound systems.
77 78 79 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 77 def unmock! @mock = false end |
Instance Method Details
#add_link(name, url) ⇒ Object
Adds a link to be displayed in the Maestro UI.
344 345 346 347 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 344 def add_link(name, url) set_field(LINKS_META, []) if fields[LINKS_META].nil? fields[LINKS_META] << {'name' => name, 'url' => url} end |
#as_boolean(value) ⇒ Object
Return boolean version of a value
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 367 def as_boolean(value) res = false if value if value.is_a?(TrueClass) || value.is_a?(FalseClass) res = value elsif value.is_a?(Fixnum) res = value != 0 elsif value.respond_to?(:to_s) value = value.to_s.downcase res = (value == 't' || value == 'true') end end res end |
#as_int(value, default = 0) ⇒ Object
Return numeric version of value
352 353 354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 352 def as_int(value, default = 0) res = default if value if value.is_a?(Fixnum) res = value elsif value.respond_to?(:to_i) res = value.to_i end end res end |
#cancel ⇒ Object
Send the “cancel” message to the server
238 239 240 241 242 243 244 245 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 238 def cancel workitem[CANCEL_META] = true rescue Exception => e Maestro.log.warn "Failed To Send Cancel Message To Server #{e.class} #{e}: #{e.backtrace.join("\n")}" ensure workitem.delete(CANCEL_META) end |
#create_record_with_fields(model, record_fields, record_values = nil) ⇒ Object
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 276 def create_record_with_fields(model, record_fields, record_values = nil) workitem[PERSIST_META] = true workitem[CREATE_META] = true workitem[MODEL_META] = model unless record_fields.is_a? Hash Maestro.log.warn 'deprecation: create_record_with_fields should be called with a Hash' record_fields = record_fields.join(',') if record_fields.respond_to? 'join' record_values = record_values.join(',') if record_values.respond_to? 'join' end workitem[RECORD_FIELDS_META] = record_fields workitem[RECORD_VALUES_META] = record_values workitem.delete(PERSIST_META) workitem.delete(CREATE_META) end |
#delete_record(model, filter) ⇒ Object
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 295 def delete_record(model, filter) workitem[PERSIST_META] = true workitem[DELETE_META] = true workitem[MODEL_META] = model if filter.is_a? Hash workitem[FILTER_META] = filter else Maestro.log.warn 'deprecation: delete_record should be called with a Hash' workitem[NAME_META] = filter.to_s end workitem.delete(PERSIST_META) workitem.delete(DELETE_META) end |
#error ⇒ Object
213 214 215 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 213 def error fields[ERROR_META] end |
#error? ⇒ Boolean
217 218 219 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 217 def error? !(error.nil? or error.empty?) end |
#fields ⇒ Object Also known as: get_fields
332 333 334 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 332 def fields workitem['fields'] end |
#get_boolean_field(field) ⇒ Object
Helper that renders a field as a boolean
328 329 330 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 328 def get_boolean_field(field) as_boolean(get_field(field)) end |
#get_field(field, default = nil) ⇒ Object
Get a field from workitem, supporting default value
316 317 318 319 320 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 316 def get_field(field, default = nil) value = fields[field] value = default if !default.nil? && (value.nil? || (value.respond_to?(:empty?) && value.empty?)) value end |
#get_int_field(field, default = 0) ⇒ Object
Helper that renders a field as an int
323 324 325 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 323 def get_int_field(field, default = 0) as_int(get_field(field), default) end |
#handle_exception(e) ⇒ Object
Fire supplied exception handlers if supplied, otherwise do nothing
126 127 128 129 130 131 132 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 126 def handle_exception(e) if self.class.exception_handler_method send(self.class.exception_handler_method, e) elsif self.class.exception_handler_block self.class.exception_handler_block.call(e, self) end end |
#is_json?(string) ⇒ Boolean Also known as: is_json
89 90 91 92 93 94 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 89 def is_json?(string) JSON.parse string true rescue Exception false end |
#not_needed ⇒ Object
Send the “not needed” message to the server.
249 250 251 252 253 254 255 256 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 249 def not_needed workitem[NOT_NEEDED] = true rescue Exception => e Maestro.log.warn "Failed To Send Not Needed Message To Server #{e.class} #{e}: #{e.backtrace.join("\n")}" ensure workitem.delete(NOT_NEEDED) end |
#output ⇒ Object
204 205 206 207 208 209 210 211 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 204 def output if MaestroWorker.mock? workitem[OUTPUT_META] else Maestro.log.warn "Output is only accessible when mock is enabled in tests. Otherwise is directly sent to Maestro" nil end end |
#perform(action, workitem) ⇒ Object
Perform the specified action with the provided workitem. Invokes the method specified by the action parameter.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 100 def perform(action, workitem) @action, @workitem = action, workitem send(action) write_output('') # Triggers any remaining buffered output to be sent run_callbacks rescue MaestroDev::Plugin::PluginError => e write_output('') # Triggers any remaining buffered output to be sent set_error(e.) rescue Exception => e write_output('') # Triggers any remaining buffered output to be sent lowerstack = e.backtrace.find_index(caller[0]) stack = lowerstack ? e.backtrace[0..lowerstack - 1] : e.backtrace msg = "Unexpected error executing task: #{e.class} #{e} at\n" + stack.join("\n") Maestro.log.warn("#{msg}\nFull stack:\n" + e.backtrace.join("\n")) # Let user-supplied exception handler do its thing handle_exception(e) set_error(msg) ensure # Older agents expected this method to *maybe* return something # .. something that no longer exists, but if we return anything # it will be *wrong* :P return nil end |
#read_output_value(name) ⇒ Object
Read a value from the context output
151 152 153 154 155 156 157 158 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 151 def read_output_value(name) if get_field(PREVIOUS_CONTEXT_OUTPUTS_META).nil? set_field(CONTEXT_OUTPUTS_META, {}) if get_field(CONTEXT_OUTPUTS_META).nil? get_field(CONTEXT_OUTPUTS_META)[name] else get_field(PREVIOUS_CONTEXT_OUTPUTS_META)[name] end end |
#reset_buffered_output ⇒ Object
199 200 201 202 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 199 def reset_buffered_output @buffered_output = '' @last_write_output = Time.now end |
#run_callbacks ⇒ Object
134 135 136 137 138 139 140 141 142 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 134 def run_callbacks return if self.class.on_complete_handler_block.nil? && self.class.on_complete_handler_method.nil? if self.class.on_complete_handler_method send(self.class.on_complete_handler_method) else self.class.on_complete_handler_block.call(workitem) end end |
#save_output_value(name, value) ⇒ Object
Set a value in the context output
145 146 147 148 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 145 def save_output_value(name, value) set_field(CONTEXT_OUTPUTS_META, {}) if get_field(CONTEXT_OUTPUTS_META).nil? get_field(CONTEXT_OUTPUTS_META)[name] = value end |
#set_error(error) ⇒ Object
221 222 223 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 221 def set_error(error) set_field(ERROR_META, error) end |
#set_field(field, value) ⇒ Object
339 340 341 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 339 def set_field(field, value) fields[field] = value end |
#set_waiting(should_wait) ⇒ Object
Sets the current task as waiting
228 229 230 231 232 233 234 235 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 228 def set_waiting(should_wait) workitem[WAITING_META] = should_wait rescue Exception => e Maestro.log.warn "Failed To Send Waiting Message To Server #{e.class} #{e}: #{e.backtrace.join("\n")}" ensure workitem.delete(WAITING_META) unless should_wait end |
#update_fields_in_record(model, name_or_id, record_field, record_value) ⇒ Object
persistence
261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 261 def update_fields_in_record(model, name_or_id, record_field, record_value) workitem[PERSIST_META] = true workitem[UPDATE_META] = true workitem[MODEL_META] = model workitem[RECORD_ID_META] = name_or_id.to_s workitem[RECORD_FIELD_META] = record_field workitem[RECORD_VALUE_META] = record_value workitem.delete(PERSIST_META) workitem.delete(UPDATE_META) end |
#write_output(output, options = {}) ⇒ Object
Sends the specified ouput string to the server for persistence If called with :buffer as an option, the output will be queued up until a number of writes has occurred, or a reasonable period since the last sent occurred. Any call without the :buffer option will cause any buffered output to be sent immediately.
Example:
write_output("I am Sam\n") <-- send immediately
write_output("Sam I am\n", :buffer => true) <-- buffer for later
write_output("I like Ham\n") <-- sends 'Sam I am\nI like Ham\n'
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/maestro_plugin/maestro_worker.rb', line 169 def write_output(output, = {}) # First time thru? We need to do some setup! reset_buffered_output if @buffered_output.nil? @buffered_output += output # If a) we have data to write, and # b) its been > 2 seconds since we last sent # # The 2 second factor is there to allow slowly accumulating data to be sent out more regularly. if !@buffered_output.empty? && (![:buffer] || Time.now - @last_write_output > 2) if !MaestroWorker.mock? workitem[OUTPUT_META] = @buffered_output else # Test mode, we want to retain output - normal operation clears out # data after it is sent workitem[OUTPUT_META] = '' if !workitem[OUTPUT_META] workitem[OUTPUT_META] = workitem[OUTPUT_META] + @buffered_output end workitem[STREAMING_META] = true reset_buffered_output end rescue Exception => e Maestro.log.warn "Unable To Write Output To Server #{e.class} #{e}: #{e.backtrace.join("\n")}" ensure workitem.delete(STREAMING_META) end |