Class: Arrow::Broker

Inherits:
Object show all
Defined in:
lib/arrow/broker.rb

Overview

The broker is the applet manager. It maintains a registry of applets, and delegates transactions based on the request’s URI.

Authors

Please see the file LICENSE in the top-level directory for licensing details.

Constant Summary collapse

FILE_SEPARATOR =

A regular expression that matches the file separator on this system

Regexp.new( Regexp.compile(File::SEPARATOR) )

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Object

deprecate_class_method, deprecate_method, inherited

Constructor Details

#initialize(config) ⇒ Broker

Create a new Arrow::Broker object from the specified config (an Arrow::Config object).



30
31
32
33
34
# File 'lib/arrow/broker.rb', line 30

def initialize( config )
	@config = config
	@registry = Arrow::AppletRegistry.new( config )
	@start_time = Time.now
end

Instance Attribute Details

#registryObject

The Hash of RegistryEntry structs keyed by uri



42
43
44
# File 'lib/arrow/broker.rb', line 42

def registry
  @registry
end

#start_timeObject (readonly)

The Time when the Broker was started



45
46
47
# File 'lib/arrow/broker.rb', line 45

def start_time
  @start_time
end

Instance Method Details

#delegate(txn) ⇒ Object

Dispatch the specified transaction txn to the appropriate handler based on the request’s path_info.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/arrow/broker.rb', line 51

def delegate( txn )
	rval = appletchain = nil
	self.log.debug "Start of delegation (%s)" % [ txn.unparsed_uri ]

	# Fetch the path and trim the leading '/'
	path = txn.path
	path.sub!( %r{^/}, '' )
	self.log.debug "Request's path is %p" % path

	# Check for updated/deleted/added applets
	@registry.check_for_updates

	# Get the chain of applets to execute for the request
	appletchain = @registry.find_applet_chain( path )

	# If the pathinfo doesn't correspond to at least one applet, run
	# the no-such-applet handler.
	if appletchain.empty?
		rval = self.run_missing_applet_handler( txn, path )
	else
		rval = self.run_applet_chain( txn, appletchain )
	end

	# Set the request status to declined if it hasn't been set yet and
	# the return value is false.
	if !rval
		self.log.error "Applet returned false value. " +
			"Setting status to DECLINED"
		txn.status = Apache::DECLINED
	end

	# self.log.debug "Returning %p" % [ rval ]
	return rval
end

#run_applet(applet, txn, rest) ⇒ Object

Run the specified applet with the given txn (an Arrow::Transaction) and the rest of the path_info split on ‘/’.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/arrow/broker.rb', line 89

def run_applet( applet, txn, rest )
	self.log.debug "Running '%s' with args: %p" %
		[ applet.signature.name, rest ]
	return applet.run( txn, *rest )
rescue ::Exception => err
	self.log.error "[%s]: Error running %s (%s): %s:\n\t%s" % [
	    txn.serial,
		applet.signature.name,
		applet.class.filename,
		err.message,
		err.backtrace.join("\n\t"),
	]
	return self.run_error_handler( applet, txn, err )
end

#run_error_handler(applet, txn, err) ⇒ Object

Handle the given applet error err for the specified applet, using the given transaction txn. This will attempt to run whatever applet is configured as the error-handler, or run a builtin handler applet if none is configured or the configured one isn’t loaded.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/arrow/broker.rb', line 134

def run_error_handler( applet, txn, err )
	rval = nil
	handlerName = @config.applets.errorApplet.sub( %r{^/}, '' )

	unless handlerName == "(builtin)" or !@registry.key?( handlerName )
		handler = @registry[handlerName]
		self.log.notice "Running error handler applet '%s' (%s)" %
			[ handler.signature.name, handlerName ]

		begin
			rval = handler.run( txn, "report_error", applet, err )
		rescue ::Exception => err2
			self.log.error "Error while attempting to use custom error "\
			"handler '%s': %s\n\t%s" % [
				handler.signature.name,
				err2.message,
				err2.backtrace.join("\n\t"),
			]

			rval = self.builtin_error_handler( applet, txn, err )
		end
	else
		rval = self.builtin_error_handler( applet, txn, err )
	end

	return rval
end

#run_missing_applet_handler(txn, uri) ⇒ Object

Handle requests that target an applet that doesn’t exist.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/arrow/broker.rb', line 106

def run_missing_applet_handler( txn, uri )
	rval = appletchain = nil
	handlerUri = @config.applets.missingApplet
	args = uri.split( %r{/} )

	# Build an applet chain for user-configured handlers
	if handlerUri != "(builtin)"
		appletchain = @registry.find_applet_chain( handlerUri )
		self.log.error "Configured MissingApplet handler (%s) doesn't exist" %
			handlerUri if appletchain.empty?
	end

	# If the user-configured handler maps to one or more handlers, run
	# them. Otherwise, run the build-in handler.
	unless appletchain.nil? || appletchain.empty?
		rval = self.run_applet_chain( txn, appletchain )
	else
		rval = self.builtin_missing_handler( txn, *args )
	end

	return rval
end