[Groonga-commit] droonga/fluent-plugin-droonga at 7bcc690 [master] Extract watch operations to Watcher

Back to archive index

Kouhei Sutou null+****@clear*****
Fri Oct 25 18:45:26 JST 2013


Kouhei Sutou	2013-10-25 18:45:26 +0900 (Fri, 25 Oct 2013)

  New Revision: 7bcc690f9388a0f1c6c26cc4b3120ccc3800afd5
  https://github.com/droonga/fluent-plugin-droonga/commit/7bcc690f9388a0f1c6c26cc4b3120ccc3800afd5

  Message:
    Extract watch operations to Watcher
    
    It improves testability.

  Copied files:
    lib/droonga/watcher.rb
      (from lib/droonga/plugin/handler_watch.rb)
  Modified files:
    lib/droonga/plugin/handler_watch.rb

  Modified: lib/droonga/plugin/handler_watch.rb (+23 -130)
===================================================================
--- lib/droonga/plugin/handler_watch.rb    2013-10-25 18:48:24 +0900 (59ef1bd)
+++ lib/droonga/plugin/handler_watch.rb    2013-10-25 18:45:26 +0900 (47dbe36)
@@ -15,65 +15,50 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+require "droonga/watcher"
 require "droonga/handler"
 
 module Droonga
   class WatchHandler < Droonga::Handler
     Droonga::HandlerPlugin.register("watch", self)
-    EXACT_MATCH = false
+
+    def initialize(*args)
+      super
+      @watcher = Watcher.new(@context)
+    end
 
     command "watch.subscribe" => :subscribe
     def subscribe(request)
       subscriber, condition, query, route = parse_request(request)
-      query_table = @context["Query"]
-      query_record = query_table[query]
-      unless query_record
-        keywords = pick_keywords([], condition)
-        query_record = query_table.add(query, :keywords => keywords)
-      end
-      subscriber_table = @context["Subscriber"]
-      subscriber_record = subscriber_table[subscriber]
-      if subscriber_record
-        subscriptions = subscriber_record.subscriptions.collect do |query|
-          return if query == query_record
-          query
-        end
-        subscriptions << query_record
-        subscriber_record.subscriptions = subscriptions
-      else
-        subscriber_table.add(subscriber,
-                             :subscriptions => [query_record],
-                             :route => route)
-      end
+      normalized_request = {
+        :subscriber => subscriber,
+        :condition  => condition,
+        :query      => query,
+        :route      => route,
+      }
+      @watcher.subscribe(normalized_request)
       emit([true])
     end
 
     command "watch.unsubscribe" => :unsubscribe
     def unsubscribe(request)
       subscriber, condition, query, route = parse_request(request)
-      query_table = @context["Query"]
-      query_record = query_table[query]
-      return unless query_record
-      subscriber_table = @context["Subscriber"]
-      subscriber_record = subscriber_table[subscriber]
-      return unless subscriber_record
-      subscriptions = subscriber_record.subscriptions.select do |query|
-        query != query_record
-      end
-      subscriber_record.subscriptions = subscriptions
+      normalized_request = {
+        :subscriber => subscriber,
+        :condition  => condition,
+        :query      => query,
+      }
+      @watcher.unsubscribe(normalized_request)
       emit([true])
     end
 
     command "watch.feed" => :feed
     def feed(request)
-      targets = request["targets"]
-
-      hits = []
-      targets.each do |key, target|
-        scan_body(hits, target)
+      @watcher.feed(:targets => request["targets"]) do |route, subscribers|
+        message = request # return request itself
+        envelope["to"] = subscribers
+        post(message, "to" => route, "type" => "watch.notification")
       end
-
-      publish(hits, request)
     end
 
     private
@@ -86,97 +71,5 @@ module Droonga
       raise "too long query" if query.size > 4095
       [subscriber, condition, query, route]
     end
-
-    def pick_keywords(memo, condition)
-      case condition
-      when Hash
-        memo << condition["query"]
-      when String
-        memo << condition
-      when Array
-        condition[1..-1].each do |element|
-          pick_keywords(memo, element)
-        end
-      end
-      memo
-    end
-
-    def scan_body(hits, body)
-      trimmed = body.strip
-      candidates = {}
-      # FIXME scan reports the longest keyword matched only
-      @context["Keyword"].scan(trimmed).each do |keyword, word, start, length|
-        @context["Query"].select do |query|
-          query.keywords =~ keyword
-        end.each do |record|
-          candidates[record.key] ||= []
-          candidates[record.key] << keyword
-        end
-      end
-      candidates.each do |query, keywords|
-        hits << query if query_match(query, keywords)
-      end
-    end
-
-    def query_match(query, keywords)
-      return true unless EXACT_MATCH
-      @conditions = {} unless @conditions
-      condition = @conditions[query.id]
-      unless condition
-        condition = JSON.parse(query.key)
-        @conditions[query.id] = condition
-        # CAUTION: @conditions can be huge.
-      end
-      words = {}
-      keywords.each do |keyword|
-        words[keyword.key] = true
-      end
-      eval_condition(condition, words)
-    end
-
-    def eval_condition(condition, words)
-      case condition
-      when Hash
-        # todo
-      when String
-        words[condition]
-      when Array
-        case condition.first
-        when "||"
-          condition[1..-1].each do |element|
-            return true if eval_condition(element, words)
-          end
-          false
-        when "&&"
-          condition[1..-1].each do |element|
-            return false unless eval_condition(element, words)
-          end
-          true
-        when "-"
-          return false unless eval_condition(condition[1], words)
-          condition[2..-1].each do |element|
-            return false if eval_condition(element, words)
-          end
-          true
-        end
-      end
-    end
-
-    def publish(hits, request)
-      routes = {}
-      hits.each do |query|
-        @context["Subscriber"].select do |subscriber|
-          subscriber.subscriptions =~ query
-        end.each do |subscriber|
-          routes[subscriber.route.key] ||= []
-          routes[subscriber.route.key] << subscriber.key.key
-        end
-      end
-      routes.each do |route, subscribers|
-        message = request # return request itself
-        envelope["to"] = subscribers
-        post(message, "to" => route, "type" => "watch.notification")
-      end
-    end
   end
 end

  Copied: lib/droonga/watcher.rb (+18 -28) 81%
===================================================================
--- lib/droonga/plugin/handler_watch.rb    2013-10-25 18:48:24 +0900 (59ef1bd)
+++ lib/droonga/watcher.rb    2013-10-25 18:45:26 +0900 (7916aab)
@@ -15,16 +15,20 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-require "droonga/handler"
-
 module Droonga
-  class WatchHandler < Droonga::Handler
-    Droonga::HandlerPlugin.register("watch", self)
+  class Watcher
     EXACT_MATCH = false
 
-    command "watch.subscribe" => :subscribe
+    def initialize(context)
+      @context = context
+    end
+
     def subscribe(request)
-      subscriber, condition, query, route = parse_request(request)
+      subscriber = request[:subscriber]
+      condition  = request[:condition]
+      query      = request[:query]
+      route      = request[:route]
+
       query_table = @context["Query"]
       query_record = query_table[query]
       unless query_record
@@ -45,12 +49,13 @@ module Droonga
                              :subscriptions => [query_record],
                              :route => route)
       end
-      emit([true])
     end
 
-    command "watch.unsubscribe" => :unsubscribe
     def unsubscribe(request)
-      subscriber, condition, query, route = parse_request(request)
+      subscriber = request[:subscriber]
+      condition  = request[:condition]
+      query      = request[:query]
+
       query_table = @context["Query"]
       query_record = query_table[query]
       return unless query_record
@@ -61,30 +66,17 @@ module Droonga
         query != query_record
       end
       subscriber_record.subscriptions = subscriptions
-      emit([true])
     end
 
-    command "watch.feed" => :feed
-    def feed(request)
-      targets = request["targets"]
+    def feed(request, &block)
+      targets = request[:targets]
 
       hits = []
       targets.each do |key, target|
         scan_body(hits, target)
       end
 
-      publish(hits, request)
-    end
-
-    private
-    def parse_request(request)
-      subscriber = request["subscriber"]
-      condition = request["condition"]
-      route = request["route"] || envelope["from"]
-      raise "invalid request" if subscriber.nil? || subscriber.empty? || condition.nil?
-      query = condition.to_json
-      raise "too long query" if query.size > 4095
-      [subscriber, condition, query, route]
+      publish(hits, request, &block)
     end
 
     def pick_keywords(memo, condition)
@@ -173,9 +165,7 @@ module Droonga
         end
       end
       routes.each do |route, subscribers|
-        message = request # return request itself
-        envelope["to"] = subscribers
-        post(message, "to" => route, "type" => "watch.notification")
+        yield(route, subscribers)
       end
     end
   end
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index