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 +1 -0
- data/README.md +1 -0
- data/doc/text/news.md +16 -3
- data/groonga-client.gemspec +1 -1
- data/lib/groonga/client.rb +69 -7
- data/lib/groonga/client/command.rb +1 -2
- data/lib/groonga/client/connection/error.rb +31 -0
- data/lib/groonga/client/{protocol → connection}/gqtp.rb +41 -1
- data/lib/groonga/client/connection/http.rb +83 -0
- data/lib/groonga/client/{protocol/http.rb → connection/request.rb} +5 -18
- data/lib/groonga/client/response/base.rb +38 -8
- data/lib/groonga/client/response/column_list.rb +3 -2
- data/lib/groonga/client/response/select.rb +46 -14
- data/lib/groonga/client/response/table_create.rb +12 -0
- data/lib/groonga/client/response/table_list.rb +3 -2
- data/lib/groonga/client/version.rb +1 -1
- data/test/connection/test-gqtp.rb +105 -0
- data/test/connection/test-http.rb +97 -0
- data/test/response/helper.rb +4 -0
- data/test/response/test-column-list.rb +2 -11
- data/test/response/test-select.rb +127 -12
- data/test/response/test-table-list.rb +2 -11
- data/test/results/test-column-list.rb +2 -1
- data/test/results/test-table-list.rb +2 -1
- data/test/test-client.rb +43 -27
- data/test/test-command.rb +36 -3
- metadata +36 -31
- data/test/results/test-select.rb +0 -63
data/.yardopts
CHANGED
data/README.md
CHANGED
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
|
-
|
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
|
|
data/groonga-client.gemspec
CHANGED
@@ -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.
|
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")
|
data/lib/groonga/client.rb
CHANGED
@@ -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/
|
22
|
-
require "groonga/client/
|
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
|
-
|
31
|
-
|
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::
|
71
|
+
@connection = Groonga::Client::Connection::GQTP.new(options)
|
47
72
|
else
|
48
|
-
@connection = Groonga::Client::
|
73
|
+
@connection = Groonga::Client::Connection::HTTP.new(options)
|
49
74
|
end
|
50
75
|
end
|
51
76
|
|
52
|
-
|
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
|
-
|
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
|
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
|
25
|
-
class
|
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
|
36
|
-
def initialize
|
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
|
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(
|
41
|
-
case
|
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
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
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
|