Class: Brown::Agent::Stimulus

Inherits:
Object
  • Object
show all
Defined in:
lib/brown/agent/stimulus.rb

Overview

A single stimulus group in a Brown Agent.

This is all the behind-the-scenes plumbing that's required to make the trickiness of stimuli work correctly. In general, if you're a Brown user and you ever need to do anything with anything in here, something has gone terribly, terribly wrong somewhere.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(method_name:, stimuli_proc:, agent_class:, logger: Logger.new("/dev/null")) ⇒ Stimulus

Create a new stimulus.

Parameters:

  • method_name (String)

    The method to call on an instance of agent_class to process a single stimulus event.

  • stimuli_proc (Proc)

    What to call over and over again to listen for new stimulus events.

  • agent_class (Class)

    The class to instantiate when processing stimulus events.

  • logger (Logger) (defaults to: Logger.new("/dev/null"))

    Where to log things to for this stimulus. If left as the default, no logging will be done.



41
42
43
44
45
46
47
# File 'lib/brown/agent/stimulus.rb', line 41

def initialize(method_name:, stimuli_proc:, agent_class:, logger: Logger.new("/dev/null"))
	@method_name  = method_name
	@stimuli_proc = stimuli_proc
	@agent_class  = agent_class
	@thread_group = ThreadGroup.new
	@logger       = logger
end

Instance Attribute Details

#agent_classClass (readonly)

The class to instantiate to process a stimulus.

Returns:

  • (Class)


25
26
27
# File 'lib/brown/agent/stimulus.rb', line 25

def agent_class
  @agent_class
end

#method_nameString (readonly)

The name of the method to call when the stimulus is triggered.

Returns:

  • (String)


13
14
15
# File 'lib/brown/agent/stimulus.rb', line 13

def method_name
  @method_name
end

#stimuli_procProc (readonly)

The chunk of code to call over and over again to listen for the stimulus.

Returns:

  • (Proc)


19
20
21
# File 'lib/brown/agent/stimulus.rb', line 19

def stimuli_proc
  @stimuli_proc
end

Instance Method Details

#finishObject

Stop the stimulus listener, and wait gracefull for all currently in-progress stimuli processing to finish before returning.



97
98
99
100
101
102
103
104
# File 'lib/brown/agent/stimulus.rb', line 97

def finish
	if @runner_thread and @runner_thread != Thread.current
		@runner_thread.raise(Brown::StopSignal.new("stimulus loop"))
	end
	@runner_thread = nil

	@thread_group.list.each { |th| th.join }
end

#run(once = nil) ⇒ Object

Fire off the stimulus listener.

Parameters:

  • once (Symbol, NilClass) (defaults to: nil)

    Ordinarily, when the stimulus is run, it just keeps going forever (or until stopped, at least). If you just want to run the stimulus listener proc once, and then return, you can pass the special symbol :once here.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/brown/agent/stimulus.rb', line 56

def run(once = nil)
	if once == :once
		stimuli_proc.call(->(*args) { process(*args) })
	else
		@runner_thread = Thread.current
		begin
			while @runner_thread
				begin
					stimuli_proc.call(method(:spawn_worker))
				rescue Brown::StopSignal, Brown::FinishSignal
					raise
				rescue Exception => ex
					log_failure("Stimuli listener", ex)
				end
			end
		rescue Brown::StopSignal
			stop
		rescue Brown::FinishSignal
			finish
		rescue Exception => ex
			log_failure("Stimuli runner", ex)
		end
	end
end

#stopObject

Signal the stimulus to immediately shut down everything.

This will cause all stimulus processing threads to be terminated immediately. You probably want to use #finish instead, normally.



86
87
88
89
90
91
92
# File 'lib/brown/agent/stimulus.rb', line 86

def stop
	@thread_group.list.each do |th|
		th.raise Brown::StopSignal.new("stimulus thread_group")
	end

	finish
end