fluent-plugin-droonga 0.7.0 → 0.8.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 +1 -4
- data/benchmark/watch/benchmark-notify.rb +2 -2
- data/benchmark/watch/benchmark-scan.rb +3 -0
- data/benchmark/watch/fluentd.conf +0 -1
- data/fluent-plugin-droonga.gemspec +2 -3
- data/lib/droonga/catalog.rb +10 -124
- data/lib/droonga/catalog/base.rb +140 -0
- data/lib/droonga/catalog/version1.rb +23 -0
- data/lib/droonga/catalog_loader.rb +33 -0
- data/lib/droonga/collector.rb +2 -71
- data/lib/droonga/collector_plugin.rb +2 -34
- data/lib/droonga/dispatcher.rb +141 -196
- data/lib/droonga/distribution_planner.rb +76 -0
- data/lib/droonga/distributor.rb +5 -7
- data/lib/droonga/distributor_plugin.rb +23 -15
- data/lib/droonga/engine.rb +2 -2
- data/lib/droonga/event_loop.rb +46 -0
- data/lib/droonga/farm.rb +9 -5
- data/lib/droonga/fluent_message_sender.rb +84 -0
- data/lib/droonga/forwarder.rb +43 -53
- data/lib/droonga/handler.rb +20 -68
- data/lib/droonga/handler_message.rb +61 -0
- data/lib/droonga/handler_messenger.rb +92 -0
- data/lib/droonga/handler_plugin.rb +10 -12
- data/lib/droonga/input_adapter.rb +52 -0
- data/lib/droonga/{adapter.rb → input_adapter_plugin.rb} +7 -13
- data/lib/droonga/input_message.rb +11 -11
- data/lib/droonga/logger.rb +4 -3
- data/lib/droonga/message_pack_packer.rb +62 -0
- data/lib/droonga/message_processing_error.rb +54 -0
- data/lib/droonga/message_pusher.rb +60 -0
- data/lib/droonga/message_receiver.rb +61 -0
- data/lib/droonga/output_adapter.rb +53 -0
- data/lib/droonga/{adapter_plugin.rb → output_adapter_plugin.rb} +3 -21
- data/lib/droonga/output_message.rb +37 -0
- data/lib/droonga/partition.rb +27 -5
- data/lib/droonga/pluggable.rb +9 -4
- data/lib/droonga/plugin.rb +12 -3
- data/lib/droonga/plugin/collector/basic.rb +91 -18
- data/lib/droonga/plugin/distributor/crud.rb +9 -9
- data/lib/droonga/plugin/distributor/distributed_search_planner.rb +401 -0
- data/lib/droonga/plugin/distributor/groonga.rb +5 -5
- data/lib/droonga/plugin/distributor/search.rb +4 -246
- data/lib/droonga/plugin/distributor/watch.rb +11 -6
- data/lib/droonga/plugin/handler/add.rb +69 -7
- data/lib/droonga/plugin/handler/groonga.rb +6 -6
- data/lib/droonga/plugin/handler/search.rb +5 -3
- data/lib/droonga/plugin/handler/watch.rb +19 -13
- data/lib/droonga/plugin/{adapter → input_adapter}/groonga.rb +5 -11
- data/lib/droonga/plugin/{adapter → input_adapter}/groonga/select.rb +2 -36
- data/lib/droonga/plugin/output_adapter/groonga.rb +30 -0
- data/lib/droonga/plugin/output_adapter/groonga/select.rb +54 -0
- data/lib/droonga/plugin_loader.rb +2 -2
- data/lib/droonga/processor.rb +21 -23
- data/lib/droonga/replier.rb +40 -0
- data/lib/droonga/searcher.rb +298 -174
- data/lib/droonga/server.rb +0 -67
- data/lib/droonga/session.rb +85 -0
- data/lib/droonga/test.rb +21 -0
- data/lib/droonga/test/stub_distributor.rb +31 -0
- data/lib/droonga/test/stub_handler.rb +37 -0
- data/lib/droonga/test/stub_handler_message.rb +35 -0
- data/lib/droonga/test/stub_handler_messenger.rb +34 -0
- data/lib/droonga/time_formatter.rb +37 -0
- data/lib/droonga/watcher.rb +1 -0
- data/lib/droonga/worker.rb +16 -19
- data/lib/fluent/plugin/out_droonga.rb +9 -9
- data/lib/groonga_command_converter.rb +5 -5
- data/sample/cluster/catalog.json +1 -1
- data/test/command/config/default/catalog.json +19 -1
- data/test/command/fixture/event.jsons +41 -0
- data/test/command/fixture/user-table.jsons +9 -0
- data/test/command/run-test.rb +2 -2
- data/test/command/suite/add/error/invalid-integer.expected +20 -0
- data/test/command/suite/add/error/invalid-integer.test +12 -0
- data/test/command/suite/add/error/invalid-time.expected +20 -0
- data/test/command/suite/add/error/invalid-time.test +12 -0
- data/test/command/suite/add/error/missing-key.expected +13 -0
- data/test/command/suite/add/error/missing-key.test +16 -0
- data/test/command/suite/add/error/missing-table.expected +13 -0
- data/test/command/suite/add/error/missing-table.test +16 -0
- data/test/command/suite/add/error/unknown-column.expected +20 -0
- data/test/command/suite/add/error/unknown-column.test +12 -0
- data/test/command/suite/add/error/unknown-table.expected +13 -0
- data/test/command/suite/add/error/unknown-table.test +17 -0
- data/test/command/suite/add/minimum.expected +1 -3
- data/test/command/suite/add/with-values.expected +1 -3
- data/test/command/suite/add/without-key.expected +1 -3
- data/test/command/suite/message/error/missing-dataset.expected +13 -0
- data/test/command/suite/message/error/missing-dataset.test +5 -0
- data/test/command/suite/message/error/unknown-command.expected +13 -0
- data/test/command/suite/message/error/unknown-command.test +6 -0
- data/test/command/suite/message/error/unknown-dataset.expected +13 -0
- data/test/command/suite/message/error/unknown-dataset.test +6 -0
- data/test/command/suite/search/{array-attribute-label.expected → attributes/array.expected} +0 -0
- data/test/command/suite/search/{array-attribute-label.test → attributes/array.test} +0 -0
- data/test/command/suite/search/{hash-attribute-label.expected → attributes/hash.expected} +0 -0
- data/test/command/suite/search/{hash-attribute-label.test → attributes/hash.test} +0 -0
- data/test/command/suite/search/{condition-nested.expected → condition/nested.expected} +0 -0
- data/test/command/suite/search/{condition-nested.test → condition/nested.test} +0 -0
- data/test/command/suite/search/{condition-query.expected → condition/query.expected} +0 -0
- data/test/command/suite/search/{condition-query.test → condition/query.test} +0 -0
- data/test/command/suite/search/{condition-script.expected → condition/script.expected} +0 -0
- data/test/command/suite/search/{condition-script.test → condition/script.test} +0 -0
- data/test/command/suite/search/error/cyclic-source.expected +18 -0
- data/test/command/suite/search/error/cyclic-source.test +12 -0
- data/test/command/suite/search/error/deeply-cyclic-source.expected +21 -0
- data/test/command/suite/search/error/deeply-cyclic-source.test +15 -0
- data/test/command/suite/search/error/missing-source-parameter.expected +17 -0
- data/test/command/suite/search/error/missing-source-parameter.test +11 -0
- data/test/command/suite/search/error/unknown-source.expected +18 -0
- data/test/command/suite/search/error/unknown-source.test +12 -0
- data/test/command/suite/search/{minimum.expected → group/count.expected} +2 -1
- data/test/command/suite/search/{minimum.test → group/count.test} +5 -3
- data/test/command/suite/search/group/limit.expected +19 -0
- data/test/command/suite/search/group/limit.test +20 -0
- data/test/command/suite/search/group/string.expected +36 -0
- data/test/command/suite/search/group/string.test +44 -0
- data/test/command/suite/search/{chained-queries.expected → multiple/chained.expected} +0 -0
- data/test/command/suite/search/{chained-queries.test → multiple/chained.test} +0 -0
- data/test/command/suite/search/{multiple-queries.expected → multiple/parallel.expected} +0 -0
- data/test/command/suite/search/{multiple-queries.test → multiple/parallel.test} +0 -0
- data/test/command/suite/search/{output-range.expected → range/only-output.expected} +0 -0
- data/test/command/suite/search/{output-range.test → range/only-output.test} +0 -0
- data/test/command/suite/search/{sort-range.expected → range/only-sort.expected} +0 -0
- data/test/command/suite/search/{sort-range.test → range/only-sort.test} +0 -0
- data/test/command/suite/search/{sort-and-output-range.expected → range/sort-and-output.expected} +0 -0
- data/test/command/suite/search/{sort-and-output-range.test → range/sort-and-output.test} +0 -0
- data/test/command/suite/search/range/too-large-output-offset.expected +16 -0
- data/test/command/suite/search/range/too-large-output-offset.test +25 -0
- data/test/command/suite/search/range/too-large-sort-offset.expected +16 -0
- data/test/command/suite/search/range/too-large-sort-offset.test +28 -0
- data/test/command/suite/search/response/records/value/time.expected +24 -0
- data/test/command/suite/search/response/records/value/time.test +24 -0
- data/test/command/suite/search/sort/default-offset-limit.expected +43 -0
- data/test/command/suite/search/sort/default-offset-limit.test +26 -0
- data/test/command/suite/search/{sort-with-invisible-column.expected → sort/invisible-column.expected} +0 -0
- data/test/command/suite/search/{sort-with-invisible-column.test → sort/invisible-column.test} +0 -0
- data/test/command/suite/watch/subscribe.expected +12 -0
- data/test/command/suite/watch/subscribe.test +9 -0
- data/test/command/suite/watch/unsubscribe.expected +12 -0
- data/test/command/suite/watch/unsubscribe.test +9 -0
- data/test/unit/{test_catalog.rb → catalog/test_version1.rb} +12 -4
- data/test/unit/fixtures/{catalog.json → catalog/version1.json} +0 -0
- data/test/unit/helper.rb +2 -0
- data/test/unit/plugin/collector/test_basic.rb +289 -33
- data/test/unit/plugin/distributor/test_search.rb +176 -861
- data/test/unit/plugin/distributor/test_search_planner.rb +1102 -0
- data/test/unit/plugin/handler/groonga/test_column_create.rb +17 -13
- data/test/unit/plugin/handler/groonga/test_table_create.rb +10 -10
- data/test/unit/plugin/handler/test_add.rb +74 -11
- data/test/unit/plugin/handler/test_groonga.rb +15 -1
- data/test/unit/plugin/handler/test_search.rb +33 -17
- data/test/unit/plugin/handler/test_watch.rb +43 -27
- data/test/unit/run-test.rb +2 -0
- data/test/unit/test_message_pack_packer.rb +51 -0
- data/test/unit/test_time_formatter.rb +29 -0
- metadata +208 -110
- data/lib/droonga/job_queue.rb +0 -87
- data/lib/droonga/job_queue_schema.rb +0 -65
- data/test/unit/test_adapter.rb +0 -51
- data/test/unit/test_job_queue_schema.rb +0 -45
@@ -22,9 +22,8 @@ module Droonga
|
|
22
22
|
extend PluginRegisterable
|
23
23
|
|
24
24
|
attr_reader :task, :input_name, :component, :output_values, :body, :output_names
|
25
|
-
def initialize
|
25
|
+
def initialize
|
26
26
|
super()
|
27
|
-
@dispatcher = dispatcher
|
28
27
|
end
|
29
28
|
|
30
29
|
def process(command, message)
|
@@ -39,44 +38,13 @@ module Droonga
|
|
39
38
|
@id = message["id"]
|
40
39
|
@value = message["value"]
|
41
40
|
@input_name = message["name"]
|
42
|
-
@descendants = message["descendants"]
|
43
41
|
super(command, @value)
|
44
|
-
output if @descendants
|
45
42
|
true
|
46
43
|
end
|
47
44
|
|
48
45
|
# TODO: consider better name
|
49
|
-
def emit(
|
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
|
46
|
+
def emit(name, value)
|
58
47
|
@output_values[name] = value
|
59
48
|
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
49
|
end
|
82
50
|
end
|
data/lib/droonga/dispatcher.rb
CHANGED
@@ -15,149 +15,185 @@
|
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
16
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
17
|
|
18
|
-
require
|
19
|
-
require "
|
18
|
+
require "English"
|
19
|
+
require "tsort"
|
20
|
+
|
21
|
+
require "droonga/input_adapter"
|
22
|
+
require "droonga/output_adapter"
|
20
23
|
require "droonga/distributor"
|
21
24
|
require "droonga/catalog"
|
22
25
|
require "droonga/collector"
|
23
26
|
require "droonga/farm"
|
24
|
-
require "droonga/
|
27
|
+
require "droonga/session"
|
28
|
+
require "droonga/replier"
|
29
|
+
require "droonga/message_processing_error"
|
25
30
|
|
26
31
|
module Droonga
|
27
32
|
class Dispatcher
|
28
|
-
attr_reader :name
|
33
|
+
attr_reader :name
|
34
|
+
|
35
|
+
class MissingDatasetParameter < BadRequest
|
36
|
+
def initialize
|
37
|
+
super("\"dataset\" must be specified.")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class UnknownCommand < BadRequest
|
42
|
+
def initialize(command, dataset)
|
43
|
+
super("The command #{command.inspect} is not available " +
|
44
|
+
"for the dataset #{dataset.inspect}.")
|
45
|
+
end
|
46
|
+
end
|
29
47
|
|
30
48
|
def initialize(options)
|
31
49
|
@options = options
|
32
50
|
@name = @options[:name]
|
33
|
-
@
|
34
|
-
@collectors = {}
|
51
|
+
@sessions = {}
|
35
52
|
@current_id = 0
|
36
53
|
@local = Regexp.new("^#{@name}")
|
37
|
-
@
|
38
|
-
|
39
|
-
@
|
54
|
+
@input_adapter =
|
55
|
+
InputAdapter.new(self, :plugins => Droonga.catalog.option("plugins"))
|
56
|
+
@output_adapter =
|
57
|
+
OutputAdapter.new(self, :plugins => Droonga.catalog.option("plugins"))
|
58
|
+
@loop = EventLoop.new
|
59
|
+
@farm = Farm.new(name, @loop, :dispatcher => self)
|
60
|
+
@forwarder = Forwarder.new(@loop)
|
61
|
+
@replier = Replier.new(@forwarder)
|
40
62
|
@distributor = Distributor.new(self, @options)
|
63
|
+
@collector = Collector.new
|
41
64
|
end
|
42
65
|
|
43
66
|
def start
|
67
|
+
@forwarder.start
|
44
68
|
@farm.start
|
69
|
+
@loop_thread = Thread.new do
|
70
|
+
@loop.run
|
71
|
+
end
|
45
72
|
end
|
46
73
|
|
47
74
|
def shutdown
|
48
75
|
@forwarder.shutdown
|
49
76
|
@distributor.shutdown
|
50
|
-
@
|
77
|
+
@collector.shutdown
|
78
|
+
@input_adapter.shutdown
|
79
|
+
@output_adapter.shutdown
|
51
80
|
@farm.shutdown
|
81
|
+
@loop.stop
|
82
|
+
@loop_thread.join
|
52
83
|
end
|
53
84
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def handle_envelope(envelope)
|
59
|
-
@envelope = envelope
|
60
|
-
if envelope["type"] == "dispatcher"
|
61
|
-
handle(envelope["body"], envelope["arguments"])
|
85
|
+
def process_message(message)
|
86
|
+
@message = message
|
87
|
+
if message["type"] == "dispatcher"
|
88
|
+
process_internal_message(message["body"])
|
62
89
|
else
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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))
|
90
|
+
begin
|
91
|
+
assert_valid_message
|
92
|
+
process_input_message(message)
|
93
|
+
rescue MessageProcessingError => error
|
94
|
+
reply("statusCode" => error.status_code,
|
95
|
+
"body" => error.response_body)
|
103
96
|
end
|
104
97
|
end
|
105
|
-
add_route(route) if route
|
106
|
-
$log.trace("#{log_tag}: post: done")
|
107
98
|
end
|
108
99
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
when Hash
|
114
|
-
handle_internal_message(message)
|
115
|
-
end
|
100
|
+
def forward(message, destination)
|
101
|
+
$log.trace("#{log_tag}: forward start")
|
102
|
+
@forwarder.forward(message, destination)
|
103
|
+
$log.trace("#{log_tag}: forward done")
|
116
104
|
end
|
117
105
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
106
|
+
# Replies response to replyTo.
|
107
|
+
#
|
108
|
+
# @param [Hash] message
|
109
|
+
# The message to be replied. See {Replier#reply} for available keys.
|
110
|
+
#
|
111
|
+
# The key-value pairs in request message are used as the default
|
112
|
+
# key-value pairs. For example, if the passed message doesn't
|
113
|
+
# include `id` key, `id` key's value is used in request message.
|
114
|
+
#
|
115
|
+
# @return [void]
|
116
|
+
#
|
117
|
+
# @see Replier#reply
|
118
|
+
def reply(message)
|
119
|
+
adapted_message = @output_adapter.adapt(@message.merge(message))
|
120
|
+
return if adapted_message["replyTo"].nil?
|
121
|
+
@replier.reply(adapted_message)
|
127
122
|
end
|
128
123
|
|
129
|
-
def
|
124
|
+
def process_internal_message(message)
|
130
125
|
id = message["id"]
|
131
|
-
|
132
|
-
|
126
|
+
session = @sessions[id]
|
127
|
+
if session
|
128
|
+
session.receive(message["input"], message["value"])
|
129
|
+
else
|
133
130
|
components = message["components"]
|
134
131
|
if components
|
135
132
|
planner = Planner.new(self, components)
|
136
|
-
|
133
|
+
session = planner.create_session(id, @collector)
|
134
|
+
@sessions[id] = session
|
137
135
|
else
|
138
136
|
#todo: take cases receiving result before its query into account
|
139
137
|
end
|
138
|
+
session.start
|
140
139
|
end
|
141
|
-
|
140
|
+
@sessions.delete(id) if session.done?
|
142
141
|
end
|
143
142
|
|
144
143
|
def dispatch(message, destination)
|
145
144
|
if local?(destination)
|
146
|
-
|
145
|
+
process_internal_message(message)
|
147
146
|
else
|
148
|
-
|
147
|
+
@forwarder.forward(@message.merge("body" => message),
|
148
|
+
"type" => "dispatcher",
|
149
|
+
"to" => destination)
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
153
|
+
def dispatch_components(components)
|
154
|
+
id = generate_id
|
155
|
+
destinations = {}
|
156
|
+
components.each do |component|
|
157
|
+
dataset = component["dataset"]
|
158
|
+
if dataset
|
159
|
+
routes = Droonga.catalog.get_routes(dataset, component)
|
160
|
+
component["routes"] = routes
|
161
|
+
else
|
162
|
+
component["routes"] ||= [id]
|
163
|
+
end
|
164
|
+
routes = component["routes"]
|
165
|
+
routes.each do |route|
|
166
|
+
destinations[farm_path(route)] = true
|
167
|
+
end
|
168
|
+
end
|
169
|
+
dispatch_message = { "id" => id, "components" => components }
|
170
|
+
destinations.each_key do |destination|
|
171
|
+
dispatch(dispatch_message, destination)
|
158
172
|
end
|
159
173
|
end
|
160
174
|
|
175
|
+
def process_local_message(local_message)
|
176
|
+
task = local_message["task"]
|
177
|
+
partition_name = task["route"]
|
178
|
+
component = task["component"]
|
179
|
+
command = component["command"]
|
180
|
+
descendants = {}
|
181
|
+
component["descendants"].each do |name, routes|
|
182
|
+
descendants[name] = routes.collect do |route|
|
183
|
+
farm_path(route)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
local_message["descendants"] = descendants
|
187
|
+
farm_message = @message.merge("body" => local_message,
|
188
|
+
"type" => command)
|
189
|
+
@farm.process(partition_name, farm_message)
|
190
|
+
end
|
191
|
+
|
192
|
+
def local?(route)
|
193
|
+
route =~ @local
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
161
197
|
def generate_id
|
162
198
|
id = @current_id
|
163
199
|
@current_id = id.succ
|
@@ -166,38 +202,21 @@ module Droonga
|
|
166
202
|
|
167
203
|
def farm_path(route)
|
168
204
|
if route =~ /\A.*:\d+\/[^\.]+/
|
169
|
-
|
205
|
+
$MATCH
|
170
206
|
else
|
171
207
|
route
|
172
208
|
end
|
173
209
|
end
|
174
210
|
|
175
|
-
def
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
def is_route?(route)
|
181
|
-
route.is_a?(String) || route.is_a?(Hash)
|
211
|
+
def process_input_message(message)
|
212
|
+
adapted_message = @input_adapter.adapt(message)
|
213
|
+
@distributor.process(adapted_message["type"], adapted_message)
|
214
|
+
rescue Droonga::Pluggable::UnknownPlugin => error
|
215
|
+
raise UnknownCommand.new(error.command, message["dataset"])
|
182
216
|
end
|
183
217
|
|
184
|
-
def
|
185
|
-
|
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)
|
218
|
+
def assert_valid_message
|
219
|
+
raise MissingDatasetParameter.new unless @message.include?("dataset")
|
201
220
|
end
|
202
221
|
|
203
222
|
def log_tag
|
@@ -206,65 +225,13 @@ module Droonga
|
|
206
225
|
|
207
226
|
class Planner
|
208
227
|
attr_reader :components
|
209
|
-
class UndefinedInputError < StandardError
|
210
|
-
attr_reader :input
|
211
|
-
def initialize(input)
|
212
|
-
@input = input
|
213
|
-
super("undefined input assigned: <#{input}>")
|
214
|
-
end
|
215
|
-
end
|
216
228
|
|
217
|
-
class CyclicComponentsError < StandardError
|
218
|
-
attr_reader :components
|
219
|
-
def initialize(components)
|
220
|
-
@components = components
|
221
|
-
super("cyclic components found: <#{components}>")
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
include TSort
|
226
229
|
def initialize(dispatcher, components)
|
227
230
|
@dispatcher = dispatcher
|
228
231
|
@components = components
|
229
232
|
end
|
230
233
|
|
231
|
-
def
|
232
|
-
@dependency = {}
|
233
|
-
@components.each do |component|
|
234
|
-
@dependency[component] = component["inputs"]
|
235
|
-
next unless component["outputs"]
|
236
|
-
component["outputs"].each do |output|
|
237
|
-
@dependency[output] = [component]
|
238
|
-
end
|
239
|
-
end
|
240
|
-
@components = []
|
241
|
-
each_strongly_connected_component do |cs|
|
242
|
-
raise CyclicComponentsError.new(cs) if cs.size > 1
|
243
|
-
@components.concat(cs) unless cs.first.is_a? String
|
244
|
-
end
|
245
|
-
resolve_routes(id)
|
246
|
-
end
|
247
|
-
|
248
|
-
def resolve_routes(id)
|
249
|
-
local = [id]
|
250
|
-
destinations = Hash.new(0)
|
251
|
-
@components.each do |component|
|
252
|
-
dataset = component["dataset"]
|
253
|
-
routes =
|
254
|
-
if dataset
|
255
|
-
Droonga.catalog.get_routes(dataset, component)
|
256
|
-
else
|
257
|
-
local
|
258
|
-
end
|
259
|
-
routes.each do |route|
|
260
|
-
destinations[@dispatcher.farm_path(route)] += 1
|
261
|
-
end
|
262
|
-
component["routes"] = routes
|
263
|
-
end
|
264
|
-
return destinations
|
265
|
-
end
|
266
|
-
|
267
|
-
def get_collector(id)
|
234
|
+
def create_session(id, collector)
|
268
235
|
resolve_descendants
|
269
236
|
tasks = []
|
270
237
|
inputs = {}
|
@@ -284,9 +251,7 @@ module Droonga
|
|
284
251
|
end
|
285
252
|
end
|
286
253
|
end
|
287
|
-
|
288
|
-
@dispatcher.collectors[id] = collector
|
289
|
-
return collector
|
254
|
+
Session.new(id, @dispatcher, collector, tasks, inputs)
|
290
255
|
end
|
291
256
|
|
292
257
|
def resolve_descendants
|
@@ -300,35 +265,15 @@ module Droonga
|
|
300
265
|
component["n_of_expects"] = 0
|
301
266
|
end
|
302
267
|
@components.each do |component|
|
303
|
-
descendants =
|
304
|
-
component["
|
305
|
-
|
306
|
-
|
268
|
+
descendants = {}
|
269
|
+
(component["outputs"] || []).each do |output|
|
270
|
+
descendants[output] = []
|
271
|
+
@descendants[output].each do |index|
|
307
272
|
@components[index]["n_of_expects"] += component["routes"].size
|
273
|
+
descendants[output].concat(@components[index]["routes"])
|
308
274
|
end
|
309
275
|
end
|
310
|
-
|
311
|
-
end
|
312
|
-
|
313
|
-
def get_descendants(component)
|
314
|
-
return {} unless component["outputs"]
|
315
|
-
descendants = {}
|
316
|
-
component["outputs"].each do |output|
|
317
|
-
descendants[output] = @descendants[output]
|
318
|
-
end
|
319
|
-
descendants
|
320
|
-
end
|
321
|
-
|
322
|
-
def tsort_each_node(&block)
|
323
|
-
@dependency.each_key(&block)
|
324
|
-
end
|
325
|
-
|
326
|
-
def tsort_each_child(node, &block)
|
327
|
-
if node.is_a? String and @dependency[node].nil?
|
328
|
-
raise UndefinedInputError.new(node)
|
329
|
-
end
|
330
|
-
if @dependency[node]
|
331
|
-
@dependency[node].each(&block)
|
276
|
+
component["descendants"] = descendants
|
332
277
|
end
|
333
278
|
end
|
334
279
|
end
|