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.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -4
  3. data/benchmark/watch/benchmark-notify.rb +2 -2
  4. data/benchmark/watch/benchmark-scan.rb +3 -0
  5. data/benchmark/watch/fluentd.conf +0 -1
  6. data/fluent-plugin-droonga.gemspec +2 -3
  7. data/lib/droonga/catalog.rb +10 -124
  8. data/lib/droonga/catalog/base.rb +140 -0
  9. data/lib/droonga/catalog/version1.rb +23 -0
  10. data/lib/droonga/catalog_loader.rb +33 -0
  11. data/lib/droonga/collector.rb +2 -71
  12. data/lib/droonga/collector_plugin.rb +2 -34
  13. data/lib/droonga/dispatcher.rb +141 -196
  14. data/lib/droonga/distribution_planner.rb +76 -0
  15. data/lib/droonga/distributor.rb +5 -7
  16. data/lib/droonga/distributor_plugin.rb +23 -15
  17. data/lib/droonga/engine.rb +2 -2
  18. data/lib/droonga/event_loop.rb +46 -0
  19. data/lib/droonga/farm.rb +9 -5
  20. data/lib/droonga/fluent_message_sender.rb +84 -0
  21. data/lib/droonga/forwarder.rb +43 -53
  22. data/lib/droonga/handler.rb +20 -68
  23. data/lib/droonga/handler_message.rb +61 -0
  24. data/lib/droonga/handler_messenger.rb +92 -0
  25. data/lib/droonga/handler_plugin.rb +10 -12
  26. data/lib/droonga/input_adapter.rb +52 -0
  27. data/lib/droonga/{adapter.rb → input_adapter_plugin.rb} +7 -13
  28. data/lib/droonga/input_message.rb +11 -11
  29. data/lib/droonga/logger.rb +4 -3
  30. data/lib/droonga/message_pack_packer.rb +62 -0
  31. data/lib/droonga/message_processing_error.rb +54 -0
  32. data/lib/droonga/message_pusher.rb +60 -0
  33. data/lib/droonga/message_receiver.rb +61 -0
  34. data/lib/droonga/output_adapter.rb +53 -0
  35. data/lib/droonga/{adapter_plugin.rb → output_adapter_plugin.rb} +3 -21
  36. data/lib/droonga/output_message.rb +37 -0
  37. data/lib/droonga/partition.rb +27 -5
  38. data/lib/droonga/pluggable.rb +9 -4
  39. data/lib/droonga/plugin.rb +12 -3
  40. data/lib/droonga/plugin/collector/basic.rb +91 -18
  41. data/lib/droonga/plugin/distributor/crud.rb +9 -9
  42. data/lib/droonga/plugin/distributor/distributed_search_planner.rb +401 -0
  43. data/lib/droonga/plugin/distributor/groonga.rb +5 -5
  44. data/lib/droonga/plugin/distributor/search.rb +4 -246
  45. data/lib/droonga/plugin/distributor/watch.rb +11 -6
  46. data/lib/droonga/plugin/handler/add.rb +69 -7
  47. data/lib/droonga/plugin/handler/groonga.rb +6 -6
  48. data/lib/droonga/plugin/handler/search.rb +5 -3
  49. data/lib/droonga/plugin/handler/watch.rb +19 -13
  50. data/lib/droonga/plugin/{adapter → input_adapter}/groonga.rb +5 -11
  51. data/lib/droonga/plugin/{adapter → input_adapter}/groonga/select.rb +2 -36
  52. data/lib/droonga/plugin/output_adapter/groonga.rb +30 -0
  53. data/lib/droonga/plugin/output_adapter/groonga/select.rb +54 -0
  54. data/lib/droonga/plugin_loader.rb +2 -2
  55. data/lib/droonga/processor.rb +21 -23
  56. data/lib/droonga/replier.rb +40 -0
  57. data/lib/droonga/searcher.rb +298 -174
  58. data/lib/droonga/server.rb +0 -67
  59. data/lib/droonga/session.rb +85 -0
  60. data/lib/droonga/test.rb +21 -0
  61. data/lib/droonga/test/stub_distributor.rb +31 -0
  62. data/lib/droonga/test/stub_handler.rb +37 -0
  63. data/lib/droonga/test/stub_handler_message.rb +35 -0
  64. data/lib/droonga/test/stub_handler_messenger.rb +34 -0
  65. data/lib/droonga/time_formatter.rb +37 -0
  66. data/lib/droonga/watcher.rb +1 -0
  67. data/lib/droonga/worker.rb +16 -19
  68. data/lib/fluent/plugin/out_droonga.rb +9 -9
  69. data/lib/groonga_command_converter.rb +5 -5
  70. data/sample/cluster/catalog.json +1 -1
  71. data/test/command/config/default/catalog.json +19 -1
  72. data/test/command/fixture/event.jsons +41 -0
  73. data/test/command/fixture/user-table.jsons +9 -0
  74. data/test/command/run-test.rb +2 -2
  75. data/test/command/suite/add/error/invalid-integer.expected +20 -0
  76. data/test/command/suite/add/error/invalid-integer.test +12 -0
  77. data/test/command/suite/add/error/invalid-time.expected +20 -0
  78. data/test/command/suite/add/error/invalid-time.test +12 -0
  79. data/test/command/suite/add/error/missing-key.expected +13 -0
  80. data/test/command/suite/add/error/missing-key.test +16 -0
  81. data/test/command/suite/add/error/missing-table.expected +13 -0
  82. data/test/command/suite/add/error/missing-table.test +16 -0
  83. data/test/command/suite/add/error/unknown-column.expected +20 -0
  84. data/test/command/suite/add/error/unknown-column.test +12 -0
  85. data/test/command/suite/add/error/unknown-table.expected +13 -0
  86. data/test/command/suite/add/error/unknown-table.test +17 -0
  87. data/test/command/suite/add/minimum.expected +1 -3
  88. data/test/command/suite/add/with-values.expected +1 -3
  89. data/test/command/suite/add/without-key.expected +1 -3
  90. data/test/command/suite/message/error/missing-dataset.expected +13 -0
  91. data/test/command/suite/message/error/missing-dataset.test +5 -0
  92. data/test/command/suite/message/error/unknown-command.expected +13 -0
  93. data/test/command/suite/message/error/unknown-command.test +6 -0
  94. data/test/command/suite/message/error/unknown-dataset.expected +13 -0
  95. data/test/command/suite/message/error/unknown-dataset.test +6 -0
  96. data/test/command/suite/search/{array-attribute-label.expected → attributes/array.expected} +0 -0
  97. data/test/command/suite/search/{array-attribute-label.test → attributes/array.test} +0 -0
  98. data/test/command/suite/search/{hash-attribute-label.expected → attributes/hash.expected} +0 -0
  99. data/test/command/suite/search/{hash-attribute-label.test → attributes/hash.test} +0 -0
  100. data/test/command/suite/search/{condition-nested.expected → condition/nested.expected} +0 -0
  101. data/test/command/suite/search/{condition-nested.test → condition/nested.test} +0 -0
  102. data/test/command/suite/search/{condition-query.expected → condition/query.expected} +0 -0
  103. data/test/command/suite/search/{condition-query.test → condition/query.test} +0 -0
  104. data/test/command/suite/search/{condition-script.expected → condition/script.expected} +0 -0
  105. data/test/command/suite/search/{condition-script.test → condition/script.test} +0 -0
  106. data/test/command/suite/search/error/cyclic-source.expected +18 -0
  107. data/test/command/suite/search/error/cyclic-source.test +12 -0
  108. data/test/command/suite/search/error/deeply-cyclic-source.expected +21 -0
  109. data/test/command/suite/search/error/deeply-cyclic-source.test +15 -0
  110. data/test/command/suite/search/error/missing-source-parameter.expected +17 -0
  111. data/test/command/suite/search/error/missing-source-parameter.test +11 -0
  112. data/test/command/suite/search/error/unknown-source.expected +18 -0
  113. data/test/command/suite/search/error/unknown-source.test +12 -0
  114. data/test/command/suite/search/{minimum.expected → group/count.expected} +2 -1
  115. data/test/command/suite/search/{minimum.test → group/count.test} +5 -3
  116. data/test/command/suite/search/group/limit.expected +19 -0
  117. data/test/command/suite/search/group/limit.test +20 -0
  118. data/test/command/suite/search/group/string.expected +36 -0
  119. data/test/command/suite/search/group/string.test +44 -0
  120. data/test/command/suite/search/{chained-queries.expected → multiple/chained.expected} +0 -0
  121. data/test/command/suite/search/{chained-queries.test → multiple/chained.test} +0 -0
  122. data/test/command/suite/search/{multiple-queries.expected → multiple/parallel.expected} +0 -0
  123. data/test/command/suite/search/{multiple-queries.test → multiple/parallel.test} +0 -0
  124. data/test/command/suite/search/{output-range.expected → range/only-output.expected} +0 -0
  125. data/test/command/suite/search/{output-range.test → range/only-output.test} +0 -0
  126. data/test/command/suite/search/{sort-range.expected → range/only-sort.expected} +0 -0
  127. data/test/command/suite/search/{sort-range.test → range/only-sort.test} +0 -0
  128. data/test/command/suite/search/{sort-and-output-range.expected → range/sort-and-output.expected} +0 -0
  129. data/test/command/suite/search/{sort-and-output-range.test → range/sort-and-output.test} +0 -0
  130. data/test/command/suite/search/range/too-large-output-offset.expected +16 -0
  131. data/test/command/suite/search/range/too-large-output-offset.test +25 -0
  132. data/test/command/suite/search/range/too-large-sort-offset.expected +16 -0
  133. data/test/command/suite/search/range/too-large-sort-offset.test +28 -0
  134. data/test/command/suite/search/response/records/value/time.expected +24 -0
  135. data/test/command/suite/search/response/records/value/time.test +24 -0
  136. data/test/command/suite/search/sort/default-offset-limit.expected +43 -0
  137. data/test/command/suite/search/sort/default-offset-limit.test +26 -0
  138. data/test/command/suite/search/{sort-with-invisible-column.expected → sort/invisible-column.expected} +0 -0
  139. data/test/command/suite/search/{sort-with-invisible-column.test → sort/invisible-column.test} +0 -0
  140. data/test/command/suite/watch/subscribe.expected +12 -0
  141. data/test/command/suite/watch/subscribe.test +9 -0
  142. data/test/command/suite/watch/unsubscribe.expected +12 -0
  143. data/test/command/suite/watch/unsubscribe.test +9 -0
  144. data/test/unit/{test_catalog.rb → catalog/test_version1.rb} +12 -4
  145. data/test/unit/fixtures/{catalog.json → catalog/version1.json} +0 -0
  146. data/test/unit/helper.rb +2 -0
  147. data/test/unit/plugin/collector/test_basic.rb +289 -33
  148. data/test/unit/plugin/distributor/test_search.rb +176 -861
  149. data/test/unit/plugin/distributor/test_search_planner.rb +1102 -0
  150. data/test/unit/plugin/handler/groonga/test_column_create.rb +17 -13
  151. data/test/unit/plugin/handler/groonga/test_table_create.rb +10 -10
  152. data/test/unit/plugin/handler/test_add.rb +74 -11
  153. data/test/unit/plugin/handler/test_groonga.rb +15 -1
  154. data/test/unit/plugin/handler/test_search.rb +33 -17
  155. data/test/unit/plugin/handler/test_watch.rb +43 -27
  156. data/test/unit/run-test.rb +2 -0
  157. data/test/unit/test_message_pack_packer.rb +51 -0
  158. data/test/unit/test_time_formatter.rb +29 -0
  159. metadata +208 -110
  160. data/lib/droonga/job_queue.rb +0 -87
  161. data/lib/droonga/job_queue_schema.rb +0 -65
  162. data/test/unit/test_adapter.rb +0 -51
  163. data/test/unit/test_job_queue_schema.rb +0 -45
@@ -0,0 +1,76 @@
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 "tsort"
19
+
20
+ module Droonga
21
+ class DistributionPlanner
22
+ class UndefinedInputError < StandardError
23
+ attr_reader :input
24
+ def initialize(input)
25
+ @input = input
26
+ super("undefined input assigned: <#{input}>")
27
+ end
28
+ end
29
+
30
+ class CyclicComponentsError < StandardError
31
+ attr_reader :components
32
+ def initialize(components)
33
+ @components = components
34
+ super("cyclic components found: <#{components}>")
35
+ end
36
+ end
37
+
38
+ include TSort
39
+
40
+ def initialize(dispatcher, components)
41
+ @dispatcher = dispatcher
42
+ @components = components
43
+ end
44
+
45
+ def plan
46
+ @dependency = {}
47
+ @components.each do |component|
48
+ @dependency[component] = component["inputs"]
49
+ next unless component["outputs"]
50
+ component["outputs"].each do |output|
51
+ @dependency[output] = [component]
52
+ end
53
+ end
54
+ components = []
55
+ each_strongly_connected_component do |cs|
56
+ raise CyclicComponentsError.new(cs) if cs.size > 1
57
+ components.concat(cs) unless cs.first.is_a? String
58
+ end
59
+ components
60
+ end
61
+
62
+ private
63
+ def tsort_each_node(&block)
64
+ @dependency.each_key(&block)
65
+ end
66
+
67
+ def tsort_each_child(node, &block)
68
+ if node.is_a? String and @dependency[node].nil?
69
+ raise UndefinedInputError.new(node)
70
+ end
71
+ if @dependency[node]
72
+ @dependency[node].each(&block)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -17,6 +17,7 @@
17
17
 
18
18
  require "droonga/pluggable"
19
19
  require "droonga/distributor_plugin"
20
+ require "droonga/distribution_planner"
20
21
 
21
22
  module Droonga
22
23
  class Distributor
@@ -30,13 +31,10 @@ module Droonga
30
31
  load_plugins(options[:distributors] || ["search", "crud", "groonga", "watch"])
31
32
  end
32
33
 
33
- def distribute(envelope)
34
- command = envelope["type"]
35
- process(command, envelope)
36
- end
37
-
38
- def post(message)
39
- @dispatcher.handle(message, [])
34
+ def distribute(components)
35
+ planner = DistributionPlanner.new(@dispatcher, components)
36
+ planned_components = planner.plan
37
+ @dispatcher.dispatch_components(planned_components)
40
38
  end
41
39
 
42
40
  private
@@ -26,34 +26,42 @@ module Droonga
26
26
  @distributor = distributor
27
27
  end
28
28
 
29
- # TODO: consider better name
30
- def post(message)
31
- @distributor.post(message)
29
+ def distribute(message)
30
+ @distributor.distribute(message)
32
31
  end
33
32
 
34
- def scatter_all(envelope, key)
35
- message = [{
36
- "command"=> envelope["type"],
37
- "dataset"=> envelope["dataset"],
38
- "body"=> envelope["body"],
33
+ def scatter_all(message, key)
34
+ distribute_message = [{
35
+ "command"=> message["type"],
36
+ "dataset"=> message["dataset"],
37
+ "body"=> message["body"],
39
38
  "key"=> key,
40
39
  "type"=> "scatter",
41
40
  "replica"=> "all",
42
41
  "post"=> true
43
42
  }]
44
- post(message)
43
+ distribute(distribute_message)
45
44
  end
46
45
 
47
- def broadcast_all(envelope)
48
- distirubte_message = [{
49
- "command"=> envelope["type"],
50
- "dataset"=> envelope["dataset"],
51
- "body"=> envelope["body"],
46
+ def broadcast_all(message)
47
+ distribute_message = [{
48
+ "command"=> message["type"],
49
+ "dataset"=> message["dataset"],
50
+ "body"=> message["body"],
52
51
  "type"=> "broadcast",
53
52
  "replica"=> "all",
54
53
  "post"=> true
55
54
  }]
56
- post(distirubte_message)
55
+ distribute(distribute_message)
56
+ end
57
+
58
+ private
59
+ def process_error(command, error, arguments)
60
+ if error.is_a?(MessageProcessingError)
61
+ raise error
62
+ else
63
+ super
64
+ end
57
65
  end
58
66
  end
59
67
  end
@@ -35,8 +35,8 @@ module Droonga
35
35
  $log.trace("engine: shutdown: done")
36
36
  end
37
37
 
38
- def process(envelope)
39
- @dispatcher.handle_envelope(envelope)
38
+ def process(message)
39
+ @dispatcher.process_message(message)
40
40
  end
41
41
  end
42
42
  end
@@ -0,0 +1,46 @@
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 "coolio"
19
+
20
+ module Droonga
21
+ class EventLoop
22
+ def initialize
23
+ @loop = Coolio::Loop.new
24
+ @loop_breaker = Coolio::AsyncWatcher.new
25
+ @loop_breaker.attach(@loop)
26
+ end
27
+
28
+ def run
29
+ @loop.run
30
+ end
31
+
32
+ def stop
33
+ @loop.stop
34
+ break_current_loop
35
+ end
36
+
37
+ def attach(watcher)
38
+ @loop.attach(watcher)
39
+ break_current_loop
40
+ end
41
+
42
+ def break_current_loop
43
+ @loop_breaker.signal
44
+ end
45
+ end
46
+ end
data/lib/droonga/farm.rb CHANGED
@@ -19,11 +19,15 @@ require "droonga/partition"
19
19
 
20
20
  module Droonga
21
21
  class Farm
22
- def initialize(name)
22
+ def initialize(name, loop, options={})
23
23
  @name = name
24
+ @loop = loop
25
+ @options = options
24
26
  @partitions = {}
25
- Droonga.catalog.get_partitions(name).each do |partition_name, options|
26
- partition = Droonga::Partition.new(options)
27
+ partitions = Droonga.catalog.get_partitions(name)
28
+ partitions.each do |partition_name, partition_options|
29
+ partition = Droonga::Partition.new(@loop,
30
+ @options.merge(partition_options))
27
31
  @partitions[partition_name] = partition
28
32
  end
29
33
  end
@@ -40,8 +44,8 @@ module Droonga
40
44
  end
41
45
  end
42
46
 
43
- def process(partition_name, envelope, synchronous)
44
- @partitions[partition_name].process(envelope, synchronous)
47
+ def process(partition_name, message)
48
+ @partitions[partition_name].process(message)
45
49
  end
46
50
  end
47
51
  end
@@ -0,0 +1,84 @@
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 "cool.io"
19
+ require "droonga/message_pack_packer"
20
+
21
+ module Droonga
22
+ class FluentMessageSender
23
+ def initialize(loop, host, port)
24
+ @loop = loop
25
+ @host = host
26
+ @port = port
27
+ end
28
+
29
+ def start
30
+ $log.trace("#{log_tag}: start: start")
31
+ connect
32
+ $log.trace("#{log_tag}: start: done")
33
+ end
34
+
35
+ def shutdown
36
+ $log.trace("#{log_tag}: shutdown: start")
37
+ @socket.close unless @socket.closed?
38
+ $log.trace("#{log_tag}: shutdown: done")
39
+ end
40
+
41
+ def send(tag, data)
42
+ $log.trace("#{log_tag}: send: start")
43
+ connect if @socket.closed?
44
+ fluent_message = [tag, Time.now.to_i, data]
45
+ packed_fluent_message = MessagePackPacker.pack(fluent_message)
46
+ @socket.write(packed_fluent_message)
47
+ @loop.break_current_loop
48
+ $log.trace("#{log_tag}: send: done")
49
+ end
50
+
51
+ private
52
+ def connect
53
+ $log.trace("#{log_tag}: connect: start")
54
+
55
+ log_write_complete = lambda do
56
+ $log.trace("#{log_tag}: write completed")
57
+ end
58
+ log_connect = lambda do
59
+ $log.trace("#{log_tag}: connected to #{@host}:#{@port}")
60
+ end
61
+ log_failed = lambda do
62
+ $log.error("#{log_tag}: failed to connect to #{@host}:#{@port}")
63
+ end
64
+
65
+ @socket = Coolio::TCPSocket.connect(@host, @port)
66
+ @socket.on_write_complete do
67
+ log_write_complete.call
68
+ end
69
+ @socket.on_connect do
70
+ log_connect.call
71
+ end
72
+ @socket.on_connect_failed do
73
+ log_failed.call
74
+ end
75
+ @loop.attach(@socket)
76
+
77
+ $log.trace("#{log_tag}: connect: done")
78
+ end
79
+
80
+ def log_tag
81
+ "[#{Process.ppid}][#{Process.pid}] fluent-message-sender"
82
+ end
83
+ end
84
+ end
@@ -15,34 +15,40 @@
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 "fluent-logger"
19
- require "fluent/logger/fluent_logger"
18
+ require "droonga/event_loop"
19
+ require "droonga/fluent_message_sender"
20
20
 
21
21
  module Droonga
22
22
  class Forwarder
23
- def initialize
24
- @outputs = {}
23
+ def initialize(loop)
24
+ @loop = loop
25
+ @senders = {}
26
+ end
27
+
28
+ def start
29
+ $log.trace("#{log_tag}: start: start")
30
+ $log.trace("#{log_tag}: start: done")
25
31
  end
26
32
 
27
33
  def shutdown
28
34
  $log.trace("#{log_tag}: shutdown: start")
29
- @outputs.each do |dest, output|
30
- output[:logger].close if output[:logger]
35
+ @senders.each_value do |sender|
36
+ sender.shutdown
31
37
  end
32
38
  $log.trace("#{log_tag}: shutdown: done")
33
39
  end
34
40
 
35
- def forward(envelope, body, destination)
36
- $log.trace("#{log_tag}: post: start")
41
+ def forward(message, destination)
42
+ $log.trace("#{log_tag}: forward: start")
37
43
  command = destination["type"]
38
44
  receiver = destination["to"]
39
45
  arguments = destination["arguments"]
40
- output(receiver, envelope, body, command, arguments)
41
- $log.trace("#{log_tag}: post: done")
46
+ output(receiver, message, command, arguments)
47
+ $log.trace("#{log_tag}: forward: done")
42
48
  end
43
49
 
44
50
  private
45
- def output(receiver, envelope, body, command, arguments)
51
+ def output(receiver, message, command, arguments)
46
52
  $log.trace("#{log_tag}: output: start")
47
53
  unless receiver.is_a?(String) && command.is_a?(String)
48
54
  $log.trace("#{log_tag}: output: abort: invalid argument",
@@ -57,65 +63,49 @@ module Droonga
57
63
  port = $2
58
64
  tag = $3
59
65
  params = $4
60
- output = get_output(host, port, params)
61
- unless output
62
- $log.trace("#{log_tag}: output: abort: no output",
66
+ sender = find_sender(host, port, params)
67
+ unless sender
68
+ $log.trace("#{log_tag}: output: abort: no sender",
63
69
  :host => host,
64
70
  :port => port,
65
71
  :params => params)
66
72
  return
67
73
  end
68
- if command =~ /\.result$/
69
- message = {
70
- inReplyTo: envelope["id"],
71
- statusCode: 200,
72
- type: command,
73
- body: body
74
- }
75
- else
76
- message = envelope.merge(
77
- body: body,
78
- type: command,
79
- arguments: arguments
80
- )
81
- end
74
+ override_message = {
75
+ "type" => command,
76
+ }
77
+ override_message["arguments"] = arguments if arguments
78
+ message = message.merge(override_message)
82
79
  output_tag = "#{tag}.message"
83
80
  log_info = "<#{receiver}>:<#{output_tag}>"
84
81
  $log.trace("#{log_tag}: output: post: start: #{log_info}")
85
- output.post(output_tag, message)
82
+ sender.send(output_tag, message)
86
83
  $log.trace("#{log_tag}: output: post: done: #{log_info}")
87
84
  $log.trace("#{log_tag}: output: done")
88
85
  end
89
86
 
90
- def get_output(host, port, params)
91
- host_port = "#{host}:#{port}"
92
- @outputs[host_port] ||= {}
93
- output = @outputs[host_port]
87
+ def find_sender(host, port, params)
88
+ connection_id = extract_connection_id(params)
89
+ destination = "#{host}:#{port}"
90
+ destination << "?#{connection_id}" if connection_id
94
91
 
95
- has_connection_id = (not params.nil? \
96
- and params =~ /[\?&;]connection_id=([^&;]+)/)
97
- if output[:logger].nil? or has_connection_id
98
- connection_id = $1
99
- if not has_connection_id or output[:connection_id] != connection_id
100
- output[:connection_id] = connection_id
101
- logger = create_logger(:host => host, :port => port.to_i)
102
- # output[:logger] should be closed if it exists beforehand?
103
- output[:logger] = logger
104
- end
105
- end
92
+ @senders[destination] ||= create_sender(host, port)
93
+ end
106
94
 
107
- has_client_session_id = (not params.nil? \
108
- and params =~ /[\?&;]client_session_id=([^&;]+)/)
109
- if has_client_session_id
110
- client_session_id = $1
111
- # some generic way to handle client_session_id is expected
112
- end
95
+ def extract_connection_id(params)
96
+ return nil unless params
113
97
 
114
- output[:logger]
98
+ if /[\?&;]connection_id=([^&;]+)/ =~ params
99
+ $1
100
+ else
101
+ nil
102
+ end
115
103
  end
116
104
 
117
- def create_logger(options)
118
- Fluent::Logger::FluentLogger.new(nil, options)
105
+ def create_sender(host, port)
106
+ sender = FluentMessageSender.new(@loop, host, port)
107
+ sender.start
108
+ sender
119
109
  end
120
110
 
121
111
  def log_tag