groonga-client 0.0.2 → 0.0.3

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.
data/.yardopts CHANGED
@@ -1,4 +1,5 @@
1
1
  --output-dir doc/reference/en
2
+ --markup markdown
2
3
  lib/**/*.rb
3
4
  -
4
5
  doc/text/**/*
data/README.md CHANGED
@@ -57,6 +57,7 @@ TODO: use commands with parameters for examples
57
57
  ## Authors
58
58
 
59
59
  * Haruka Yoshihara \<yoshihara@clear-code.com\>
60
+ * Kouhei Sutou \<kou@clear-code.com\>
60
61
 
61
62
  ## License
62
63
 
data/doc/text/news.md CHANGED
@@ -1,12 +1,25 @@
1
1
  # NEWS
2
2
 
3
+ ## 0.0.3 - 2013-09-18
4
+
5
+ ### Improvements
6
+
7
+ * Supported "table_create" command.
8
+ * {Groonga::Client.open} returns block value.
9
+ * Supported {Groonga::Client#close}.
10
+ * select: Supported auto time value conversion.
11
+ * select: Renamed to {Groonga::Client::Response::Select#n_hits}
12
+ from #n_records. It is a backward incompatible change.
13
+ * Added {Groonga::Client::Connection::Error} as an abstracted error.
14
+ * Required groonga-command 1.0.4 or later.
15
+
3
16
  ## 0.0.2 - 2013-07-08
4
17
 
5
18
  ### Improvements
6
19
 
7
- * Supported "select" command.
8
- * Supported Enumerable type interface in
9
- Response::TableList and Response::ColumnList
20
+ * Supported "select" command.
21
+ * Supported Enumerable type interface in
22
+ Response::TableList and Response::ColumnList
10
23
 
11
24
  ## 0.0.1 - 2013-06-27
12
25
 
@@ -47,7 +47,7 @@ Gem::Specification.new do |spec|
47
47
  # end
48
48
 
49
49
  spec.add_runtime_dependency("gqtp", ">= 1.0.4")
50
- spec.add_runtime_dependency("groonga-command", ">= 1.0.2")
50
+ spec.add_runtime_dependency("groonga-command", ">= 1.0.4")
51
51
 
52
52
  spec.add_development_dependency("bundler")
53
53
  spec.add_development_dependency("rake")
@@ -18,17 +18,41 @@
18
18
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
19
 
20
20
  require "groonga/client/command"
21
- require "groonga/client/protocol/gqtp"
22
- require "groonga/client/protocol/http"
21
+ require "groonga/client/connection/gqtp"
22
+ require "groonga/client/connection/http"
23
23
 
24
24
  module Groonga
25
25
  class Client
26
26
  class << self
27
+ # @!macro [new] initialize_options
28
+ # @param [Hash] options The options.
29
+ # @option options [:gqtp or :http] :protocol The protocol that is
30
+ # used by the client.
31
+ #
32
+ # @overload open(options={})
33
+ # Opens a new client connection.
34
+ #
35
+ # @macro initialize_options
36
+ # @return [Client] The opened client.
37
+ #
38
+ # @overload open(options={}) {|client| }
39
+ # Opens a new client connection while the block is evaluated.
40
+ # The block is finished the opened client is closed.
41
+ #
42
+ # @macro initialize_options
43
+ # @yield [client] Gives a opened client to the block. The opened
44
+ # client is closed automatically when the block is finished.
45
+ # @yieldparam client [Client] The opened client.
46
+ # @yieldreturn [Object] Any object.
47
+ # @return [Object] Any object that is returned by the block.
27
48
  def open(options={}, &block)
28
49
  client = new(options)
29
50
  if block_given?
30
- yield(client)
31
- client.close
51
+ begin
52
+ yield(client)
53
+ ensure
54
+ client.close
55
+ end
32
56
  else
33
57
  client
34
58
  end
@@ -38,18 +62,55 @@ module Groonga
38
62
  attr_reader :protocol
39
63
  attr_reader :connection
40
64
 
65
+ # @macro initialize_options
41
66
  def initialize(options)
42
67
  @protocol = options.delete(:protocol) || :gqtp
43
68
 
44
69
  @connection = nil
45
70
  if @protocol == :gqtp
46
- @connection = Groonga::Client::Protocol::GQTP.new(options)
71
+ @connection = Groonga::Client::Connection::GQTP.new(options)
47
72
  else
48
- @connection = Groonga::Client::Protocol::HTTP.new(options)
73
+ @connection = Groonga::Client::Connection::HTTP.new(options)
49
74
  end
50
75
  end
51
76
 
52
- def close
77
+ # Closes the opened client connection if the current connection is
78
+ # still opened. You can't send a new command after you call this
79
+ # method.
80
+ #
81
+ # @overload close
82
+ # Closes synchronously.
83
+ #
84
+ # @return [Boolean] true when the opened connection is closed.
85
+ # false when there is no connection.
86
+ #
87
+ # @overload close {}
88
+ # Closes asynchronously.
89
+ #
90
+ # @yield [] Calls the block when the opened connection is closed.
91
+ # @return [#wait] The request object. If you want to wait until
92
+ # the request is processed. You can send #wait message to the
93
+ # request.
94
+ def close(&block)
95
+ sync = !block_given?
96
+ if @connection
97
+ close_request = @connection.close do
98
+ yield unless sync
99
+ @connection = nil
100
+ end
101
+ if sync
102
+ close_request.wait
103
+ true
104
+ else
105
+ close_request
106
+ end
107
+ else
108
+ if sync
109
+ false
110
+ else
111
+ Connection::EmptryReqest.new
112
+ end
113
+ end
53
114
  end
54
115
 
55
116
  def cache_limit(parameters)
@@ -128,6 +189,7 @@ module Groonga
128
189
  end
129
190
 
130
191
  def table_create(parameters)
192
+ execute_command("table_create", parameters)
131
193
  end
132
194
 
133
195
  def table_list(parameters={})
@@ -46,8 +46,7 @@ module Groonga
46
46
 
47
47
  private
48
48
  def parse_raw_response(raw_response)
49
- response_class = Groonga::Client::Response.find(@command.name)
50
- response_class.parse(raw_response, @command.output_type)
49
+ Groonga::Client::Response.parse(@command, raw_response)
51
50
  end
52
51
  end
53
52
  end
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
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 as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ module Groonga
20
+ class Client
21
+ module Connection
22
+ class Error < StandardError
23
+ attr_reader :raw_error
24
+ def initialize(raw_error)
25
+ @raw_error = raw_error
26
+ super(raw_error.message)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -22,9 +22,11 @@ require "erb"
22
22
  require "gqtp"
23
23
  require "json"
24
24
 
25
+ require "groonga/client/connection/request"
26
+
25
27
  module Groonga
26
28
  class Client
27
- module Protocol
29
+ module Connection
28
30
  class GQTP
29
31
  def initialize(options)
30
32
  @client = ::GQTP::Client.new(options)
@@ -41,6 +43,44 @@ module Groonga
41
43
  end
42
44
  end
43
45
 
46
+ # @return [Boolean] true if the current connection is opened,
47
+ # false otherwise.
48
+ def connected?
49
+ not @client.nil?
50
+ end
51
+
52
+ # Closes the opened connection if the current connection is
53
+ # still opened. You can't send a new command after you call
54
+ # this method.
55
+ #
56
+ # @overload close
57
+ # Closes synchronously.
58
+ #
59
+ # @return [Boolean] true when the opened connection is closed.
60
+ # false when there is no connection.
61
+ #
62
+ # @overload close {}
63
+ # Closes asynchronously.
64
+ #
65
+ # @yield [] Calls the block when the opened connection is closed.
66
+ # @return [#wait] The request object. If you want to wait until
67
+ # the request is processed. You can send #wait message to the
68
+ # request.
69
+ def close(&block)
70
+ sync = !block_given?
71
+ if connected?
72
+ return_value = @client.close(&block)
73
+ @client = nil
74
+ return_value
75
+ else
76
+ if sync
77
+ false
78
+ else
79
+ EmptyRequest.new
80
+ end
81
+ end
82
+ end
83
+
44
84
  class RawResponse
45
85
  include ERB::Util
46
86
 
@@ -0,0 +1,83 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
4
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+
20
+ require "open-uri"
21
+
22
+ require "groonga/client/connection/request"
23
+ require "groonga/client/connection/error"
24
+
25
+ module Groonga
26
+ class Client
27
+ module Connection
28
+ class HTTP
29
+ def initialize(options)
30
+ @host = options[:host] || "127.0.0.1"
31
+ @port = options[:port] || 10041
32
+ end
33
+
34
+ def send(command)
35
+ url = "http://#{@host}:#{@port}#{command.to_uri_format}"
36
+ thread = Thread.new do
37
+ begin
38
+ open(url) do |response|
39
+ body = response.read
40
+ yield(body)
41
+ end
42
+ rescue OpenURI::HTTPError
43
+ raise Error.new($!)
44
+ end
45
+ end
46
+ ThreadRequest.new(thread)
47
+ end
48
+
49
+ # @return [false] Always returns false because the current
50
+ # implementation doesn't support keep-alive.
51
+ def connected?
52
+ false
53
+ end
54
+
55
+ # Does nothing because the current implementation doesn't
56
+ # support keep-alive. If the implementation supports
57
+ # keep-alive, it close the opend connection.
58
+ #
59
+ # @overload close
60
+ # Closes synchronously.
61
+ #
62
+ # @return [false] It always returns false because there is always
63
+ # no connectin.
64
+ #
65
+ # @overload close {}
66
+ # Closes asynchronously.
67
+ #
68
+ # @yield [] Calls the block when the opened connection is closed.
69
+ # @return [#wait] The request object. If you want to wait until
70
+ # the request is processed. You can send #wait message to the
71
+ # request.
72
+ def close(&block)
73
+ sync = !block_given?
74
+ if sync
75
+ false
76
+ else
77
+ EmptyRequest.new
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,6 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
4
3
  # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
5
4
  #
6
5
  # This library is free software; you can redistribute it and/or
@@ -17,12 +16,10 @@
17
16
  # License along with this library; if not, write to the Free Software
18
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
18
 
20
- require "open-uri"
21
-
22
19
  module Groonga
23
20
  class Client
24
- module Protocol
25
- class Request
21
+ module Connection
22
+ class ThreadRequest
26
23
  def initialize(thread)
27
24
  @thread = thread
28
25
  end
@@ -32,21 +29,11 @@ module Groonga
32
29
  end
33
30
  end
34
31
 
35
- class HTTP
36
- def initialize(options)
37
- @host = options[:host] || "127.0.0.1"
38
- @port = options[:port] || 10041
32
+ class EmptyRequest
33
+ def initialize
39
34
  end
40
35
 
41
- def send(command)
42
- url = "http://#{@host}:#{@port}#{command.to_uri_format}"
43
- thread = Thread.new do
44
- open(url) do |response|
45
- body = response.read
46
- yield(body)
47
- end
48
- end
49
- Request.new(thread)
36
+ def wait
50
37
  end
51
38
  end
52
39
  end
@@ -33,12 +33,24 @@ module Groonga
33
33
  def find(name)
34
34
  @@registered_commands[name] || Base
35
35
  end
36
+
37
+ # Parses the response for the request of the command and returns
38
+ # response object.
39
+ #
40
+ # @param [Groonga::Command::Base] The command of the request.
41
+ # @param [String] The raw (not parsed) response returned by groonga
42
+ # server.
43
+ # @return [Base]
44
+ def parse(command, raw_response)
45
+ klass = find(command.name)
46
+ klass.parse(command, raw_response)
47
+ end
36
48
  end
37
49
 
38
50
  class Base
39
51
  class << self
40
- def parse(raw_response, type)
41
- case type
52
+ def parse(command, raw_response)
53
+ case command.output_type
42
54
  when :json
43
55
  header, body = JSON.parse(raw_response)
44
56
  when :xml
@@ -47,7 +59,7 @@ module Groonga
47
59
  header = nil
48
60
  body = raw_response
49
61
  end
50
- response = new(header, body)
62
+ response = new(command, header, body)
51
63
  response.raw = raw_response
52
64
  response
53
65
  end
@@ -100,13 +112,31 @@ module Groonga
100
112
  end
101
113
  end
102
114
 
103
- attr_accessor :header, :body
115
+ # @return [Groonga::Command] The command for the request.
116
+ attr_accessor :command
117
+ # @return [::Array<Integer, Float, Float>] The header of response.
118
+ # It consists of `[return_code, start_time, elapsed_time_in_seconds]`
119
+ # for success case.
120
+ # It consists of
121
+ # `[return_code, start_time, elapsed_time_in_seconds, error_message, error_location]`
122
+ # for error case.
123
+ # @see http://groonga.org/docs/reference/command/output_format.html#header
124
+ # Defails for header format.
125
+ attr_accessor :header
126
+ # @return [::Hash] The body of response. Its content is depends on
127
+ # command.
128
+ # @see http://groonga.org/docs/reference/command.html
129
+ # The list of built-in commands.
130
+ attr_accessor :body
131
+ # @return [String] The unparsed response. It may be JSON, XML or
132
+ # groonga command format.
104
133
  attr_accessor :raw
105
134
 
106
- def initialize(header, body)
107
- @header = header
108
- @body = body
109
- @raw = nil
135
+ def initialize(command, header, body)
136
+ self.command = command
137
+ self.header = header
138
+ self.body = body
139
+ self.raw = nil
110
140
  end
111
141
  end
112
142
  end