fluent-plugin-droonga 0.0.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|