Each Droonga Engine plugin can have its handler. On the handling phase, handlers can process a request and return a result.
For example, here is a sample plugin named “foo” with a handler:
require "droonga/plugin"
module Droonga::Plugins::FooPlugin
extend Plugin
register("foo")
define_single_step do |step|
step.name = "foo"
step.handler = :Handler
step.collector = Collectors::And
end
class Handler < Droonga::Handler
def handle(message)
# operations to process a request
end
end
end
Steps to define a handler:
Droonga::Plugins::FooPlugin
) and register it as a plugin. (required)Droonga::SingleStepDefinition
. (required)Droonga::Plugins::FooPlugin::Handler
) inheriting Droonga::Handler
. (required)#handle
. (optional)See also the plugin development tutorial.
A handler works like following:
#handle
is called with a task massage including the request.
As described above, the Droonga Engine creates an instance of the handler class for each request.
Any error raised from the handler is handled by the Droonga Engine itself. See also error handling.
action.synchronous
(boolean, optional, default=false
)action.synchronous = true
.Droonga::SingleStepDefinition
This provides methods to describe the “step” corresponding to the handler.
#name
, #name=(name)
Describes the name of the step itself. Possible value is a string.
The Droonga Engine treats an incoming message as a request of a “command”, if there is any step with the name
which equals to the message’s type
.
In other words, this defines the name of the command corresponding to the step itself.
#handler
, #handler=(handler)
Associates a specific handler class to the step itself. You can specify the class as any one of following choices:
Handler
or Droonga::Plugins::FooPlugin::Handler
.
Of course, the class have to be already defined at the time.:Handler
.
This is useful if you want to describe the step at first and define the actual class after that."Droonga::Plugins::FooPlugin::Handler"
.
This is also useful to define the class itself after the description.You must define the referenced class by the time the Droonga Engine actually processes the step, if you specify the name of the handler class as a symbol or a string. If the Droonga Engine fails to find out the actual handler class, or no handler is specified, then the Droonga Engine does nothing for the request.
#collector
, #collector=(collector)
Associates a specific collector class to the step itself. You can specify the class as any one of following choices:
Collectors::Something
or Droonga::Plugins::FooPlugin::MyCollector
.
Of course, the class have to be already defined at the time.:MyCollector
.
This is useful if you want to describe the step at first and define the actual class after that."Droonga::Plugins::FooPlugin::MyCollector"
.
This is also useful to define the class itself after the description.You must define the referenced class by the time the Droonga Engine actually collects results, if you specify the name of the collector class as a symbol or a string. If the Droonga Engine fails to find out the actual collector class, or no collector is specified, then the Droonga Engine doesn’t collect results and returns multiple messages as results.
See also descriptions of collectors.
#write
, #write=(write)
Describes whether the step modifies any data in the storage or don’t. If a request aims to modify some data in the storage, the request must be processed for all replicas. Otherwise the Droonga Engine can optimize handling of the step. For example, caching of results, reducing of CPU/memory usage, and so on.
Possible values are:
true
, means “this step can modify the storage.”false
, means “this step never modifies the storage.” (default)#inputs
, #inputs=(inputs)
(TBD)
#output
, #output=(output)
(TBD)
Droonga::Handler
This is the common base class of any handler. Your plugin’s handler class must inherit this.
#handle(message)
This method receives a Droonga::HandlerMessage
wrapped task message.
You can read the request information via its methods.
In this base class, this method is defined as just a placeholder and it does nothing. To process messages, you have to override it by yours, like following:
module Droonga::Plugins::MySearch
class Handler < Droonga::Handler
def handle(message)
search_query = message.request["body"]["query"]
...
{ ... } # the result
end
end
end
The Droonga Engine uses the returned value of this method as the result of the handling. It will be used to build the body of the unified response, and delivered to the Protocol Adapter.
Droonga::HandlerMessage
This is a wrapper for a task message.
The Droonga Engine analyzes a transferred request message, and build multiple task massages to process the request. A task massage has some information: a request, a step, descendant tasks, and so on.
#request
This returns the request message. You can read request body via this method. For example:
module Droonga::Plugins::MySearch
class Handler < Droonga::Handler
def handle(message)
request = message.request
search_query = request["body"]["query"]
...
end
end
end
@context
This is a reference to the Groonga::Context
instance for the storage of the corresponding volume.
See the class reference of Rroonga.
You can use any feature of Rroonga via @context
.
For example, this code returns the number of records in the specified table:
module Droonga::Plugins::CountRecords
class Handler < Droonga::Handler
def handle(message)
request = message.request
table_name = request["body"]["table"]
count = @context[table_name].size
end
end
end