fluent-plugin-droonga 0.9.9 → 1.0.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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.dir-locals.el +3 -0
  3. data/.travis.yml +6 -2
  4. data/README.md +6 -7
  5. data/Rakefile +23 -6
  6. data/fluent-plugin-droonga.gemspec +2 -2
  7. data/lib/droonga/adapter.rb +12 -3
  8. data/lib/droonga/adapter_runner.rb +28 -23
  9. data/lib/droonga/catalog/base.rb +7 -111
  10. data/lib/droonga/catalog/dataset.rb +13 -25
  11. data/lib/droonga/catalog/errors.rb +94 -0
  12. data/lib/droonga/catalog/schema.rb +277 -0
  13. data/lib/droonga/catalog/version1.rb +404 -0
  14. data/lib/droonga/catalog/version2.rb +160 -0
  15. data/lib/droonga/catalog_loader.rb +27 -4
  16. data/lib/droonga/catalog_observer.rb +44 -6
  17. data/lib/droonga/collector.rb +12 -10
  18. data/lib/droonga/{handler_plugin.rb → collector_message.rb} +47 -20
  19. data/lib/droonga/collector_runner.rb +64 -0
  20. data/lib/droonga/collectors.rb +18 -0
  21. data/lib/droonga/{catalog.rb → collectors/add.rb} +9 -7
  22. data/lib/droonga/{command_repository.rb → collectors/and.rb} +7 -14
  23. data/lib/droonga/collectors/sum.rb +26 -0
  24. data/lib/droonga/dispatcher.rb +74 -41
  25. data/lib/droonga/distributed_command_planner.rb +2 -2
  26. data/lib/droonga/engine.rb +13 -5
  27. data/lib/droonga/{message_processing_error.rb → error.rb} +33 -12
  28. data/lib/droonga/{plugin/planner/search.rb → error_messages.rb} +12 -10
  29. data/lib/droonga/farm.rb +15 -14
  30. data/lib/droonga/fluent_message_sender.rb +15 -11
  31. data/lib/droonga/forwarder.rb +22 -18
  32. data/lib/droonga/handler.rb +8 -2
  33. data/lib/droonga/handler_runner.rb +47 -26
  34. data/lib/droonga/input_message.rb +6 -6
  35. data/lib/droonga/{command.rb → loggable.rb} +7 -14
  36. data/lib/droonga/logger.rb +56 -15
  37. data/lib/droonga/message_matcher.rb +12 -7
  38. data/lib/droonga/message_pusher.rb +8 -4
  39. data/lib/droonga/message_receiver.rb +11 -9
  40. data/lib/droonga/output_message.rb +2 -0
  41. data/lib/droonga/planner.rb +21 -10
  42. data/lib/droonga/plugin.rb +15 -0
  43. data/lib/droonga/plugin/metadata/{adapter_message.rb → adapter_input_message.rb} +6 -14
  44. data/lib/droonga/plugin/metadata/adapter_output_message.rb +39 -0
  45. data/lib/droonga/plugin/metadata/collector_message.rb +39 -0
  46. data/lib/droonga/plugin/metadata/input_message.rb +15 -0
  47. data/lib/droonga/plugin_loader.rb +33 -25
  48. data/lib/droonga/plugin_registry.rb +9 -1
  49. data/lib/droonga/plugins/basic.rb +54 -0
  50. data/lib/droonga/plugins/crud.rb +36 -15
  51. data/lib/droonga/plugins/error.rb +5 -4
  52. data/lib/droonga/plugins/groonga.rb +9 -6
  53. data/lib/droonga/plugins/groonga/column_create.rb +10 -5
  54. data/lib/droonga/plugins/groonga/generic_command.rb +2 -8
  55. data/lib/droonga/plugins/groonga/generic_response.rb +2 -2
  56. data/lib/droonga/plugins/groonga/select.rb +2 -2
  57. data/lib/droonga/plugins/groonga/table_create.rb +9 -4
  58. data/lib/droonga/plugins/groonga/table_remove.rb +10 -5
  59. data/lib/droonga/plugins/search.rb +106 -5
  60. data/lib/droonga/plugins/search/distributed_search_planner.rb +398 -0
  61. data/lib/droonga/plugins/watch.rb +41 -20
  62. data/lib/droonga/processor.rb +12 -9
  63. data/lib/droonga/{plugin/collector/basic.rb → reducer.rb} +36 -50
  64. data/lib/droonga/replier.rb +7 -4
  65. data/lib/droonga/searcher.rb +40 -37
  66. data/lib/droonga/server.rb +8 -6
  67. data/lib/droonga/session.rb +17 -7
  68. data/lib/droonga/single_step.rb +53 -0
  69. data/lib/droonga/{plugin/planner/watch.rb → single_step_definition.rb} +27 -26
  70. data/lib/droonga/{partition.rb → slice.rb} +23 -12
  71. data/lib/droonga/status_code.rb +25 -0
  72. data/lib/droonga/step_runner.rb +63 -0
  73. data/lib/droonga/watch_schema.rb +7 -3
  74. data/lib/droonga/watcher.rb +4 -4
  75. data/lib/droonga/worker.rb +6 -6
  76. data/lib/fluent/plugin/out_droonga.rb +27 -2
  77. data/sample/cluster/catalog.json +33 -32
  78. data/test/command/config/default/catalog.json +72 -45
  79. data/test/command/config/version1/catalog.json +68 -0
  80. data/test/command/config/version1/fluentd.conf +11 -0
  81. data/test/command/suite/message/error/missing-dataset.expected +1 -1
  82. data/test/command/suite/message/error/unknown-dataset.expected +1 -1
  83. data/test/command/suite/message/error/unknown-type.expected +13 -0
  84. data/test/command/suite/message/error/{unknown-command.test → unknown-type.test} +1 -1
  85. data/test/command/suite/search/error/missing-source-parameter.expected +1 -1
  86. data/test/command/suite/search/error/unknown-source.expected +15 -3
  87. data/test/command/suite/watch/subscribe.expected +1 -3
  88. data/test/command/suite/watch/unsubscribe.expected +1 -3
  89. data/test/performance/watch/catalog.json +1 -0
  90. data/test/unit/catalog/test_dataset.rb +16 -358
  91. data/test/unit/catalog/test_schema.rb +285 -0
  92. data/test/unit/catalog/test_version1.rb +222 -28
  93. data/test/unit/catalog/test_version2.rb +155 -0
  94. data/test/unit/fixtures/catalog/version2.json +62 -0
  95. data/test/unit/helper/distributed_search_planner_helper.rb +2 -2
  96. data/test/unit/plugins/crud/test_add.rb +13 -13
  97. data/test/unit/plugins/groonga/test_column_create.rb +14 -11
  98. data/test/unit/plugins/groonga/test_table_create.rb +4 -9
  99. data/test/unit/plugins/groonga/test_table_remove.rb +4 -9
  100. data/test/unit/{plugin/planner/search_planner → plugins/search/planner}/test_basic.rb +0 -0
  101. data/test/unit/{plugin/planner/search_planner → plugins/search/planner}/test_group_by.rb +0 -0
  102. data/test/unit/{plugin/planner/search_planner → plugins/search/planner}/test_output.rb +0 -0
  103. data/test/unit/{plugin/planner/search_planner → plugins/search/planner}/test_sort_by.rb +0 -0
  104. data/test/unit/{plugin/collector/test_search.rb → plugins/search/test_collector.rb} +40 -39
  105. data/test/unit/plugins/{test_search.rb → search/test_handler.rb} +6 -5
  106. data/test/unit/{plugin/planner/test_search.rb → plugins/search/test_planner.rb} +3 -3
  107. data/test/unit/{plugin/collector → plugins}/test_basic.rb +68 -50
  108. data/test/unit/plugins/test_groonga.rb +2 -15
  109. data/test/unit/plugins/test_watch.rb +25 -22
  110. data/test/unit/test_message_matcher.rb +29 -6
  111. data/test/unit/test_output.rb +4 -0
  112. metadata +58 -50
  113. data/lib/droonga/collector_plugin.rb +0 -50
  114. data/lib/droonga/legacy_pluggable.rb +0 -66
  115. data/lib/droonga/legacy_plugin.rb +0 -57
  116. data/lib/droonga/legacy_plugin_repository.rb +0 -54
  117. data/lib/droonga/planner_plugin.rb +0 -54
  118. data/lib/droonga/plugin/collector/search.rb +0 -98
  119. data/lib/droonga/plugin/planner/crud.rb +0 -49
  120. data/lib/droonga/plugin/planner/distributed_search_planner.rb +0 -393
  121. data/lib/droonga/plugin/planner/groonga.rb +0 -54
  122. data/lib/droonga/plugin_registerable.rb +0 -75
  123. data/test/command/suite/message/error/unknown-command.expected +0 -13
  124. data/test/unit/test_command_repository.rb +0 -39
  125. data/test/unit/test_legacy_plugin.rb +0 -50
  126. data/test/unit/test_legacy_plugin_repository.rb +0 -89
@@ -0,0 +1,18 @@
1
+ # Copyright (C) 2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/collectors/add"
17
+ require "droonga/collectors/and"
18
+ require "droonga/collectors/sum"
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2013 Droonga Project
1
+ # Copyright (C) 2014 Droonga Project
4
2
  #
5
3
  # This library is free software; you can redistribute it and/or
6
4
  # modify it under the terms of the GNU Lesser General Public
@@ -15,10 +13,14 @@
15
13
  # License along with this library; if not, write to the Free Software
16
14
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
15
 
18
- require "droonga/catalog_loader"
19
-
20
16
  module Droonga
21
- class << self
22
- attr_accessor :catalog
17
+ module Collectors
18
+ class Add
19
+ class << self
20
+ def operator
21
+ "or"
22
+ end
23
+ end
24
+ end
23
25
  end
24
26
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013-2014 Droonga Project
1
+ # Copyright (C) 2014 Droonga Project
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -14,19 +14,12 @@
14
14
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
15
 
16
16
  module Droonga
17
- class CommandRepository
18
- attr_reader :commands
19
- def initialize
20
- @commands = []
21
- end
22
-
23
- def register(command)
24
- @commands << command
25
- end
26
-
27
- def find(message)
28
- @commands.find do |command|
29
- command.match?(message)
17
+ module Collectors
18
+ class And
19
+ class << self
20
+ def operator
21
+ "and"
22
+ end
30
23
  end
31
24
  end
32
25
  end
@@ -0,0 +1,26 @@
1
+ # Copyright (C) 2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ module Droonga
17
+ module Collectors
18
+ class Sum
19
+ class << self
20
+ def operator
21
+ "sum"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -16,56 +16,54 @@
16
16
  require "English"
17
17
  require "tsort"
18
18
 
19
+ require "droonga/loggable"
19
20
  require "droonga/adapter_runner"
20
- require "droonga/planner"
21
- require "droonga/catalog"
22
- require "droonga/collector"
21
+ require "droonga/collector_runner"
22
+ require "droonga/step_runner"
23
23
  require "droonga/farm"
24
24
  require "droonga/session"
25
25
  require "droonga/replier"
26
- require "droonga/message_processing_error"
27
- require "droonga/catalog_observer"
26
+ require "droonga/error_messages"
28
27
  require "droonga/distributor"
29
28
 
30
29
  module Droonga
31
30
  class Dispatcher
31
+ include Loggable
32
+
32
33
  attr_reader :name
33
34
 
34
- class MissingDatasetParameter < BadRequest
35
+ class MissingDatasetParameter < ErrorMessages::BadRequest
35
36
  def initialize
36
- super("\"dataset\" must be specified.")
37
+ super("Missing required parameter: <dataset>")
37
38
  end
38
39
  end
39
40
 
40
- class UnknownDataset < NotFound
41
+ class UnknownDataset < ErrorMessages::NotFound
41
42
  def initialize(dataset)
42
- super("The dataset #{dataset.inspect} does not exist.")
43
+ super("Unknown dataset: <#{dataset}>")
43
44
  end
44
45
  end
45
46
 
46
- class UnknownCommand < BadRequest
47
- def initialize(command, dataset)
48
- super("The command #{command.inspect} is not available " +
49
- "for the dataset #{dataset.inspect}.")
47
+ class UnknownType < ErrorMessages::BadRequest
48
+ def initialize(type, dataset)
49
+ super("[#{dataset}] Handler not found for the type: <#{type}>")
50
50
  end
51
51
  end
52
52
 
53
- def initialize(options)
53
+ def initialize(catalog, options)
54
+ @catalog = catalog
54
55
  @options = options
55
56
  @name = @options[:name]
56
57
  @loop = EventLoop.new
57
- @catalog_observer = CatalogObserver.new(@loop)
58
58
  @sessions = {}
59
59
  @current_id = 0
60
60
  @local = Regexp.new("^#{@name}")
61
61
  @adapter_runners = create_adapter_runners
62
- @farm = Farm.new(name, @loop, :dispatcher => self)
62
+ @farm = Farm.new(name, @catalog, @loop, :dispatcher => self)
63
63
  @forwarder = Forwarder.new(@loop)
64
64
  @replier = Replier.new(@forwarder)
65
- # TODO: make customizable
66
- @planner = Planner.new(self, ["search", "crud", "groonga", "watch"])
67
- # TODO: make customizable
68
- @collector = Collector.new(["basic", "search"])
65
+ @collector_runners = create_collector_runners
66
+ @step_runners = create_step_runners
69
67
  end
70
68
 
71
69
  def start
@@ -74,12 +72,15 @@ module Droonga
74
72
  @loop_thread = Thread.new do
75
73
  @loop.run
76
74
  end
75
+
76
+ ensure_schema
77
77
  end
78
78
 
79
79
  def shutdown
80
80
  @forwarder.shutdown
81
- @planner.shutdown
82
- @collector.shutdown
81
+ @collector_runners.each_value do |collector_runner|
82
+ collector_runner.shutdown
83
+ end
83
84
  @adapter_runners.each_value do |adapter_runner|
84
85
  adapter_runner.shutdown
85
86
  end
@@ -96,12 +97,12 @@ module Droonga
96
97
  begin
97
98
  assert_valid_message(message)
98
99
  process_input_message(message)
99
- rescue MessageProcessingError => error
100
+ rescue ErrorMessage => error
100
101
  reply("statusCode" => error.status_code,
101
102
  "body" => error.response_body)
102
- rescue => error
103
- Logger.error("failed to process input message", error)
104
- formatted_error = MessageProcessingError.new("Unknown internal error")
103
+ rescue StandardError, LoadError, SyntaxError => error
104
+ logger.exception("failed to process input message", error)
105
+ formatted_error = ErrorMessages::InternalServerError.new("Unknown internal error")
105
106
  reply("statusCode" => formatted_error.status_code,
106
107
  "body" => formatted_error.response_body)
107
108
  raise error
@@ -110,9 +111,9 @@ module Droonga
110
111
  end
111
112
 
112
113
  def forward(message, destination)
113
- $log.trace("#{log_tag}: forward start")
114
+ logger.trace("forward start")
114
115
  @forwarder.forward(message, destination)
115
- $log.trace("#{log_tag}: forward done")
116
+ logger.trace("forward done")
116
117
  end
117
118
 
118
119
  # Replies response to replyTo.
@@ -146,7 +147,9 @@ module Droonga
146
147
  steps = message["steps"]
147
148
  if steps
148
149
  session_planner = SessionPlanner.new(self, steps)
149
- session = session_planner.create_session(id, @collector)
150
+ dataset = message["dataset"] || @message["dataset"]
151
+ collector_runner = @collector_runners[dataset]
152
+ session = session_planner.create_session(id, collector_runner)
150
153
  @sessions[id] = session
151
154
  else
152
155
  #todo: take cases receiving result before its query into account
@@ -172,7 +175,7 @@ module Droonga
172
175
  steps.each do |step|
173
176
  dataset = step["dataset"]
174
177
  if dataset
175
- routes = Droonga.catalog.get_routes(dataset, step)
178
+ routes = @catalog.get_routes(dataset, step)
176
179
  step["routes"] = routes
177
180
  else
178
181
  step["routes"] ||= [id]
@@ -190,7 +193,7 @@ module Droonga
190
193
 
191
194
  def process_local_message(local_message)
192
195
  task = local_message["task"]
193
- partition_name = task["route"]
196
+ slice_name = task["route"]
194
197
  step = task["step"]
195
198
  command = step["command"]
196
199
  descendants = {}
@@ -202,7 +205,7 @@ module Droonga
202
205
  local_message["descendants"] = descendants
203
206
  farm_message = @message.merge("body" => local_message,
204
207
  "type" => command)
205
- @farm.process(partition_name, farm_message)
208
+ @farm.process(slice_name, farm_message)
206
209
  end
207
210
 
208
211
  def local?(route)
@@ -228,11 +231,13 @@ module Droonga
228
231
  dataset = message["dataset"]
229
232
  adapter_runner = @adapter_runners[dataset]
230
233
  adapted_message = adapter_runner.adapt_input(message)
231
- plan = @planner.process(adapted_message["type"], adapted_message)
234
+ step_runner = @step_runners[dataset]
235
+ plan = step_runner.plan(message)
232
236
  distributor = Distributor.new(self)
233
237
  distributor.distribute(plan)
234
- rescue Droonga::LegacyPluggable::UnknownPlugin => error
235
- raise UnknownCommand.new(error.command, message["dataset"])
238
+ rescue Droonga::UnsupportedMessageError => error
239
+ target_message = error.message
240
+ raise UnknownType.new(target_message["type"], target_message["dataset"])
236
241
  end
237
242
 
238
243
  def assert_valid_message(message)
@@ -240,19 +245,47 @@ module Droonga
240
245
  raise MissingDatasetParameter.new
241
246
  end
242
247
  dataset = message["dataset"]
243
- unless Droonga.catalog.have_dataset?(dataset)
248
+ unless @catalog.have_dataset?(dataset)
244
249
  raise UnknownDataset.new(dataset)
245
250
  end
246
251
  end
247
252
 
248
- def create_adapter_runners
253
+ def create_runners
249
254
  runners = {}
250
- Droonga.catalog.datasets.each do |name, configuration|
251
- runners[name] = AdapterRunner.new(self, configuration["plugins"] || [])
255
+ @catalog.datasets.each do |name, configuration|
256
+ runners[name] = yield(configuration)
252
257
  end
253
258
  runners
254
259
  end
255
260
 
261
+ def create_adapter_runners
262
+ create_runners do |configuration|
263
+ AdapterRunner.new(self, configuration["plugins"] || [])
264
+ end
265
+ end
266
+
267
+ def create_collector_runners
268
+ create_runners do |configuration|
269
+ CollectorRunner.new(configuration["plugins"] || [])
270
+ end
271
+ end
272
+
273
+ def create_step_runners
274
+ create_runners do |configuration|
275
+ StepRunner.new(configuration["plugins"] || [])
276
+ end
277
+ end
278
+
279
+ def ensure_schema
280
+ @catalog.datasets.each do |name, dataset|
281
+ schema = dataset.schema
282
+ messages = schema.to_messages
283
+ messages.each do |message|
284
+ process_message(message)
285
+ end
286
+ end
287
+ end
288
+
256
289
  def log_tag
257
290
  "[#{Process.ppid}][#{Process.pid}] dispatcher"
258
291
  end
@@ -265,7 +298,7 @@ module Droonga
265
298
  @steps = steps
266
299
  end
267
300
 
268
- def create_session(id, collector)
301
+ def create_session(id, collector_runner)
269
302
  resolve_descendants
270
303
  tasks = []
271
304
  inputs = {}
@@ -285,7 +318,7 @@ module Droonga
285
318
  end
286
319
  end
287
320
  end
288
- Session.new(id, @dispatcher, collector, tasks, inputs)
321
+ Session.new(id, @dispatcher, collector_runner, tasks, inputs)
289
322
  end
290
323
 
291
324
  def resolve_descendants
@@ -45,7 +45,7 @@ module Droonga
45
45
  return unless params
46
46
  params.each do |name, reducer|
47
47
  gatherer = nil
48
- if reducer.is_a?(Hash) && reducer[:gather]
48
+ if reducer.is_a?(Hash) and reducer[:gather]
49
49
  gatherer = reducer[:gather]
50
50
  reducer = reducer[:reduce]
51
51
  end
@@ -127,7 +127,7 @@ module Droonga
127
127
  def fixed_processor
128
128
  @processor["outputs"] = @outputs
129
129
  if @processor["type"] == "scatter"
130
- raise MessageProcessingError.new("missing key") unless @key
130
+ raise ErrorMessages::InternalServerError.new("missing key") unless @key
131
131
  @processor["key"] = @key
132
132
  end
133
133
  @processor
@@ -15,14 +15,17 @@
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 "droonga/logger"
18
+ require "droonga/loggable"
19
19
  require "droonga/dispatcher"
20
20
 
21
21
  module Droonga
22
22
  class Engine
23
- def initialize(options={})
23
+ include Loggable
24
+
25
+ def initialize(catalog, options={})
26
+ @catalog = catalog
24
27
  @options = options
25
- @dispatcher = Dispatcher.new(@options)
28
+ @dispatcher = Dispatcher.new(@catalog, @options)
26
29
  end
27
30
 
28
31
  def start
@@ -30,13 +33,18 @@ module Droonga
30
33
  end
31
34
 
32
35
  def shutdown
33
- $log.trace("engine: shutdown: start")
36
+ logger.trace("shutdown: start")
34
37
  @dispatcher.shutdown
35
- $log.trace("engine: shutdown: done")
38
+ logger.trace("shutdown: done")
36
39
  end
37
40
 
38
41
  def process(message)
39
42
  @dispatcher.process_message(message)
40
43
  end
44
+
45
+ private
46
+ def log_tag
47
+ "engine"
48
+ end
41
49
  end
42
50
  end
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2013 Droonga Project
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2014 Droonga Project
2
4
  #
3
5
  # This library is free software; you can redistribute it and/or
4
6
  # modify it under the terms of the GNU Lesser General Public
@@ -14,14 +16,31 @@
14
16
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
17
 
16
18
  module Droonga
17
- class MessageProcessingError < StandardError
18
- STATUS_CODE = 500
19
+ class Error < StandardError
20
+ end
21
+
22
+ class MultiplexError < Error
23
+ attr_reader :errors
24
+
25
+ def initialize(errors=[])
26
+ @errors = errors
27
+ error_messages = @errors.collect do |error|
28
+ error.message
29
+ end
30
+ message = error_messages.sort.join("\n-----------------------\n")
31
+ super(message)
32
+ end
33
+ end
19
34
 
20
- attr_reader :message, :detail
35
+ # the base class for any error which can be described as a Droonga message
36
+ class ErrorMessage < Error
37
+ STATUS_CODE = nil
38
+
39
+ attr_reader :detail
21
40
 
22
41
  def initialize(message, detail=nil)
23
- @message = message
24
42
  @detail = detail
43
+ super(message)
25
44
  end
26
45
 
27
46
  def name
@@ -35,18 +54,20 @@ module Droonga
35
54
  def response_body
36
55
  body = {
37
56
  "name" => name,
38
- "message" => @message,
57
+ "message" => message,
39
58
  }
40
59
  body["detail"] = @detail unless @detail.nil?
41
60
  body
42
61
  end
43
62
  end
44
63
 
45
- class BadRequest < MessageProcessingError
46
- STATUS_CODE = 400
47
- end
48
-
49
- class NotFound < MessageProcessingError
50
- STATUS_CODE = 404
64
+ # TODO: Move to common file for runners
65
+ class UnsupportedMessageError < Error
66
+ attr_reader :phase, :message
67
+ def initialize(phase, message)
68
+ @phase = phase
69
+ @message = message
70
+ super("[#{@phase}] Unsupported message: #{@message.inspect}")
71
+ end
51
72
  end
52
73
  end