title | layout |
---|---|
API set for plugins on the adaption phase |
en |
- TOC {:toc}
Each Droonga Engine plugin can have its adapter. On the adaption phase, adapters can modify both incoming messages (from the Protocol Adapter to the Droonga Engine, in other words, they are "request"s) and outgoing messages (from the Droonga Engine to the Protocol Adapter, in other words, they are "response"s).
For example, here is a sample plugin named "foo" with an adapter:
require "droonga/plugin"
module Droonga::Plugins::FooPlugin
extend Plugin
register("foo")
class Adapter < Droonga::Adapter
# operations to configure this adapter
XXXXXX = XXXXXX
def adapt_input(input_message)
# operations to modify incoming messages
input_message.XXXXXX = XXXXXX
end
def adapt_output(output_message)
# operations to modify outgoing messages
output_message.XXXXXX = XXXXXX
end
end
end
Steps to define an adapter:
- Define a module for your plugin (ex.
Droonga::Plugins::FooPlugin
) and register it as a plugin. (required) - Define an adapter class (ex.
Droonga::Plugins::FooPlugin::Adapter
) inheritingDroonga::Adapter
. (required) - Configure conditions to apply the adapter. (required)
- Define adaption logic for incoming messages as
#adapt_input
. (optional) - Define adaption logic for outgoing messages as
#adapt_output
. (optional)
See also the plugin development tutorial.
An adapter works like following:
- The Droonga Engine starts.
- A global instance of the adapter class (ex.
Droonga::Plugins::FooPlugin::Adapter
) is created and it is registered.- The input pattern and the output pattern are registered.
- The Droonga Engine starts to wait for incoming messages.
- A global instance of the adapter class (ex.
- An incoming message is transferred from the Protocol Adapter to the Droonga Engine.
Then, the adaption phase (for an incoming message) starts.
- The adapter's
#adapt_input
is called, if the message matches to the input matching pattern of the adapter. - The method can modify the given incoming message, via its methods.
- The adapter's
- After all adapters are applied, the adaption phase for an incoming message ends, and the message is transferred to the next "planning" phase.
- An outgoing message returns from the previous "collection" phase.
Then, the adaption phase (for an outgoing message) starts.
- The adapter's
#adapt_output
is called, if the message meets following both requirements:- It is originated from an incoming message which was processed by the adapter itself.
- It matches to the output matching pattern of the adapter.
- The method can modify the given outgoing message, via its methods.
- The adapter's
- After all adapters are applied, the adaption phase for an outgoing message ends, and the outgoing message is transferred to the Protocol Adapter.
As described above, the Droonga Engine creates only one global instance of the adapter class for each plugin. You should not keep stateful information for a pair of incoming and outgoing messages as instance variables of the adapter itself. Instead, you should give stateful information as a part of the incoming message body, and receive it from the body of the corresponding outgoing message.
Any error raised from the adapter is handled by the Droonga Engine itself. See also error handling.
input_message.pattern
(matching pattern, optional, default=nil
)
: A matching pattern for incoming messages.
If no pattern (nil
) is given, any message is regarded as "matched".
output_message.pattern
(matching pattern, optional, default=nil
)
: A matching pattern for outgoing messages.
If no pattern (nil
) is given, any message is regarded as "matched".
This is the common base class of any adapter. Your plugin's adapter class must inherit this.
This method receives a Droonga::InputMessage
wrapped incoming message.
You can modify the incoming message via its methods.
In this base class, this method is defined as just a placeholder and it does nothing. To modify incoming messages, you have to override it by yours, like following:
module Droonga::Plugins::QueryFixer
class Adapter < Droonga::Adapter
def adapt_input(input_message)
input_message.body["query"] = "fixed query"
end
end
end
This method receives a Droonga::OutputMessage
wrapped outgoing message.
You can modify the outgoing message via its methods.
In this base class, this method is defined as just a placeholder and it does nothing. To modify outgoing messages, you have to override it by yours, like following:
module Droonga::Plugins::ErrorConcealer
class Adapter < Droonga::Adapter
def adapt_output(output_message)
output_message.status_code = Droonga::StatusCode::OK
end
end
end
This returns the "type"
of the incoming message.
You can override it by assigning a new string value, like:
module Droonga::Plugins::MySearch
class Adapter < Droonga::Adapter
input_message.pattern = ["type", :equal, "my-search"]
def adapt_input(input_message)
p input_message.type
# => "my-search"
# This message will be handled by a plugin
# for the custom "my-search" type.
input_message.type = "search"
p input_message.type
# => "search"
# The messge type (type) is changed.
# This message will be handled by the "search" plugin,
# as a regular search request.
end
end
end
This returns the "body"
of the incoming message.
You can override it by assigning a new value, partially or fully. For example:
module Droonga::Plugins::MinimumLimit
class Adapter < Droonga::Adapter
input_message.pattern = ["type", :equal, "search"]
MAXIMUM_LIMIT = 10
def adapt_input(input_message)
input_message.body["queries"].each do |name, query|
query["output"] ||= {}
query["output"]["limit"] ||= MAXIMUM_LIMIT
query["output"]["limit"] = [query["output"]["limit"], MAXIMUM_LIMIT].min
end
# Now, all queries have "output.limit=10".
end
end
end
Another case:
module Droonga::Plugins::MySearch
class Adapter < Droonga::Adapter
input_message.pattern = ["type", :equal, "my-search"]
def adapt_input(input_message)
# Extract the query string from the custom type message.
query_string = input_message["body"]["query"]
# Construct internal search request for the "search" type.
input_message.type = "search"
input_message.body = {
"queries" => {
"source" => "Store",
"condition" => {
"query" => query_string,
"matchTo" => ["name"],
},
"output" => {
"elements" => ["records"],
"limit" => 10,
},
},
}
# Now, both "type" and "body" are completely replaced.
end
end
end
This returns the "statusCode"
of the outgoing message.
You can override it by assigning a new status code. For example:
module Droonga::Plugins::ErrorConcealer
class Adapter < Droonga::Adapter
input_message.pattern = ["type", :equal, "search"]
def adapt_output(output_message)
unless output_message.status_code == StatusCode::InternalServerError
output_message.status_code = Droonga::StatusCode::OK
output_message.body = {}
output_message.errors = nil
# Now any internal server error is ignored and clients
# receive regular responses.
end
end
end
end
This returns the "errors"
of the outgoing message.
You can override it by assigning new error information, partially or fully. For example:
module Droonga::Plugins::ErrorExporter
class Adapter < Droonga::Adapter
input_message.pattern = ["type", :equal, "search"]
def adapt_output(output_message)
output_message.errors.delete(secret_database)
# Delete error information from secret database
output_message.body["errors"] = {
"records" => output_message.errors.collect do |database, error|
{
"database" => database,
"error" => error
}
end,
}
# Convert error informations to a fake search result named "errors".
end
end
end
This returns the "body"
of the outgoing message.
You can override it by assigning a new value, partially or fully. For example:
module Droonga::Plugins::SponsoredSearch
class Adapter < Droonga::Adapter
input_message.pattern = ["type", :equal, "search"]
def adapt_output(output_message)
output_message.body.each do |name, result|
next unless result["records"]
result["records"].unshift(sponsored_entry)
end
# Now all search results include sponsored entry.
end
def sponsored_entry
{
"title"=> "SALE!",
"url"=> "http://..."
}
end
end
end