fluent-plugin-droonga 0.0.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +6 -0
- data/.yardopts +7 -0
- data/Gemfile +14 -2
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/Rakefile +27 -5
- data/benchmark/benchmark.rb +1 -1
- data/benchmark/utils.rb +9 -6
- data/benchmark/watch/benchmark-notify.rb +2 -2
- data/benchmark/watch/benchmark-publish.rb +1 -1
- data/benchmark/watch/benchmark-scan.rb +1 -1
- data/benchmark/watch/catalog.json +1 -1
- data/bin/grn2jsons +1 -1
- data/fluent-plugin-droonga.gemspec +5 -3
- data/lib/droonga/adapter.rb +13 -130
- data/lib/droonga/adapter_plugin.rb +51 -0
- data/lib/droonga/catalog.rb +2 -2
- data/lib/droonga/collector.rb +107 -0
- data/lib/droonga/collector_plugin.rb +82 -0
- data/lib/droonga/command_mapper.rb +1 -1
- data/lib/droonga/{proxy.rb → dispatcher.rb} +116 -151
- data/lib/droonga/distributor.rb +51 -0
- data/lib/droonga/distributor_plugin.rb +59 -0
- data/lib/droonga/engine.rb +9 -50
- data/lib/droonga/farm.rb +47 -0
- data/lib/droonga/forwarder.rb +125 -0
- data/lib/droonga/handler.rb +69 -60
- data/lib/droonga/handler_plugin.rb +22 -11
- data/lib/droonga/input_message.rb +51 -0
- data/lib/droonga/job_queue.rb +5 -1
- data/lib/droonga/job_queue_schema.rb +1 -1
- data/lib/droonga/logger.rb +1 -1
- data/lib/droonga/partition.rb +76 -0
- data/lib/droonga/pluggable.rb +62 -0
- data/lib/droonga/plugin.rb +18 -16
- data/lib/droonga/plugin/{adapter_groonga.rb → adapter/groonga.rb} +10 -10
- data/lib/droonga/plugin/adapter/groonga/select.rb +13 -4
- data/lib/droonga/plugin/collector/basic.rb +142 -0
- data/lib/droonga/plugin/distributor/crud.rb +43 -0
- data/lib/droonga/plugin/distributor/groonga.rb +37 -0
- data/lib/droonga/plugin/distributor/search.rb +273 -0
- data/lib/droonga/plugin/distributor/watch.rb +39 -0
- data/lib/droonga/plugin/{handler_add.rb → handler/add.rb} +6 -6
- data/lib/droonga/plugin/{handler_forward.rb → handler/forward.rb} +9 -4
- data/lib/droonga/plugin/{handler_groonga.rb → handler/groonga.rb} +36 -4
- data/lib/droonga/plugin/handler/groonga/column_create.rb +5 -9
- data/lib/droonga/plugin/handler/groonga/table_create.rb +9 -18
- data/lib/droonga/plugin/{handler_search.rb → handler/search.rb} +4 -4
- data/lib/droonga/plugin/{handler_watch.rb → handler/watch.rb} +4 -4
- data/lib/droonga/plugin_loader.rb +45 -0
- data/lib/droonga/plugin_registerable.rb +51 -0
- data/lib/droonga/plugin_repository.rb +56 -0
- data/lib/droonga/processor.rb +64 -0
- data/lib/droonga/searcher.rb +16 -7
- data/lib/droonga/server.rb +5 -9
- data/lib/droonga/sweeper.rb +1 -1
- data/lib/droonga/watch_schema.rb +1 -1
- data/lib/droonga/watcher.rb +1 -1
- data/lib/droonga/worker.rb +21 -9
- data/lib/fluent/plugin/out_droonga.rb +33 -15
- data/lib/groonga_command_converter.rb +1 -1
- data/sample/cluster/fluentd.conf +0 -1
- data/test/command/config/default/catalog.json +43 -0
- data/test/command/config/default/fluentd.conf +11 -0
- data/test/command/fixture/documents.jsons +208 -0
- data/test/command/fixture/user-table-array.jsons +38 -0
- data/test/command/fixture/user-table.jsons +38 -0
- data/test/command/run-test.rb +35 -0
- data/test/command/suite/add/minimum.expected +12 -0
- data/test/command/suite/add/minimum.test +11 -0
- data/test/command/suite/add/with-values.expected +12 -0
- data/test/command/suite/add/with-values.test +17 -0
- data/test/command/suite/add/without-key.expected +12 -0
- data/test/command/suite/add/without-key.test +16 -0
- data/test/command/suite/groonga/column_create/scalar.expected +34 -0
- data/test/command/suite/groonga/column_create/scalar.test +17 -0
- data/test/command/suite/groonga/column_create/vector.expected +34 -0
- data/test/command/suite/groonga/column_create/vector.test +18 -0
- data/test/command/suite/groonga/select/minimum.expected +26 -0
- data/test/command/suite/groonga/select/minimum.test +8 -0
- data/test/command/suite/groonga/table_create/array.expected +17 -0
- data/test/command/suite/groonga/table_create/array.test +8 -0
- data/test/command/suite/groonga/table_create/hash.expected +17 -0
- data/test/command/suite/groonga/table_create/hash.test +8 -0
- data/test/command/suite/search/array-attribute-label.expected +25 -0
- data/test/command/suite/search/array-attribute-label.test +30 -0
- data/test/command/suite/search/chained-queries.expected +45 -0
- data/test/command/suite/search/chained-queries.test +43 -0
- data/test/command/suite/search/complex.expected +52 -0
- data/test/command/suite/search/complex.test +25 -0
- data/test/command/suite/search/condition-nested.expected +19 -0
- data/test/command/suite/search/condition-nested.test +29 -0
- data/test/command/suite/search/condition-query.expected +28 -0
- data/test/command/suite/search/condition-query.test +25 -0
- data/test/command/suite/search/condition-script.expected +28 -0
- data/test/command/suite/search/condition-script.test +28 -0
- data/test/command/suite/search/hash-attribute-label.expected +34 -0
- data/test/command/suite/search/hash-attribute-label.test +38 -0
- data/test/command/suite/search/minimum.expected +13 -0
- data/test/command/suite/search/minimum.test +16 -0
- data/test/command/suite/search/multiple-queries.expected +39 -0
- data/test/command/suite/search/multiple-queries.test +39 -0
- data/test/command/suite/search/output-range.expected +28 -0
- data/test/command/suite/search/output-range.test +25 -0
- data/test/command/suite/search/simple.expected +52 -0
- data/test/command/suite/search/simple.test +24 -0
- data/test/command/suite/search/sort-and-output-range.expected +25 -0
- data/test/command/suite/search/sort-and-output-range.test +29 -0
- data/test/command/suite/search/sort-range.expected +28 -0
- data/test/command/suite/search/sort-range.test +28 -0
- data/test/command/suite/search/sort-with-invisible-column.expected +28 -0
- data/test/command/suite/search/sort-with-invisible-column.test +28 -0
- data/test/unit/fixtures/array.grn +18 -0
- data/test/{fixtures → unit/fixtures}/catalog.json +0 -0
- data/test/{fixtures → unit/fixtures}/document.grn +20 -9
- data/test/unit/fixtures/reference/array.grn +11 -0
- data/test/unit/fixtures/reference/hash.grn +7 -0
- data/test/{helper.rb → unit/helper.rb} +2 -1
- data/test/{helper → unit/helper}/fixture.rb +1 -1
- data/test/unit/helper/plugin_helper.rb +38 -0
- data/test/{helper → unit/helper}/sandbox.rb +19 -6
- data/test/{helper → unit/helper}/stub_worker.rb +1 -1
- data/test/{helper → unit/helper}/watch_helper.rb +1 -13
- data/test/{plugin → unit/plugin}/adapter/groonga/test_select.rb +108 -4
- data/test/unit/plugin/collector/test_basic.rb +558 -0
- data/test/unit/plugin/distributor/test_search.rb +914 -0
- data/test/{plugin → unit/plugin}/handler/groonga/test_column_create.rb +18 -14
- data/test/{plugin → unit/plugin}/handler/groonga/test_table_create.rb +13 -11
- data/test/{plugin/handler/test_handler_add.rb → unit/plugin/handler/test_add.rb} +2 -14
- data/test/{plugin/handler/test_handler_groonga.rb → unit/plugin/handler/test_groonga.rb} +6 -26
- data/test/unit/plugin/handler/test_search.rb +601 -0
- data/test/{plugin/handler/test_handler_watch.rb → unit/plugin/handler/test_watch.rb} +2 -2
- data/test/{run-test.rb → unit/run-test.rb} +3 -3
- data/test/{test_adapter.rb → unit/test_adapter.rb} +17 -14
- data/test/{test_catalog.rb → unit/test_catalog.rb} +4 -4
- data/test/{test_command_mapper.rb → unit/test_command_mapper.rb} +1 -1
- data/test/{test_groonga_command_converter.rb → unit/test_groonga_command_converter.rb} +3 -3
- data/test/{test_job_queue_schema.rb → unit/test_job_queue_schema.rb} +1 -1
- data/test/{test_output.rb → unit/test_output.rb} +9 -9
- data/test/{test_handler.rb → unit/test_plugin.rb} +19 -22
- data/test/unit/test_plugin_repository.rb +89 -0
- data/test/{test_sweeper.rb → unit/test_sweeper.rb} +1 -1
- data/test/{test_watch_schema.rb → unit/test_watch_schema.rb} +1 -1
- data/test/{test_watcher.rb → unit/test_watcher.rb} +1 -1
- metadata +226 -66
- data/lib/droonga/executor.rb +0 -289
- data/lib/droonga/plugin/handler_proxy.rb +0 -82
- data/test/plugin/handler/test_handler_search.rb +0 -512
- data/test/test_worker.rb +0 -144
data/lib/droonga/catalog.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2013
|
|
3
|
+
# Copyright (C) 2013 Droonga Project
|
|
4
4
|
#
|
|
5
5
|
# This library is free software; you can redistribute it and/or
|
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
|
@@ -63,7 +63,7 @@ module Droonga
|
|
|
63
63
|
@options[name]
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
def
|
|
66
|
+
def get_partitions(name)
|
|
67
67
|
device = @catalog["farms"][name]["device"]
|
|
68
68
|
pattern = Regexp.new("^#{name}\.")
|
|
69
69
|
results = {}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2013 Droonga Project
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
8
|
+
#
|
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
+
# Lesser General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
15
|
+
# License along with this library; if not, write to the Free Software
|
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
17
|
+
|
|
18
|
+
require "droonga/pluggable"
|
|
19
|
+
require "droonga/collector_plugin"
|
|
20
|
+
|
|
21
|
+
module Droonga
|
|
22
|
+
class Collector
|
|
23
|
+
include Pluggable
|
|
24
|
+
|
|
25
|
+
def initialize(id, dispatcher, components, tasks, inputs)
|
|
26
|
+
@id = id
|
|
27
|
+
@dispatcher = dispatcher
|
|
28
|
+
@components = components
|
|
29
|
+
@tasks = tasks
|
|
30
|
+
@n_dones = 0
|
|
31
|
+
@inputs = inputs
|
|
32
|
+
load_plugins(["basic"]) # TODO: make customizable
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def handle(name, value)
|
|
36
|
+
tasks = @inputs[name]
|
|
37
|
+
unless tasks
|
|
38
|
+
#TODO: result arrived before its query
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
tasks.each do |task|
|
|
42
|
+
task["n_of_inputs"] += 1 if name
|
|
43
|
+
component = task["component"]
|
|
44
|
+
type = component["type"]
|
|
45
|
+
command = component["command"] || ("collector_" + type)
|
|
46
|
+
n_of_expects = component["n_of_expects"]
|
|
47
|
+
synchronous = nil
|
|
48
|
+
if command
|
|
49
|
+
synchronous = true unless n_of_expects.zero?
|
|
50
|
+
# TODO: check if asynchronous execution is available.
|
|
51
|
+
message = {
|
|
52
|
+
"task"=>task,
|
|
53
|
+
"name"=>name,
|
|
54
|
+
"value"=>value
|
|
55
|
+
}
|
|
56
|
+
unless synchronous
|
|
57
|
+
descendants = {}
|
|
58
|
+
component["descendants"].each do |name, indices|
|
|
59
|
+
descendants[name] = indices.collect do |index|
|
|
60
|
+
@components[index]["routes"].map do |route|
|
|
61
|
+
@dispatcher.farm_path(route)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
message["descendants"] = descendants
|
|
66
|
+
message["id"] = @id
|
|
67
|
+
end
|
|
68
|
+
if @id == task["route"]
|
|
69
|
+
process(command, message)
|
|
70
|
+
else
|
|
71
|
+
@dispatcher.deliver(@id, task["route"], message, command, synchronous)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
return if task["n_of_inputs"] < n_of_expects
|
|
75
|
+
#the task is done
|
|
76
|
+
if synchronous
|
|
77
|
+
result = task["values"]
|
|
78
|
+
post = component["post"]
|
|
79
|
+
@dispatcher.post(result, post) if post
|
|
80
|
+
component["descendants"].each do |name, indices|
|
|
81
|
+
message = {
|
|
82
|
+
"id" => @id,
|
|
83
|
+
"input" => name,
|
|
84
|
+
"value" => result[name]
|
|
85
|
+
}
|
|
86
|
+
indices.each do |index|
|
|
87
|
+
@components[index]["routes"].each do |route|
|
|
88
|
+
@dispatcher.dispatch(message, route)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
@n_dones += 1
|
|
94
|
+
@dispatcher.collectors.delete(@id) if @n_dones == @tasks.size
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
def instantiate_plugin(name)
|
|
100
|
+
CollectorPlugin.repository.instantiate(name, @dispatcher)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def log_tag
|
|
104
|
+
"collector"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2013 Droonga Project
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
8
|
+
#
|
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
+
# Lesser General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
15
|
+
# License along with this library; if not, write to the Free Software
|
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
17
|
+
|
|
18
|
+
require "droonga/plugin"
|
|
19
|
+
|
|
20
|
+
module Droonga
|
|
21
|
+
class CollectorPlugin < Plugin
|
|
22
|
+
extend PluginRegisterable
|
|
23
|
+
|
|
24
|
+
attr_reader :task, :input_name, :component, :output_values, :body, :output_names
|
|
25
|
+
def initialize(dispatcher)
|
|
26
|
+
super()
|
|
27
|
+
@dispatcher = dispatcher
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def process(command, message)
|
|
31
|
+
return false unless message.is_a? Hash
|
|
32
|
+
@task = message["task"]
|
|
33
|
+
return false unless @task.is_a? Hash
|
|
34
|
+
@component = @task["component"]
|
|
35
|
+
return false unless @component.is_a? Hash
|
|
36
|
+
@output_values = @task["values"]
|
|
37
|
+
@body = @component["body"]
|
|
38
|
+
@output_names = @component["outputs"]
|
|
39
|
+
@id = message["id"]
|
|
40
|
+
@value = message["value"]
|
|
41
|
+
@input_name = message["name"]
|
|
42
|
+
@descendants = message["descendants"]
|
|
43
|
+
super(command, @value)
|
|
44
|
+
output if @descendants
|
|
45
|
+
true
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# TODO: consider better name
|
|
49
|
+
def emit(value, name=nil)
|
|
50
|
+
unless name
|
|
51
|
+
if @output_names
|
|
52
|
+
name = @output_names.first
|
|
53
|
+
else
|
|
54
|
+
@output_values = @task["values"] = value
|
|
55
|
+
return
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
@output_values[name] = value
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def post(message, destination=nil)
|
|
62
|
+
@dispatcher.post(message, destination)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def output
|
|
66
|
+
result = @task["values"]
|
|
67
|
+
post(result, @component["post"]) if @component["post"]
|
|
68
|
+
@descendants.each do |name, dests|
|
|
69
|
+
message = {
|
|
70
|
+
"id" => @id,
|
|
71
|
+
"input" => name,
|
|
72
|
+
"value" => result[name]
|
|
73
|
+
}
|
|
74
|
+
dests.each do |routes|
|
|
75
|
+
routes.each do |route|
|
|
76
|
+
post(message, "to"=>route, "type"=>"dispatcher")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2013
|
|
3
|
+
# Copyright (C) 2013 Droonga Project
|
|
4
4
|
#
|
|
5
5
|
# This library is free software; you can redistribute it and/or
|
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
|
@@ -16,36 +16,94 @@
|
|
|
16
16
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
17
17
|
|
|
18
18
|
require 'tsort'
|
|
19
|
-
require "droonga/handler"
|
|
20
19
|
require "droonga/adapter"
|
|
20
|
+
require "droonga/distributor"
|
|
21
21
|
require "droonga/catalog"
|
|
22
|
+
require "droonga/collector"
|
|
23
|
+
require "droonga/farm"
|
|
24
|
+
require "droonga/input_message"
|
|
22
25
|
|
|
23
26
|
module Droonga
|
|
24
|
-
class
|
|
25
|
-
attr_reader :collectors
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
engine.start
|
|
32
|
-
@engines[name] = engine
|
|
33
|
-
end
|
|
34
|
-
@worker = worker
|
|
35
|
-
@name = name
|
|
27
|
+
class Dispatcher
|
|
28
|
+
attr_reader :name, :envelope, :collectors
|
|
29
|
+
|
|
30
|
+
def initialize(options)
|
|
31
|
+
@options = options
|
|
32
|
+
@name = @options[:name]
|
|
33
|
+
@farm = Farm.new(name)
|
|
36
34
|
@collectors = {}
|
|
37
35
|
@current_id = 0
|
|
38
36
|
@local = Regexp.new("^#{@name}")
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
@adapter = Adapter.new(self,
|
|
38
|
+
:adapters => Droonga.catalog.option("plugins"))
|
|
39
|
+
@forwarder = Forwarder.new
|
|
40
|
+
@distributor = Distributor.new(self, @options)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def start
|
|
44
|
+
@farm.start
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
def shutdown
|
|
46
|
-
@
|
|
47
|
-
|
|
48
|
+
@forwarder.shutdown
|
|
49
|
+
@distributor.shutdown
|
|
50
|
+
@adapter.shutdown
|
|
51
|
+
@farm.shutdown
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def add_route(route)
|
|
55
|
+
envelope["via"].push(route)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def handle_envelope(envelope)
|
|
59
|
+
@envelope = envelope
|
|
60
|
+
if envelope["type"] == "dispatcher"
|
|
61
|
+
handle(envelope["body"], envelope["arguments"])
|
|
62
|
+
else
|
|
63
|
+
process_input_message(envelope)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def post(body, destination=nil)
|
|
68
|
+
$log.trace("#{log_tag}: post: start")
|
|
69
|
+
route = nil
|
|
70
|
+
unless is_route?(destination)
|
|
71
|
+
route = envelope["via"].pop
|
|
72
|
+
destination = route
|
|
73
|
+
end
|
|
74
|
+
unless is_route?(destination)
|
|
75
|
+
destination = envelope["replyTo"]
|
|
76
|
+
end
|
|
77
|
+
command = nil
|
|
78
|
+
receiver = nil
|
|
79
|
+
arguments = nil
|
|
80
|
+
synchronous = nil
|
|
81
|
+
case destination
|
|
82
|
+
when String
|
|
83
|
+
command = destination
|
|
84
|
+
when Hash
|
|
85
|
+
command = destination["type"]
|
|
86
|
+
receiver = destination["to"]
|
|
87
|
+
arguments = destination["arguments"]
|
|
88
|
+
synchronous = destination["synchronous"]
|
|
89
|
+
end
|
|
90
|
+
if receiver
|
|
91
|
+
@forwarder.forward(envelope, body,
|
|
92
|
+
"type" => command,
|
|
93
|
+
"to" => receiver,
|
|
94
|
+
"arguments" => arguments)
|
|
95
|
+
else
|
|
96
|
+
if command == "dispatcher"
|
|
97
|
+
handle(body, arguments)
|
|
98
|
+
elsif @adapter.processable?(command)
|
|
99
|
+
@adapter.process(command, body, *arguments)
|
|
100
|
+
else
|
|
101
|
+
@distributor.distribute(envelope.merge("type" => command,
|
|
102
|
+
"body" => body))
|
|
103
|
+
end
|
|
48
104
|
end
|
|
105
|
+
add_route(route) if route
|
|
106
|
+
$log.trace("#{log_tag}: post: done")
|
|
49
107
|
end
|
|
50
108
|
|
|
51
109
|
def handle(message, arguments)
|
|
@@ -87,7 +145,7 @@ module Droonga
|
|
|
87
145
|
if local?(destination)
|
|
88
146
|
handle_internal_message(message)
|
|
89
147
|
else
|
|
90
|
-
post(message, "to"=>farm_path(destination), "type"=>"
|
|
148
|
+
post(message, "to"=>farm_path(destination), "type"=>"dispatcher")
|
|
91
149
|
end
|
|
92
150
|
end
|
|
93
151
|
|
|
@@ -95,15 +153,11 @@ module Droonga
|
|
|
95
153
|
if id == route
|
|
96
154
|
post(message, "type" => type, "synchronous"=> synchronous)
|
|
97
155
|
else
|
|
98
|
-
envelope = @
|
|
99
|
-
@
|
|
156
|
+
envelope = @envelope.merge("body" => message, "type" => type)
|
|
157
|
+
@farm.process(route, envelope, synchronous)
|
|
100
158
|
end
|
|
101
159
|
end
|
|
102
160
|
|
|
103
|
-
def post(message, destination)
|
|
104
|
-
@worker.post(message, destination)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
161
|
def generate_id
|
|
108
162
|
id = @current_id
|
|
109
163
|
@current_id = id.succ
|
|
@@ -122,6 +176,34 @@ module Droonga
|
|
|
122
176
|
route =~ @local
|
|
123
177
|
end
|
|
124
178
|
|
|
179
|
+
private
|
|
180
|
+
def is_route?(route)
|
|
181
|
+
route.is_a?(String) || route.is_a?(Hash)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def apply_input_adapters(envelope)
|
|
185
|
+
adapted_envelope = envelope
|
|
186
|
+
loop do
|
|
187
|
+
input_message = InputMessage.new(adapted_envelope)
|
|
188
|
+
command = input_message.command
|
|
189
|
+
break unless @adapter.processable?(command)
|
|
190
|
+
@adapter.process(command, input_message)
|
|
191
|
+
new_command = input_message.command
|
|
192
|
+
adapted_envelope = input_message.adapted_envelope
|
|
193
|
+
break if command == new_command
|
|
194
|
+
end
|
|
195
|
+
adapted_envelope
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def process_input_message(envelope)
|
|
199
|
+
adapted_envelope = apply_input_adapters(envelope)
|
|
200
|
+
@distributor.distribute(adapted_envelope)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def log_tag
|
|
204
|
+
"[#{Process.ppid}][#{Process.pid}] dispatcher"
|
|
205
|
+
end
|
|
206
|
+
|
|
125
207
|
class Planner
|
|
126
208
|
attr_reader :components
|
|
127
209
|
class UndefinedInputError < StandardError
|
|
@@ -141,8 +223,8 @@ module Droonga
|
|
|
141
223
|
end
|
|
142
224
|
|
|
143
225
|
include TSort
|
|
144
|
-
def initialize(
|
|
145
|
-
@
|
|
226
|
+
def initialize(dispatcher, components)
|
|
227
|
+
@dispatcher = dispatcher
|
|
146
228
|
@components = components
|
|
147
229
|
end
|
|
148
230
|
|
|
@@ -170,12 +252,12 @@ module Droonga
|
|
|
170
252
|
dataset = component["dataset"]
|
|
171
253
|
routes =
|
|
172
254
|
if dataset
|
|
173
|
-
Droonga
|
|
255
|
+
Droonga.catalog.get_routes(dataset, component)
|
|
174
256
|
else
|
|
175
257
|
local
|
|
176
258
|
end
|
|
177
259
|
routes.each do |route|
|
|
178
|
-
destinations[@
|
|
260
|
+
destinations[@dispatcher.farm_path(route)] += 1
|
|
179
261
|
end
|
|
180
262
|
component["routes"] = routes
|
|
181
263
|
end
|
|
@@ -188,7 +270,7 @@ module Droonga
|
|
|
188
270
|
inputs = {}
|
|
189
271
|
@components.each do |component|
|
|
190
272
|
component["routes"].each do |route|
|
|
191
|
-
next unless @
|
|
273
|
+
next unless @dispatcher.local?(route)
|
|
192
274
|
task = {
|
|
193
275
|
"route" => route,
|
|
194
276
|
"component" => component,
|
|
@@ -202,8 +284,8 @@ module Droonga
|
|
|
202
284
|
end
|
|
203
285
|
end
|
|
204
286
|
end
|
|
205
|
-
collector = Collector.new(id, @
|
|
206
|
-
@
|
|
287
|
+
collector = Collector.new(id, @dispatcher, @components, tasks, inputs)
|
|
288
|
+
@dispatcher.collectors[id] = collector
|
|
207
289
|
return collector
|
|
208
290
|
end
|
|
209
291
|
|
|
@@ -250,122 +332,5 @@ module Droonga
|
|
|
250
332
|
end
|
|
251
333
|
end
|
|
252
334
|
end
|
|
253
|
-
|
|
254
|
-
class Collector
|
|
255
|
-
def initialize(id, proxy, components, tasks, inputs)
|
|
256
|
-
@id = id
|
|
257
|
-
@proxy = proxy
|
|
258
|
-
@components = components
|
|
259
|
-
@tasks = tasks
|
|
260
|
-
@n_dones = 0
|
|
261
|
-
@inputs = inputs
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def handle(name, value)
|
|
265
|
-
tasks = @inputs[name]
|
|
266
|
-
unless tasks
|
|
267
|
-
#TODO: result arrived before its query
|
|
268
|
-
return
|
|
269
|
-
end
|
|
270
|
-
tasks.each do |task|
|
|
271
|
-
task["n_of_inputs"] += 1 if name
|
|
272
|
-
component = task["component"]
|
|
273
|
-
type = component["type"]
|
|
274
|
-
command = component["command"] || ("proxy_" + type)
|
|
275
|
-
n_of_expects = component["n_of_expects"]
|
|
276
|
-
synchronous = nil
|
|
277
|
-
if command
|
|
278
|
-
# TODO: should be controllable for each command respectively.
|
|
279
|
-
synchronous = !n_of_expects.zero?
|
|
280
|
-
# TODO: check if asynchronous execution is available.
|
|
281
|
-
message = {
|
|
282
|
-
"task"=>task,
|
|
283
|
-
"name"=>name,
|
|
284
|
-
"value"=>value
|
|
285
|
-
}
|
|
286
|
-
unless synchronous
|
|
287
|
-
descendants = {}
|
|
288
|
-
component["descendants"].each do |name, indices|
|
|
289
|
-
descendants[name] = indices.collect do |index|
|
|
290
|
-
@components[index]["routes"].map do |route|
|
|
291
|
-
@proxy.farm_path(route)
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
message["descendants"] = descendants
|
|
296
|
-
message["id"] = @id
|
|
297
|
-
end
|
|
298
|
-
@proxy.deliver(@id, task["route"], message, command, synchronous)
|
|
299
|
-
end
|
|
300
|
-
return if task["n_of_inputs"] < n_of_expects
|
|
301
|
-
#the task is done
|
|
302
|
-
if synchronous
|
|
303
|
-
result = task["values"]
|
|
304
|
-
post = component["post"]
|
|
305
|
-
@proxy.post(result, post) if post
|
|
306
|
-
component["descendants"].each do |name, indices|
|
|
307
|
-
message = {
|
|
308
|
-
"id" => @id,
|
|
309
|
-
"input" => name,
|
|
310
|
-
"value" => result[name]
|
|
311
|
-
}
|
|
312
|
-
indices.each do |index|
|
|
313
|
-
@components[index]["routes"].each do |route|
|
|
314
|
-
@proxy.dispatch(message, route)
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
@n_dones += 1
|
|
320
|
-
@proxy.collectors.delete(@id) if @n_dones == @tasks.size
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
class ProxyMessageHandler < Droonga::Handler
|
|
327
|
-
Droonga::HandlerPlugin.register("proxy_message", self)
|
|
328
|
-
def initialize(*arguments)
|
|
329
|
-
super
|
|
330
|
-
@proxy = Droonga::Proxy.new(@worker, @worker.name)
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
def shutdown
|
|
334
|
-
@proxy.shutdown
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
command :proxy
|
|
338
|
-
def proxy(request, *arguments)
|
|
339
|
-
@proxy.handle(request, arguments)
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
def prefer_synchronous?(command)
|
|
343
|
-
return true
|
|
344
|
-
end
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
class ProxyHandler < Droonga::Handler
|
|
348
|
-
attr_reader :task, :input_name, :component, :output_values, :body, :output_names
|
|
349
|
-
def handle(command, request, *arguments)
|
|
350
|
-
return false unless request.is_a? Hash
|
|
351
|
-
@task = request["task"]
|
|
352
|
-
return false unless @task.is_a? Hash
|
|
353
|
-
@component = @task["component"]
|
|
354
|
-
return false unless @component.is_a? Hash
|
|
355
|
-
@output_values = @task["values"]
|
|
356
|
-
@body = @component["body"]
|
|
357
|
-
@output_names = @component["outputs"]
|
|
358
|
-
@id = request["id"]
|
|
359
|
-
@value = request["value"]
|
|
360
|
-
@input_name = request["name"]
|
|
361
|
-
@descendants = request["descendants"]
|
|
362
|
-
invoke(command, @value, *arguments)
|
|
363
|
-
output if @descendants
|
|
364
|
-
true
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
def prefer_synchronous?(command)
|
|
368
|
-
return true
|
|
369
|
-
end
|
|
370
335
|
end
|
|
371
336
|
end
|