Module: AgentDispatcher
- Included in:
- AgentUtils::AgentBase
- Defined in:
- lib/agentdispatcher.rb
Overview
Complex command dispatcher mixin / Application micro-framework
Simplifies creation of configurable objects which can react on messages/events while using OO approach. They can be easily executed from command line. The micro-framework has lots of features. Therefore an example first:
Example Usage
agent.rb:
class Agent
include AgentDispatcher
@AllowedCommands = %w(start stop)
def on_run *args
# do some job
end
def on_stop *args
# do some job
end
...
end
class AgentB < Agent
@DefaultCfg = {:log_path=>'/tmp'}
@AllowedCommands = %w(start run stop)
upMethod :initBussines
def initBussines
puts "post creation placeholder"
end
downMethod :closeBussines
def closeBussines
puts "pre-shutdown placeholder"
end
def on_run *args
# do some job
end
...
end
if __FILE__ == $0
AgentB::Dispatch *ARGV
end
There are several options how to dispatch events to the ‘agent’ (programatically)
Agent::Dispatch *ARGV
AgentB::Dispatch 'agent1', 'run', 'param1', 'param2'
Agent::Dispatch 'start'
Agent::DispatchString '--config cfgfile1,cfgfile2 agentID start'
Agent.new(...).dispatch *ARGV
The purpose of ARGV variants is of course to call the ‘agent’ right away from the command line, e.g.:
agent.rb --config cfgfile1,cfgfile2 agentID start
agent.rb --help
Feature Documentation
-
dispatching commands (+id, arguments, configuration)
-
defintion of accepted commands
@AllowedCommands = %w(start stop) -
command handler method in format
on_#{command in lowercase}<tt> (e.g. <tt>run-> <tt>on_run<tt>) -
dispatching from: command-line string, ARGV, Hash
-
the agents object can used conventional inheritance to override/add new behavior.
-
objects may have their own constructors (the class method Dispatch uses default constructor)
-
injection of business constructors/desctructors
-
upMethod aMethodName -
downMethod aMethodName
-
-
autogeneration of command-line help
-
(TODO: in future support for any methods by injections)
Configuration
-
hierarchical configuration (the final configuration is constructed by overlaying several sources)
-
default config can be defined in class variable
@DefaultCfg = {:log_path=>'/tmp'} -
loaded from file; specified in option :config either by path (ends with .yml) or by name (the file is loaded from
#{AGENTS_ROOT}/config/#{name}.yml) -
multiple configuration files can be passed
:config=>'cfg1,cfg2', precedence in the given order -
the configuration can be given by arguments
-
precedence of configuration overlaying defaut < files < arguments
Logging
-
@loginstance variable is created, can be overriden in object constructor -
default path is
#{AGENTS_ROOT}/tmp/log/#{@id}.log -
the path can be modified by setting
:log_pathoption
Process Management
-
a PID file is generated while the script is running
-
generated in
#{AGENTS_ROOT}/var/run/#{@id}.pid -
the path can be modified by setting
:pid_pathoption -
passing
:nopidoption supresses genereation of pid file -
process does not start if a pid file already exists. Force execution by passing
:forcepidoption
Comandline format Usage: #@agentClass [CONFIG] [ID] [COMMAND] [ARGS]
CONFIG Any application specific configuration flags in the format --NAME VALUE[,VALUE]*
Special flags: {help, id, config=[A,B,...],log_path, nopid, pid_path, quiet, cmd}
ID Instance id of the agent (default: 'id-fied classname')
COMMAND Command to execute [aplication soec. commands] (default: 'run')
ARGS Space separated arguments (default:none)
-
Passing
:helpoption makes the script to generate help intructions to the STDOUT
Author
Viktor Zigo, alephzarro.com, All rights reserved. Distributed under GNU GPL License (see LICENSE).
sponsored by 7inf.com
Defined Under Namespace
Modules: AgentDispatcherClassMethods
Constant Summary collapse
- PID_PATH =
'var/run'- LOG_PATH =
'tmp/log'- AGENTS_ROOT =
(ENV['AGENTS_ROOT'] || '.' )
Instance Method Summary collapse
- #dispatch(*argv) ⇒ Object
-
#dispatchString(aString) ⇒ Object
@AllowedCommands = [].
Instance Method Details
#dispatch(*argv) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/agentdispatcher.rb', line 110 def dispatch *argv ## puts "AGENTS_ROOT: #{AGENTS_ROOT}, agentClass: #{self.class} allowedCmds: #{self.class.AllowedCommands}" #make validation customizable cfg = AgentUtils::ConfFactory.new(self.class).createFromArgv *argv id = cfg[:id] #TODO: forcepid #generate pid cfg[:pid_path] = File.join( AGENTS_ROOT, PID_PATH, "#{id}.pid") unless cfg[:pid_path] ProcTools::withPidFile(cfg[:pid_path], cfg) do initializeAgent cfg cmd = cfg[:cmd] if self.class.AllowedCommands().include? cmd executeInjections :postInit begin self.send "on_#{cmd.downcase}", *cfg[:args] ensure executeInjections :preExit end else raise "Unknown command '#{cmd}', allowed commands are {#{self.class.AllowedCommands.join(',')}}" end end end |
#dispatchString(aString) ⇒ Object
@AllowedCommands = []
106 107 108 |
# File 'lib/agentdispatcher.rb', line 106 def dispatchString aString dispatch *aString.split end |