YUKI Hiroshi
null+****@clear*****
Fri Feb 28 12:16:16 JST 2014
YUKI Hiroshi 2014-02-28 12:16:16 +0900 (Fri, 28 Feb 2014) New Revision: 47f05e160557214920f1a055f34c041473260b4d https://github.com/droonga/droonga.org/commit/47f05e160557214920f1a055f34c041473260b4d Message: Update ja version of plugin development tutorial Modified files: _po/ja/tutorial/plugin-development/adapter/index.po _po/ja/tutorial/plugin-development/handler/index.po _po/ja/tutorial/plugin-development/index.po ja/tutorial/plugin-development/adapter/index.md ja/tutorial/plugin-development/index.md Modified: _po/ja/tutorial/plugin-development/adapter/index.po (+10 -4) =================================================================== --- _po/ja/tutorial/plugin-development/adapter/index.po 2014-02-28 12:11:33 +0900 (8a494d1) +++ _po/ja/tutorial/plugin-development/adapter/index.po 2014-02-28 12:16:16 +0900 (59927c7) @@ -46,7 +46,7 @@ msgstr "" msgid "" "First, let's study basics with a simple logger plugin named `sample-logger` af" -"fects on the adaption phase." +"fects at the adaption phase." msgstr "" msgid "" @@ -112,7 +112,10 @@ msgid "" "module Droonga\n" " module Plugins\n" " module SampleLoggerPlugin\n" -" Plugin.registry.register(\"sample-logger\", self)" +" extend Plugin" +msgstr "" + +msgid " registry.register(\"sample-logger\", self)" msgstr "" msgid "" @@ -131,7 +134,10 @@ msgstr "" msgid "" " * The `sample-logger` is the name of the plugin itself. You'll use it in your" " `catalog.json`, to activate the plugin.\n" -" * As the example above, you must define your plugin as a module." +" * As the example above, you must define your plugin as a module.\n" +" * Behaviors at the adaption phase is defined a class called *adapter*.\n" +" An adapter class must be defined as a subclass of the `Droonga::Adapter`, u" +"nder the namespace of the plugin module." msgstr "" msgid "### Activate the plugin with `catalog.json`" @@ -159,7 +165,7 @@ msgstr "" msgid "" "Note: you must place `\"sample-logger\"` before `\"search\"`, because the `sample-" -"logger` plugin depends on the `search`. Droonga Engine applies plugins on the " +"logger` plugin depends on the `search`. Droonga Engine applies plugins at the " "adaption phase in the order defined in the `catalog.json`, so you must resolve" " plugin dependencies by your hand (for now)." msgstr "" Modified: _po/ja/tutorial/plugin-development/handler/index.po (+466 -305) =================================================================== --- _po/ja/tutorial/plugin-development/handler/index.po 2014-02-28 12:11:33 +0900 (523146c) +++ _po/ja/tutorial/plugin-development/handler/index.po 2014-02-28 12:16:16 +0900 (e782344) @@ -9,14 +9,11 @@ msgstr "" msgid "" "---\n" -"title: \"Plugin: Handle requests\"\n" +"title: \"Plugin: Handle requests on all partitions\"\n" "layout: en\n" "---" msgstr "" -msgid "!!! WORK IN PROGRESS !!!" -msgstr "" - msgid "" "* TOC\n" "{:toc}" @@ -26,55 +23,132 @@ msgid "## The goal of this tutorial" msgstr "## チュートリアルのゴール" msgid "" -"This tutorial aims to help you to learn how to develop plugins\n" -"which extends operations in handle phrase." +"This tutorial aims to help you to learn how to develop plugins which do someth" +"ing dispersively for/in each partition, around the handling phase." msgstr "" msgid "## Precondition" msgstr "## 前提条件" -msgid "* You must complete [Modify requests and responses tutorial][adapter]." +msgid "* You must complete the [tutorial for the adaption phase][adapter]." msgstr "" -msgid "## Handling phase" +msgid "## Handling of incoming messages" msgstr "" msgid "" -"The handling phase is the phase that the actual storage access is happen.\n" -"As Droonga is a distributed system, handler phase is done in multiple partitio" -"ns." +"When an incoming message is transferred from the adaption phase, the Droonga E" +"ngine enters into the *processing phase*." msgstr "" msgid "" -"Here, in this tutorial, we are going to replace the handling phase of `search`" -" command for explanation. This breaks the `search` command. So this is not use" -"ful in practice, but it will help you to learn how Droonga works." +"In the processing phase, the Droonga Engine processes incoming messages step b" +"y step.\n" +"One *step* is constructed from some sub phases: *planning phase*, *distributio" +"n phase*, *handling phase*, and *collection phase*." msgstr "" msgid "" -"In practice, we need to *extend* Droonga. In this case, we need to add a new c" -"ommand which does not conflict with the existing commands. To do so, you need " -"to learn not only how to handle messages but also how to distribute messages t" -"o handlers and collect messages from them. Proceed to [Distribute requests and" -" collect responses][] after this tutorial completed." +" * At the *planning phase*, the Droonga Engine generates multiple sub steps to" +" process an incoming message.\n" +" In simple cases, you don't have to write codes for this phase, then there i" +"s just one sub step to handle the message.\n" +" * At the *distribution phase*, the Droonga Engine distributes the message to " +"multiple partitions.\n" +" (It is completely done by the Droonga Engine itself, so this phase is not p" +"luggable.)\n" +" * At the *handling phase*, *each partition simply processes only one distribu" +"ted message as its input, and returns a result.*\n" +" This is the time that actual storage accesses happen.\n" +" Actually, some commands (`search`, `add`, `create_table` and so on) access " +"to the storage at the time.\n" +" * At the *collection phase*, the Droonga Engine collects results from partiti" +"ons to one unified result.\n" +" There are some useful generic collectors, so you don't have to write codes " +"for this phase in most cases." msgstr "" -msgid "TODO fix the link to \"Distribute requests and collect responses\" tutorial" +msgid "" +"After all steps are finished, the Droonga Engine transfers the result to the p" +"ost adaption phase." msgstr "" -msgid "## Directory Structure" +msgid "" +"A class to define operations at the handling phase is called *handler*.\n" +"Put simply, adding of a new handler means adding a new command." +msgstr "" + +msgid "## Design a read-only command `countRecords`" msgstr "" msgid "" -"The directory structure for plugins are in same rule as explained in [Modify r" -"equests and responses tutorial][adapter]." +"Here, in this tutorial, we are going to add a new custom `countRecords` comman" +"d.\n" +"At first, let's design it." +msgstr "" + +msgid "" +"The command reports the number of records about a specified table, for each pa" +"rtition.\n" +"So it will help you to know how records are distributed in the cluster.\n" +"Nothing is changed by the command, so it is a *read-only command*." +msgstr "" + +msgid "The request must have the name of one table, like:" +msgstr "" + +msgid "" +"~~~json\n" +"{\n" +" \"dataset\" : \"Starbucks\",\n" +" \"type\" : \"countRecords\",\n" +" \"body\" : {\n" +" \"table\": \"Store\"\n" +" }\n" +"}\n" +"~~~" +msgstr "" + +msgid "" +"Create a JSON file `count-records.json` with the content above.\n" +"We'll use it for testing." +msgstr "" + +msgid "" +"The response must have number of records in the table, for each partition.\n" +"They can be appear in an array, like:" +msgstr "" + +msgid "" +"~~~json\n" +"{\n" +" \"inReplyTo\": \"(message id)\",\n" +" \"statusCode\": 200,\n" +" \"type\": \"countRecords.result\",\n" +" \"body\": [10, 10]\n" +"}\n" +"~~~" msgstr "" msgid "" -"Now let's create `sample-logger` plugin again. This will act almost same as [M" -"odify requests and responses tutorial][adapter] version, except the phase in w" -"hich the plugin works. We need to put `sample-logger.rb` to `lib/droonga/plugi" -"ns/sample-logger.rb`. The directory tree will be like this:" +"If there are 2 partitions and 20 records are stored evenly, the array will hav" +"e two elements like above.\n" +"It means that a partition has 10 records and another one also has 10 records." +msgstr "" + +msgid "" +"We're going to create a plugin to accept such requests and return such respons" +"es." +msgstr "" + +msgid "### Directory structure" +msgstr "" + +msgid "" +"The directory structure for plugins are in same rule as explained in the [tuto" +"rial for the adaption phase][adapter].\n" +"Now let's create the `count-records` plugin, as the file `count-records.rb`. T" +"he directory tree will be:" msgstr "" msgid "" @@ -82,17 +156,14 @@ msgid "" "lib\n" "└── droonga\n" " └── plugins\n" -" └── sample-logger.rb\n" +" └── count-records.rb\n" "~~~" msgstr "" -msgid "## Create a plugin" -msgstr "" - -msgid "Create a plugin as follows:" +msgid "Then, create a skelton of a plugin as follows:" msgstr "" -msgid "lib/droonga/plugins/sample-logger.rb:" +msgid "lib/droonga/plugins/count-records.rb:" msgstr "" msgid "" @@ -103,19 +174,62 @@ msgstr "" msgid "" "module Droonga\n" " module Plugins\n" -" module SampleLoggerPlugin\n" -" Plugin.registry.register(\"sample-logger\", self)" +" module CountRecordsPlugin\n" +" Plugin.registry.register(\"count-records\", self)\n" +" end\n" +" end\n" +"end\n" +"~~~" +msgstr "" + +msgid "### Define a \"step\" for the command" +msgstr "" + +msgid "Define a \"step\" for the new `countRecords` command, in your plugin. Like:" msgstr "" msgid "" -" class Handler < Droonga::Handler\n" -" message.type = \"search\"" +"module Droonga\n" +" module Plugins\n" +" module CountRecordsPlugin\n" +" Plugin.registry.register(\"count-records\", self)" msgstr "" msgid "" -" def handle(message, messenger)\n" -" $log.info \"Droonga::Plugins::SampleLoggerPlugin\", :message => messag" -"e\n" +" define_single_step do |step|\n" +" step.name = \"countRecords\"\n" +" end\n" +" end\n" +" end\n" +"end\n" +"~~~" +msgstr "" + +msgid "" +"The `step.name` equals to the name of the command itself.\n" +"Currently we just define the name of the command.\n" +"That's all." +msgstr "" + +msgid "### Define the handling logic" +msgstr "" + +msgid "" +"The command has no handler, so it does nothing yet.\n" +"Let's define the behavior." +msgstr "" + +msgid "" +" define_single_step do |step|\n" +" step.name = \"countRecords\"\n" +" step.handler = :Handler\n" +" end" +msgstr "" + +msgid "" +" class Handler < Droonga::Handler\n" +" def handle(message)\n" +" [0]\n" " end\n" " end\n" " end\n" @@ -124,12 +238,58 @@ msgid "" "~~~" msgstr "" -msgid "## Activate the plugin with `catalog.json`" +msgid "The class `Handler` is a handler class for our new command." +msgstr "" + +msgid "" +" * It must inherit a builtin-class `Droonga::Handler`.\n" +" * It implements the logic to handle requests.\n" +" Its instance method `#handle` actually handles requests." +msgstr "" + +msgid "" +"Currently the handler does nothing and returns an array of a number.\n" +"The returned value is used to construct the response body." +msgstr "" + +msgid "" +"The handler is bound to the step with the configuration `step.handler`.\n" +"Because we define the class `Handler` after `define_single_step`, we specify t" +"he handler class with a symbol `:Handler`.\n" +"If you define the handler class before `define_single_step`, then you can writ" +"e as `step.handler = Handler` simply.\n" +"Moreover, a class path string like `\"OtherPlugin::Handler\"` is also available." +msgstr "" + +msgid "" +"Then, we also have to bind a collector to the step, with the configuration `st" +"ep.collector`." +msgstr "" + +msgid "" +"~~~ruby\n" +"(snip)\n" +" define_single_step do |step|\n" +" step.name = \"countRecords\"\n" +" step.handler = :Handler\n" +" step.collector = SumCollector\n" +" end\n" +"(snip)\n" +"~~~" +msgstr "" + +msgid "" +"The `SumCollector` is one of built-in collectors.\n" +"It merges results retuned from handler instances for each partition to one res" +"ult." +msgstr "" + +msgid "### Activate the plugin with `catalog.json`" msgstr "" msgid "" -"Update catalog.json to activate this plugin. Add `\"sample-logger\"` to `\"plugin" -"s\"`." +"Update catalog.json to activate this plugin.\n" +"Add `\"count-records\"` to `\"plugins\"`." msgstr "" msgid "" @@ -138,17 +298,18 @@ msgid "" " \"datasets\": {\n" " \"Starbucks\": {\n" " (snip)\n" -" \"plugins\": [\"sample-logger\", \"groonga\", \"crud\", \"search\"],\n" +" \"plugins\": [\"count-records\", \"groonga\", \"crud\", \"search\"],\n" "(snip)\n" "~~~" msgstr "" -msgid "## Run" +msgid "### Run and test" msgstr "" msgid "" -"Let's get Droonga started. Note that you need to specify ./lib directory in RU" -"BYLIB environment variable in order to make ruby possible to find your plugin." +"Let's get Droonga started.\n" +"Note that you need to specify ./lib directory in RUBYLIB environment variable " +"in order to make ruby possible to find your plugin." msgstr "" msgid "" @@ -157,343 +318,340 @@ msgid "" "luentd.pid" msgstr "" -msgid "## Test" +msgid "Then, send a message for the `countRecords` command to the Droonga Engine." msgstr "" msgid "" -"Send a search request to Droonga Engine. Use `search-columbus.json` same as of" -" [Modify requests and responses tutorial][adapter]." +"~~~\n" +"# droonga-request --tag starbucks count-records.json\n" +"Elapsed time: 0.01494\n" +"[\n" +" \"droonga.message\",\n" +" 1392621168,\n" +" {\n" +" \"inReplyTo\": \"1392621168.0119512\",\n" +" \"statusCode\": 200,\n" +" \"type\": \"countRecords.result\",\n" +" \"body\": [0, 0, 0]\n" +" }\n" +"]\n" +"~~~" msgstr "" msgid "" -"~~~\n" -"# droonga-request --tag starbucks search-columbus.json\n" +"You'll get a response message like above.\n" +"Look at these points:" +msgstr "" + +msgid "" +" * The `type` of the response becomes `countRecords.result`.\n" +" It is automatically named by the Droonga Engine.\n" +" * The format of the `body` is same to the returned value of the handler's `ha" +"ndle` method." +msgstr "" + +msgid "There are 3 elements in the array. Why?" +msgstr "" + +msgid "" +" * Remember that we have configured the `Starbucks` dataset to use 3 partition" +"s (and each has 2 replicas) in the `catalog.json` of [the basic tutorial][basi" +"c].\n" +" * Because it is a read-only command, an incoming message is distributed only " +"to paritions, not to replicas.\n" +" So there are only 3 results, not 6.\n" +" (TODO: I have to add a figure to indicate active nodes: [000, 001, 010, 011" +", 020, 021] => [000, 011, 020])\n" +" * The `SumCollector` collects them.\n" +" Those 3 results are joined to just one array by the collector." +msgstr "" + +msgid "As the result, just one array with 3 elements appears in the response message." +msgstr "" + +msgid "### Read-only access to the storage" +msgstr "" + +msgid "" +"Now, each instance of the handler class always returns `[0]` as its result.\n" +"Let's implement codes to count up the number of records from the actual storag" +"e." +msgstr "" + +msgid "" +"~~~ruby\n" +"(snip)\n" +" class Handler < Droonga::Handler\n" +" def handle(message)\n" +" table_name = message[\"body\"][\"table\"]\n" +" table = @context[table_name]\n" +" count = table.size\n" +" [count]\n" +" end\n" +" end\n" +"(snip)\n" "~~~" msgstr "" msgid "" -"You will see no output for `droonga-request` execution because out `sample-log" -"ger` plugin traps the `add` request." +"The instance variable `@context` is an instance of `Groonga::Context` for the " +"storage of the partition.\n" +"See the [class reference of Rroonga][Groonga::Context].\n" +"You can use any feature of Rroonga via `@context`.\n" +"For now, we simply access to the table itself by its name and read the value o" +"f its `size` method - it returns the number of records." msgstr "" -msgid "Instead, you will see something like these lines in `fluentd.log`:" +msgid "" +"Then, test it.\n" +"Restart the Droonga Engine and send the request again." msgstr "" msgid "" "~~~\n" -"2014-02-17 16:25:23 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message" -"=#<Droonga::HandlerMessage:0x007f9a7f0987a8 @raw={\"dataset\"=>\"Starbucks\", \"typ" -"e\"=>\"search\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"route\"=" -">\"localhost:24224/starbucks.011\", \"step\"=>{\"command\"=>\"search\", \"dataset\"=>\"St" -"arbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition\"=>{\"qu" -"ery\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTime\", \"el" -"apsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], \"limit\"" -"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replica\"=>\"ra" -"ndom\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/starbucks." -"011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants\"=>{\"er" -"rors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/starbucks" -".#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhos" -"t:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"t" -"ype\"=>\"search.result\", \"to\"=>\"127.0.0.1:50410/droonga\"}, \"id\"=>\"1392621923.903" -"868\", \"date\"=>\"2014-02-17 16:25:23 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugi" -"ns::Error::Adapter\"]}, @body={\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"" -"route\"=>\"localhost:24224/starbucks.011\", \"step\"=>{\"command\"=>\"search\", \"datase" -"t\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition" -"\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTim" -"e\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], " -"\"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replic" -"a\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/sta" -"rbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants" -"\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/st" -"arbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"l" -"ocalhost:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, @task={" -"\"route\"=>\"localhost:24224/starbucks.011\", \"step\"=>{\"command\"=>\"search\", \"datas" -"et\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"conditio" -"n\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTi" -"me\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"]," -" \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"repli" -"ca\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/st" -"arbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendant" -"s\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/s" -"tarbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step={\"command\"=>\"search\", " -"\"dataset\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"co" -"ndition\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"s" -"tartTime\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_" -"key\"], \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], " -"\"replica\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24" -"224/starbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"desc" -"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:2" -"4224/starbucks.#0\"]}}>\n" -"2014-02-17 16:25:23 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message" -"=#<Droonga::HandlerMessage:0x007f9a7f060970 @raw={\"dataset\"=>\"Starbucks\", \"typ" -"e\"=>\"search\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"route\"=" -">\"localhost:24224/starbucks.020\", \"step\"=>{\"command\"=>\"search\", \"dataset\"=>\"St" -"arbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition\"=>{\"qu" -"ery\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTime\", \"el" -"apsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], \"limit\"" -"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replica\"=>\"ra" -"ndom\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/starbucks." -"011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants\"=>{\"er" -"rors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/starbucks" -".#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhos" -"t:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"t" -"ype\"=>\"search.result\", \"to\"=>\"127.0.0.1:50410/droonga\"}, \"id\"=>\"1392621923.903" -"868\", \"date\"=>\"2014-02-17 16:25:23 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugi" -"ns::Error::Adapter\"]}, @body={\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"" -"route\"=>\"localhost:24224/starbucks.020\", \"step\"=>{\"command\"=>\"search\", \"datase" -"t\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition" -"\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTim" -"e\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], " -"\"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replic" -"a\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/sta" -"rbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants" -"\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/st" -"arbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"l" -"ocalhost:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, @task={" -"\"route\"=>\"localhost:24224/starbucks.020\", \"step\"=>{\"command\"=>\"search\", \"datas" -"et\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"conditio" -"n\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTi" -"me\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"]," -" \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"repli" -"ca\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/st" -"arbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendant" -"s\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/s" -"tarbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step={\"command\"=>\"search\", " -"\"dataset\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"co" -"ndition\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"s" -"tartTime\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_" -"key\"], \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], " -"\"replica\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24" -"224/starbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"desc" -"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:2" -"4224/starbucks.#0\"]}}>\n" -"2014-02-17 16:25:23 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message" -"=#<Droonga::HandlerMessage:0x007f9a7f069c50 @raw={\"dataset\"=>\"Starbucks\", \"typ" -"e\"=>\"search\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"route\"=" -">\"localhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"search\", \"dataset\"=>\"St" -"arbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition\"=>{\"qu" -"ery\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTime\", \"el" -"apsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], \"limit\"" -"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replica\"=>\"ra" -"ndom\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/starbucks." -"011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants\"=>{\"er" -"rors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/starbucks" -".#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhos" -"t:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"t" -"ype\"=>\"search.result\", \"to\"=>\"127.0.0.1:50410/droonga\"}, \"id\"=>\"1392621923.903" -"868\", \"date\"=>\"2014-02-17 16:25:23 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugi" -"ns::Error::Adapter\"]}, @body={\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"" -"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"search\", \"datase" -"t\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition" -"\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTim" -"e\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], " -"\"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replic" -"a\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/sta" -"rbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants" -"\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/st" -"arbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"l" -"ocalhost:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, @task={" -"\"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"search\", \"datas" -"et\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"conditio" -"n\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTi" -"me\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"]," -" \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"repli" -"ca\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/st" -"arbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendant" -"s\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/s" -"tarbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step={\"command\"=>\"search\", " -"\"dataset\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"co" -"ndition\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"s" -"tartTime\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_" -"key\"], \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], " -"\"replica\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24" -"224/starbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"desc" -"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:2" -"4224/starbucks.#0\"]}}>\n" +"# kill $(cat fluentd.pid)\n" +"# RUBYLIB=./lib fluentd --config fluentd.conf --log fluentd.log --daemon fluen" +"td.pid\n" +"# droonga-request --tag starbucks count-records.json\n" +"Elapsed time: 0.01494\n" +"[\n" +" \"droonga.message\",\n" +" 1392621168,\n" +" {\n" +" \"inReplyTo\": \"1392621168.0119512\",\n" +" \"statusCode\": 200,\n" +" \"type\": \"countRecords.result\",\n" +" \"body\": [12, 12, 11]\n" +" }\n" +"]\n" "~~~" msgstr "" -msgid "Note that three lines are shown for only one request. What is happening?" +msgid "Because there are totally 35 records, they are stored evenly like above." +msgstr "" + +msgid "## Design a read-write command `deleteStores`" +msgstr "" + +msgid "Next, let's add another new custom command `deleteStores`." msgstr "" msgid "" -"Remember that we have configured `Starbucks` dataset to use three partitions (" -"and each has two replicas) in `catalog.json` of [the basic tutorial][basic]." +"The command deletes records of the `Store` table, from the storage.\n" +"Because it modifies something in existing storage, it is a *read-write command" +"*." +msgstr "" + +msgid "The request must have the condition to select records to be deleted, like:" msgstr "" msgid "" -"The `search` request is dispatched to three partitions and passed into handlin" -"g phase for each partition. That is because we saw three lines for one request" -"." +"~~~json\n" +"{\n" +" \"dataset\" : \"Starbucks\",\n" +" \"type\" : \"deleteStores\",\n" +" \"body\" : {\n" +" \"keyword\": \"Broardway\"\n" +" }\n" +"}\n" +"~~~" msgstr "" msgid "" -"The messages shown is in internal format, which is transformed from the reques" -"t you've sent.\n" -"You can see your search request is distributed to partitions `localhost:24224/" -"starbucks.001`, `localhost:24224/starbucks.011` and `localhost:24224/starbucks" -".020` from `\"routes\"`." +"Any record including the given keyword `\"Broadway\"` in its `\"key\"` is deleted " +"from the storage of all partitions." msgstr "" msgid "" -"In `search` case, it is enough to use one replica per one partition because re" -"plicas for a partition are expected to have the exactly same contents.\n" -"So the planner ordered distributor to choose one replica randomly." +"Create a JSON file `delete-stores-broadway.json` with the content above.\n" +"We'll use it for testing." +msgstr "" + +msgid "The response must have a boolean value to indicate \"success\" or \"fail\", like:" msgstr "" -msgid "## Trap \"add\" command" +msgid "" +"~~~json\n" +"{\n" +" \"inReplyTo\": \"(message id)\",\n" +" \"statusCode\": 200,\n" +" \"type\": \"deleteStores.result\",\n" +" \"body\": true\n" +"}\n" +"~~~" msgstr "" msgid "" -"We have seen how distributed search is done from the view point of handling ph" -"ase so far.\n" -"How about `\"add\"` command?" +"If the request is successfully processed, the `body` becomes `true`. Otherwise" +" `false`.\n" +"The `body` is just one boolean value, because we don't have to receive multipl" +"e results from partitions." msgstr "" -msgid "Update `smaple-logger` plugin to trap `\"add\"` message instead of `\"search\"`." +msgid "### Directory Structure" +msgstr "" + +msgid "" +"Now let's create the `delete-stores` plugin, as the file `delete-stores.rb`. T" +"he directory tree will be:" msgstr "" msgid "" "~~~\n" -"require \"droonga/plugin\"" +"lib\n" +"└── droonga\n" +" └── plugins\n" +" └── delete-stores.rb\n" +"~~~" +msgstr "" + +msgid "lib/droonga/plugins/delete-stores.rb:" msgstr "" msgid "" -" class Handler < Droonga::Handler\n" -" message.type = \"add\" # This was \"search\" in the previous version." +"module Droonga\n" +" module Plugins\n" +" module DeleteStoresPlugin\n" +" Plugin.registry.register(\"delete-stores\", self)\n" +" end\n" +" end\n" +"end\n" +"~~~" msgstr "" -msgid "Restart `fluentd`:" +msgid "Define a \"step\" for the new `deleteStores` command, in your plugin. Like:" msgstr "" msgid "" -"~~~\n" -"# kill $(cat fluentd.pid)\n" -"# RUBYLIB=./lib fluentd --config fluentd.conf --log fluentd.log --daemon fluen" -"td.pid\n" +"module Droonga\n" +" module Plugins\n" +" module DeleteStoresPlugin\n" +" Plugin.registry.register(\"delete-stores\", self)" +msgstr "" + +msgid "" +" define_single_step do |step|\n" +" step.name = \"deleteStores\"\n" +" step.write = true\n" +" end\n" +" end\n" +" end\n" +"end\n" "~~~" msgstr "" msgid "" -"Let's send a request to Droonga Engine.\n" -"Here, we use the first line of `stores.json`." +"Look at a new configuration `step.write`.\n" +"Because this command modifies the storage, we must indicate it clearly." msgstr "" -msgid "add-store.json:" +msgid "Let's define the handler." msgstr "" msgid "" -"~~~\n" -"{\"dataset\":\"Starbucks\",\"type\":\"add\",\"body\":{\"table\":\"Store\",\"key\":\"1st Avenue " -"& 75th St. - New York NY (W)\",\"values\":{\"location\":\"40.770262,-73.954798\"}}}\n" +" define_single_step do |step|\n" +" step.name = \"deleteStores\"\n" +" step.write = true\n" +" step.handler = :Handler\n" +" step.collector = AndCollector\n" +" end" +msgstr "" + +msgid "" +" class Handler < Droonga::Handler\n" +" def handle(message)\n" +" keyword = message[\"body\"][\"keyword\"]\n" +" table = @context[\"Store\"]\n" +" table.delete do |record|\n" +" record.key @ keyword\n" +" end\n" +" true\n" +" end\n" +" end\n" +" end\n" +" end\n" +"end\n" "~~~" msgstr "" -msgid "Send it to the engine:" +msgid "" +"The handler finds and deletes existing records which have the given keyword in" +" its \"key\", by the [API of Rroonga][Groonga::Table_delete]." +msgstr "" + +msgid "" +"And, the `AndCollector` is bound to the step by the configuration `step.collec" +"tor`.\n" +"It is is also one of built-in collectors, and merges boolean values retuned fr" +"om handler instances for each partition and replica, to one boolean value." +msgstr "" + +msgid "" +"Update catalog.json to activate this plugin.\n" +"Add `\"delete-stores\"` to `\"plugins\"`." msgstr "" msgid "" "~~~\n" -"# droonga-request --tag starbucks add-store.json\n" +"(snip)\n" +" \"datasets\": {\n" +" \"Starbucks\": {\n" +" (snip)\n" +" \"plugins\": [\"delete-stores\", \"count-records\", \"groonga\", \"crud\", \"se" +"arch\"],\n" +"(snip)\n" "~~~" msgstr "" -msgid "Instead, you will see results like this in `fluentd.log`:" +msgid "Restart the Droonga Engine and send the request." msgstr "" msgid "" "~~~\n" -"2014-02-17 16:29:18 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message" -"=#<Droonga::HandlerMessage:0x007f7f6a66c4c0 @raw={\"dataset\"=>\"Starbucks\", \"typ" -"e\"=>\"add\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#2\", \"task\"=>{\"route\"=>\"l" -"ocalhost:24224/starbucks.000\", \"step\"=>{\"command\"=>\"add\", \"dataset\"=>\"Starbuck" -"s\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st Avenue & 75th St. - New York NY (W" -")\", \"values\"=>{\"location\"=>\"40.770262,-73.954798\"}}, \"key\"=>\"1st Avenue & 75th" -" St. - New York NY (W)\", \"type\"=>\"scatter\", \"outputs\"=>[\"errors\", \"success\"]," -" \"replica\"=>\"all\", \"post\"=>true, \"routes\"=>[\"localhost:24224/starbucks.000\", \"" -"localhost:24224/starbucks.001\"], \"n_of_expects\"=>0, \"descendants\"=>{\"errors\"=>" -"[\"localhost:24224/starbucks.#2\"], \"success\"=>[\"localhost:24224/starbucks.#2\"]}" -"}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhost:2422" -"4/starbucks\"], \"success\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"type\"=" -">\"add.result\", \"to\"=>\"127.0.0.1:50480/droonga\"}, \"id\"=>\"1392622158.374441\", \"d" -"ate\"=>\"2014-02-17 16:29:18 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugins::CRUD" -"::Adapter\", \"Droonga::Plugins::Error::Adapter\"]}, @body={\"id\"=>\"localhost:2422" -"4/starbucks.#2\", \"task\"=>{\"route\"=>\"localhost:24224/starbucks.000\", \"step\"=>{\"" -"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1s" -"t Avenue & 75th St. - New York NY (W)\", \"values\"=>{\"location\"=>\"40.770262,-73" -".954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY (W)\", \"type\"=>\"scatte" -"r\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\"" -"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_ex" -"pects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succes" -"s\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"desc" -"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks\"], \"success\"=>[\"localhost:242" -"24/starbucks\"]}}, @task={\"route\"=>\"localhost:24224/starbucks.000\", \"step\"=>{\"c" -"ommand\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st" -" Avenue & 75th St. - New York NY (W)\", \"values\"=>{\"location\"=>\"40.770262,-73." -"954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY (W)\", \"type\"=>\"scatter" -"\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\"=" -">[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_exp" -"ects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"success" -"\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step=" -"{\"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"" -"1st Avenue & 75th St. - New York NY (W)\", \"values\"=>{\"location\"=>\"40.770262,-" -"73.954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY (W)\", \"type\"=>\"scat" -"ter\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"route" -"s\"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_" -"expects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succ" -"ess\"=>[\"localhost:24224/starbucks.#2\"]}}>\n" -"2014-02-17 16:29:18 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message" -"=#<Droonga::HandlerMessage:0x007f7f6a65ff40 @raw={\"dataset\"=>\"Starbucks\", \"typ" -"e\"=>\"add\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#2\", \"task\"=>{\"route\"=>\"l" -"ocalhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"add\", \"dataset\"=>\"Starbuck" -"s\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st Avenue & 75th St. - New York NY (W" -")\", \"values\"=>{\"location\"=>\"40.770262,-73.954798\"}}, \"key\"=>\"1st Avenue & 75th" -" St. - New York NY (W)\", \"type\"=>\"scatter\", \"outputs\"=>[\"errors\", \"success\"]," -" \"replica\"=>\"all\", \"post\"=>true, \"routes\"=>[\"localhost:24224/starbucks.000\", \"" -"localhost:24224/starbucks.001\"], \"n_of_expects\"=>0, \"descendants\"=>{\"errors\"=>" -"[\"localhost:24224/starbucks.#2\"], \"success\"=>[\"localhost:24224/starbucks.#2\"]}" -"}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhost:2422" -"4/starbucks\"], \"success\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"type\"=" -">\"add.result\", \"to\"=>\"127.0.0.1:50480/droonga\"}, \"id\"=>\"1392622158.374441\", \"d" -"ate\"=>\"2014-02-17 16:29:18 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugins::CRUD" -"::Adapter\", \"Droonga::Plugins::Error::Adapter\"]}, @body={\"id\"=>\"localhost:2422" -"4/starbucks.#2\", \"task\"=>{\"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\"" -"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1s" -"t Avenue & 75th St. - New York NY (W)\", \"values\"=>{\"location\"=>\"40.770262,-73" -".954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY (W)\", \"type\"=>\"scatte" -"r\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\"" -"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_ex" -"pects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succes" -"s\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"desc" -"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks\"], \"success\"=>[\"localhost:242" -"24/starbucks\"]}}, @task={\"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\"c" -"ommand\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st" -" Avenue & 75th St. - New York NY (W)\", \"values\"=>{\"location\"=>\"40.770262,-73." -"954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY (W)\", \"type\"=>\"scatter" -"\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\"=" -">[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_exp" -"ects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"success" -"\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step=" -"{\"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"" -"1st Avenue & 75th St. - New York NY (W)\", \"values\"=>{\"location\"=>\"40.770262,-" -"73.954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY (W)\", \"type\"=>\"scat" -"ter\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"route" -"s\"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_" -"expects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succ" -"ess\"=>[\"localhost:24224/starbucks.#2\"]}}>\n" +"# kill $(cat fluentd.pid)\n" +"# RUBYLIB=./lib fluentd --config fluentd.conf --log fluentd.log --daemon fluen" +"td.pid\n" +"# droonga-request --tag starbucks count-records.json\n" +"Elapsed time: 0.01494\n" +"[\n" +" \"droonga.message\",\n" +" 1392621168,\n" +" {\n" +" \"inReplyTo\": \"1392621168.0119512\",\n" +" \"statusCode\": 200,\n" +" \"type\": \"deleteStores.result\",\n" +" \"body\": true\n" +" }\n" +"]\n" "~~~" msgstr "" msgid "" -"In `add` case, two log lines are shown for one request. This is because we hav" -"e configured to have two replicas for each partition." +"Because results from partitions are unified to just one boolean value, the res" +"ponse's `body` is a `true`.\n" +"As the verification, send the request of `countRecords` command." +msgstr "" + +msgid "" +"~~~\n" +"# droonga-request --tag starbucks count-records.json\n" +"Elapsed time: 0.01494\n" +"[\n" +" \"droonga.message\",\n" +" 1392621168,\n" +" {\n" +" \"inReplyTo\": \"1392621168.0119512\",\n" +" \"statusCode\": 200,\n" +" \"type\": \"countRecords.result\",\n" +" \"body\": [8, 8, 7]\n" +" }\n" +"]\n" +"~~~" msgstr "" msgid "" -"In order to be consistent, `add` command must reach all of the replicas of the" -" partition, but not the other partitions.\n" -"As a consequence, `localhost:24224/starbucks.000` and `localhost:24224/starbuc" -"ks.001` are chosen." +"Note, the number of records are smaller than the previous result.\n" +"This means that 4 or some records are deleted from each partitions." msgstr "" msgid "## Conclusion" @@ -504,5 +662,8 @@ msgstr "" msgid "" " [adapter]: ../adapter\n" -" [basic]: ../basic" +" [basic]: ../basic\n" +" [Groonga::Context]: http://ranguba.org/rroonga/en/Groonga/Context.html\n" +" [Groonga::Table_delete]: http://ranguba.org/rroonga/en/Groonga/Table.html#de" +"lete-instance_method" msgstr "" Modified: _po/ja/tutorial/plugin-development/index.po (+2 -2) =================================================================== --- _po/ja/tutorial/plugin-development/index.po 2014-02-28 12:11:33 +0900 (72b84ed) +++ _po/ja/tutorial/plugin-development/index.po 2014-02-28 12:16:16 +0900 (12d4f24) @@ -60,7 +60,7 @@ msgid "" msgstr "" msgid "You can use plugins in those situations." -msgstr "このような状況でプラグインを利用することができます。" +msgstr "" msgid "## Pluggable operations in Droonga Engine" msgstr "## Droongaエンジンにおけるプラガブルな操作" @@ -116,7 +116,7 @@ msgid "## How to develop plugins?" msgstr "## プラグインを開発するには" msgid "For more details, let's read these sub tutorials:" -msgstr "詳細は以下のサブチュートリアルを参照してください:" +msgstr "" msgid "" " 1. [Modify requests and responses][adapter]\n" Modified: ja/tutorial/plugin-development/adapter/index.md (+1 -1) =================================================================== --- ja/tutorial/plugin-development/adapter/index.md 2014-02-28 12:11:33 +0900 (3c15cf9) +++ ja/tutorial/plugin-development/adapter/index.md 2014-02-28 12:16:16 +0900 (9f5a856) @@ -19,7 +19,7 @@ layout: ja Learning steps to develop a Droonga plugin by yourself. -This page focuses at the adaption phase for Droonga plugins. +This page focuses on the adaption phase for Droonga plugins. At the last, wraps up them to make a small practical plugin named `store-search`, for the adaption phase. ## 前提条件 Modified: ja/tutorial/plugin-development/index.md (+2 -2) =================================================================== --- ja/tutorial/plugin-development/index.md 2014-02-28 12:11:33 +0900 (7c78935) +++ ja/tutorial/plugin-development/index.md 2014-02-28 12:16:16 +0900 (a33f053) @@ -32,7 +32,7 @@ Generally, data processing tasks in the real world need custom treatments of the * One may want to do more complex data processing than that provided by Droonga as built-in, to have direct storage access for efficiency. * One may need to control data distribution and collection logic of Droonga to profit from distributed nature of Droonga. -このような状況でプラグインを利用することができます。 +You can use plugins in those situations. ## Droongaエンジンにおけるプラガブルな操作 @@ -64,7 +64,7 @@ Following this tutorial, you will learn how to write plugins. This will be the f ## プラグインを開発するには -詳細は以下のサブチュートリアルを参照してください: +For more details, let's read these sub tutorials: 1. [Modify requests and responses][adapter] 2. [Handle requests on all partitions][handler] -------------- next part -------------- HTML����������������������������...Download