oedipus 0.0.15 → 0.0.16
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/lib/oedipus/connection.rb +12 -7
- data/lib/oedipus/rspec/test_rig.rb +125 -0
- data/lib/oedipus/version.rb +1 -1
- data/spec/integration/connection/registry_spec.rb +6 -15
- data/spec/integration/connection_spec.rb +8 -15
- data/spec/integration/index_spec.rb +5 -14
- metadata +9 -9
- data/lib/oedipus/rspec/test_harness.rb +0 -152
data/lib/oedipus/connection.rb
CHANGED
@@ -12,6 +12,8 @@ module Oedipus
|
|
12
12
|
#
|
13
13
|
# Currently this class wraps a native mysql extension.
|
14
14
|
class Connection
|
15
|
+
attr_reader :options
|
16
|
+
|
15
17
|
# Instantiate a new Connection to a SphinxQL host.
|
16
18
|
#
|
17
19
|
# @param [String] server
|
@@ -24,18 +26,21 @@ module Oedipus
|
|
24
26
|
#
|
25
27
|
# The underlying implementation uses a thread-safe connection pool.
|
26
28
|
def initialize(options)
|
27
|
-
options =
|
28
|
-
|
29
|
-
|
29
|
+
@options =
|
30
|
+
if options.kind_of?(String)
|
31
|
+
Hash[ [:host, :port].zip(options.split(":")) ]
|
32
|
+
else
|
33
|
+
options.dup
|
34
|
+
end.tap { |o| o[:port] = o[:port].to_i }
|
30
35
|
|
31
36
|
@pool = Pool.new(
|
32
|
-
host: options[:host],
|
33
|
-
port: options[:port]
|
34
|
-
size: options.fetch(:pool_size, 8),
|
37
|
+
host: @options[:host],
|
38
|
+
port: @options[:port],
|
39
|
+
size: @options.fetch(:pool_size, 8),
|
35
40
|
ttl: 60
|
36
41
|
)
|
37
42
|
|
38
|
-
assert_valid_pool
|
43
|
+
assert_valid_pool unless @options[:verify] == false
|
39
44
|
end
|
40
45
|
|
41
46
|
# Acess a specific index for querying.
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "rspec/core"
|
11
|
+
require "tmpdir"
|
12
|
+
|
13
|
+
# RSpec shared context that may be included to provide a pre-defined index.
|
14
|
+
shared_context "oedipus posts_rt" do
|
15
|
+
def sphinx_indexes
|
16
|
+
<<-STR
|
17
|
+
index posts_rt
|
18
|
+
{
|
19
|
+
type = rt
|
20
|
+
path = #{data_dir}/posts_rt
|
21
|
+
|
22
|
+
rt_field = title
|
23
|
+
rt_field = body
|
24
|
+
|
25
|
+
rt_attr_uint = user_id
|
26
|
+
rt_attr_uint = views
|
27
|
+
rt_attr_string = state
|
28
|
+
}
|
29
|
+
STR
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# RSpec shared context that may be included to start and stop sphinx between example groups.
|
34
|
+
shared_context "oedipus test rig" do
|
35
|
+
before(:all) do
|
36
|
+
write_sphinx_config
|
37
|
+
start_sphinx
|
38
|
+
end
|
39
|
+
|
40
|
+
after(:all) do
|
41
|
+
stop_sphinx
|
42
|
+
clean_data_dir
|
43
|
+
end
|
44
|
+
|
45
|
+
after(:each) { empty_indexes }
|
46
|
+
|
47
|
+
# It is intended that any or all of the following be overridden in tests.
|
48
|
+
def connection
|
49
|
+
@connection ||= Oedipus::Connection.new(host: "127.0.0.1", port: 9399, verify: false)
|
50
|
+
end
|
51
|
+
|
52
|
+
def data_dir
|
53
|
+
@data_dir ||= Dir.mktmpdir("oedipus")
|
54
|
+
end
|
55
|
+
|
56
|
+
def searchd
|
57
|
+
ENV["SEARCHD"] || "searchd"
|
58
|
+
end
|
59
|
+
|
60
|
+
def sphinx_indexes
|
61
|
+
<<-IDX.strip.gsub(/^ {4}/, "")
|
62
|
+
index test_rt {
|
63
|
+
type = rt
|
64
|
+
path = #{data_dir}/test_rt
|
65
|
+
rt_field = test"
|
66
|
+
}
|
67
|
+
IDX
|
68
|
+
end
|
69
|
+
|
70
|
+
def sphinx_conf
|
71
|
+
<<-CONF.strip.gsub(/^ {4}/, "")
|
72
|
+
##
|
73
|
+
# This file is automatically generated during tests
|
74
|
+
##
|
75
|
+
|
76
|
+
#{sphinx_indexes}
|
77
|
+
|
78
|
+
searchd
|
79
|
+
{
|
80
|
+
compat_sphinxql_magics = 0
|
81
|
+
|
82
|
+
max_matches = 2000
|
83
|
+
pid_file = #{data_dir}/searchd.pid
|
84
|
+
listen = #{connection.options[:host]}:#{connection.options[:port]}:mysql41
|
85
|
+
workers = threads
|
86
|
+
log = #{data_dir}/searchd.log
|
87
|
+
query_log = #{data_dir}/searchd.log
|
88
|
+
binlog_path = #{data_dir}
|
89
|
+
}
|
90
|
+
CONF
|
91
|
+
end
|
92
|
+
|
93
|
+
def write_sphinx_config
|
94
|
+
File.open("#{data_dir}/sphinx.conf", "w") do |f|
|
95
|
+
f << sphinx_conf
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def start_sphinx
|
100
|
+
@pid = Process.spawn(
|
101
|
+
searchd, "--console", "-c", "#{data_dir}/sphinx.conf",
|
102
|
+
out: "#{data_dir}/searchd.out",
|
103
|
+
err: "#{data_dir}/searchd.err"
|
104
|
+
)
|
105
|
+
sleep 1
|
106
|
+
end
|
107
|
+
|
108
|
+
def stop_sphinx
|
109
|
+
Process.kill(:TERM, @pid) && Process.wait
|
110
|
+
end
|
111
|
+
|
112
|
+
def clean_data_dir
|
113
|
+
Dir["#{data_dir}/**/*"].each do |path|
|
114
|
+
File.delete(path)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def empty_indexes
|
119
|
+
connection.query("SHOW TABLES").each do |idx|
|
120
|
+
connection.query("SELECT id FROM #{idx['Index']}").each do |hash|
|
121
|
+
connection.execute("DELETE FROM #{idx['Index']} WHERE id = #{hash['id']}")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/oedipus/version.rb
CHANGED
@@ -8,20 +8,11 @@
|
|
8
8
|
##
|
9
9
|
|
10
10
|
require "spec_helper"
|
11
|
-
require "oedipus/rspec/
|
11
|
+
require "oedipus/rspec/test_rig"
|
12
12
|
|
13
13
|
describe Oedipus::Connection::Registry do
|
14
|
-
|
15
|
-
|
16
|
-
before(:all) do
|
17
|
-
set_data_dir File.expand_path("../../../data", __FILE__)
|
18
|
-
set_searchd ENV["SEARCHD"]
|
19
|
-
start_searchd
|
20
|
-
end
|
21
|
-
|
22
|
-
after(:all) { stop_searchd }
|
23
|
-
|
24
|
-
before(:each) { empty_indexes }
|
14
|
+
include_context "oedipus test rig"
|
15
|
+
include_context "oedipus posts_rt"
|
25
16
|
|
26
17
|
let(:registry) do
|
27
18
|
Object.new.tap { |o| o.send(:extend, Oedipus::Connection::Registry) }
|
@@ -29,13 +20,13 @@ describe Oedipus::Connection::Registry do
|
|
29
20
|
|
30
21
|
describe "#connect" do
|
31
22
|
it "makes a new connection to a SphinxQL host" do
|
32
|
-
registry.connect(
|
23
|
+
registry.connect(connection.options).should be_a_kind_of(Oedipus::Connection)
|
33
24
|
end
|
34
25
|
end
|
35
26
|
|
36
27
|
describe "#connection" do
|
37
28
|
context "without a name" do
|
38
|
-
let(:conn) { registry.connect(
|
29
|
+
let(:conn) { registry.connect(connection.options) }
|
39
30
|
|
40
31
|
it "returns an existing connection" do
|
41
32
|
conn.should equal registry.connection
|
@@ -43,7 +34,7 @@ describe Oedipus::Connection::Registry do
|
|
43
34
|
end
|
44
35
|
|
45
36
|
context "with a name" do
|
46
|
-
let(:conn) { registry.connect(
|
37
|
+
let(:conn) { registry.connect(connection.options, :bob) }
|
47
38
|
|
48
39
|
it "returns the named connection" do
|
49
40
|
conn.should equal registry.connection(:bob)
|
@@ -8,28 +8,21 @@
|
|
8
8
|
##
|
9
9
|
|
10
10
|
require "spec_helper"
|
11
|
-
require "oedipus/rspec/
|
11
|
+
require "oedipus/rspec/test_rig"
|
12
12
|
|
13
13
|
describe Oedipus::Connection do
|
14
|
-
|
14
|
+
include_context "oedipus test rig"
|
15
|
+
include_context "oedipus posts_rt"
|
15
16
|
|
16
|
-
|
17
|
-
set_data_dir File.expand_path("../../data", __FILE__)
|
18
|
-
set_searchd ENV["SEARCHD"]
|
19
|
-
start_searchd
|
20
|
-
end
|
21
|
-
|
22
|
-
after(:all) { stop_searchd }
|
23
|
-
|
24
|
-
before(:each) { empty_indexes }
|
25
|
-
|
26
|
-
let(:conn) { Oedipus::Connection.new(searchd_host) }
|
17
|
+
let(:conn) { Oedipus::Connection.new(connection.options) }
|
27
18
|
|
28
19
|
describe "#initialize" do
|
29
20
|
context "with a hosname:port string" do
|
30
21
|
context "on successful connection" do
|
31
22
|
it "returns the connection" do
|
32
|
-
Oedipus::Connection.new(
|
23
|
+
Oedipus::Connection.new(
|
24
|
+
"#{connection.options[:host]}:#{connection.options[:port]}"
|
25
|
+
).should be_a_kind_of(Oedipus::Connection)
|
33
26
|
end
|
34
27
|
end
|
35
28
|
|
@@ -45,7 +38,7 @@ describe Oedipus::Connection do
|
|
45
38
|
context "with an options Hash" do
|
46
39
|
context "on successful connection" do
|
47
40
|
it "returns the connection" do
|
48
|
-
Oedipus::Connection.new(
|
41
|
+
Oedipus::Connection.new(connection.options).should be_a_kind_of(Oedipus::Connection)
|
49
42
|
end
|
50
43
|
end
|
51
44
|
|
@@ -8,22 +8,13 @@
|
|
8
8
|
##
|
9
9
|
|
10
10
|
require "spec_helper"
|
11
|
-
require "oedipus/rspec/
|
11
|
+
require "oedipus/rspec/test_rig"
|
12
12
|
|
13
13
|
describe Oedipus::Index do
|
14
|
-
|
14
|
+
include_context "oedipus test rig"
|
15
|
+
include_context "oedipus posts_rt"
|
15
16
|
|
16
|
-
|
17
|
-
set_data_dir File.expand_path("../../data", __FILE__)
|
18
|
-
set_searchd ENV["SEARCHD"]
|
19
|
-
start_searchd
|
20
|
-
end
|
21
|
-
|
22
|
-
after(:all) { stop_searchd }
|
23
|
-
|
24
|
-
before(:each) { empty_indexes }
|
25
|
-
|
26
|
-
let(:conn) { Oedipus::Connection.new(searchd_host) }
|
17
|
+
let(:conn) { connection }
|
27
18
|
let(:index) { Oedipus::Index.new(:posts_rt, conn) }
|
28
19
|
|
29
20
|
describe "#insert" do
|
@@ -340,7 +331,7 @@ describe Oedipus::Index do
|
|
340
331
|
end
|
341
332
|
|
342
333
|
context "with overriding overriding fulltext queries" do
|
343
|
-
let(:results) do
|
334
|
+
let(:results) do # FIXME: Weird RSpec bug is not clearing the previous result, hence the ridiculous naming
|
344
335
|
index.search(
|
345
336
|
"badgers",
|
346
337
|
facets: {
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oedipus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.16
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &15535840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *15535840
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake-compiler
|
27
|
-
requirement: &
|
27
|
+
requirement: &15533700 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *15533700
|
36
36
|
description: ! "== Sphinx 2 Comes to Ruby\n\nOedipus brings full support for Sphinx
|
37
37
|
2 to Ruby:\n\n - real-time indexes (insert, replace, update, delete)\n - faceted
|
38
38
|
search (variations on a base query)\n - multi-queries (multiple queries executed
|
@@ -77,7 +77,7 @@ files:
|
|
77
77
|
- lib/oedipus/connection_error.rb
|
78
78
|
- lib/oedipus/index.rb
|
79
79
|
- lib/oedipus/query_builder.rb
|
80
|
-
- lib/oedipus/rspec/
|
80
|
+
- lib/oedipus/rspec/test_rig.rb
|
81
81
|
- lib/oedipus/version.rb
|
82
82
|
- oedipus.gemspec
|
83
83
|
- spec/data/.gitkeep
|
@@ -113,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
113
|
version: '0'
|
114
114
|
segments:
|
115
115
|
- 0
|
116
|
-
hash:
|
116
|
+
hash: 1033865904728202433
|
117
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
118
|
none: false
|
119
119
|
requirements:
|
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
version: '0'
|
123
123
|
segments:
|
124
124
|
- 0
|
125
|
-
hash:
|
125
|
+
hash: 1033865904728202433
|
126
126
|
requirements: []
|
127
127
|
rubyforge_project: oedipus
|
128
128
|
rubygems_version: 1.8.11
|
@@ -1,152 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
##
|
4
|
-
# Oedipus Sphinx 2 Search.
|
5
|
-
# Copyright © 2012 Chris Corbyn.
|
6
|
-
#
|
7
|
-
# See LICENSE file for details.
|
8
|
-
##
|
9
|
-
|
10
|
-
module Oedipus
|
11
|
-
module RSpec
|
12
|
-
# Mixed into RSpec suites to manage starting/stopping Sphinx and writing indexes.
|
13
|
-
module TestHarness
|
14
|
-
# Set the path to the searchd executable.
|
15
|
-
#
|
16
|
-
# The version of Sphinx must be >= 2.0.2.
|
17
|
-
#
|
18
|
-
# @param [String] path
|
19
|
-
# the absolute path to searchd
|
20
|
-
def set_searchd(path)
|
21
|
-
@searchd = path
|
22
|
-
end
|
23
|
-
|
24
|
-
# Set the path to a temporary directory for writing test data to.
|
25
|
-
#
|
26
|
-
# @param [String] path
|
27
|
-
# the path to a writable directory whose contents may be completely deleted
|
28
|
-
def set_data_dir(path)
|
29
|
-
@data_dir = path
|
30
|
-
end
|
31
|
-
|
32
|
-
# Ensure that the temporary data directories exist and are clean.
|
33
|
-
def prepare_data_dirs
|
34
|
-
Dir.mkdir("#{data_dir}/index") unless Dir.exist?("#{data_dir}/index")
|
35
|
-
Dir.mkdir("#{data_dir}/binlog") unless Dir.exist?("#{data_dir}/binlog")
|
36
|
-
|
37
|
-
clean_data_dirs
|
38
|
-
end
|
39
|
-
|
40
|
-
def empty_indexes
|
41
|
-
@conn ||= Oedipus::Connection.new(host: searchd_host[:host], port: searchd_host[:port])
|
42
|
-
|
43
|
-
@conn.query("SHOW TABLES").each do |idx|
|
44
|
-
@conn.query("SELECT id FROM #{idx['Index']}").each do |hash|
|
45
|
-
@conn.execute("DELETE FROM #{idx['Index']} WHERE id = #{hash['id']}")
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Write the sphinx.conf file, using #index_definiton.
|
51
|
-
#
|
52
|
-
# Sphinx will listen on localhost port 9399.
|
53
|
-
#
|
54
|
-
# Any string returned from #index_definition will be used to define one or more indexes.
|
55
|
-
def write_sphinx_conf
|
56
|
-
File.open(searchd_config, "wb") do |f|
|
57
|
-
f <<
|
58
|
-
<<-CONF.gsub(/^ {10}/m, "")
|
59
|
-
##
|
60
|
-
# This file is automatically generated during tests
|
61
|
-
##
|
62
|
-
|
63
|
-
index posts_rt
|
64
|
-
{
|
65
|
-
type = rt
|
66
|
-
path = #{data_dir}/index/posts_rt
|
67
|
-
|
68
|
-
rt_field = title
|
69
|
-
rt_field = body
|
70
|
-
|
71
|
-
rt_attr_uint = user_id
|
72
|
-
rt_attr_uint = views
|
73
|
-
rt_attr_string = state
|
74
|
-
}
|
75
|
-
|
76
|
-
searchd
|
77
|
-
{
|
78
|
-
compat_sphinxql_magics = 0
|
79
|
-
|
80
|
-
max_matches = 2000
|
81
|
-
pid_file = #{data_dir}/searchd.pid
|
82
|
-
listen = #{searchd_host[:host]}:#{searchd_host[:port]}:mysql41
|
83
|
-
workers = threads
|
84
|
-
log = #{data_dir}/searchd.log
|
85
|
-
query_log = #{data_dir}/searchd.log
|
86
|
-
binlog_path = #{data_dir}/binlog
|
87
|
-
}
|
88
|
-
CONF
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Start the sphinx daemon in a child process and return the PID.
|
93
|
-
#
|
94
|
-
# Output is redirected to searchd.out and searchd.err in the data dir.
|
95
|
-
def start_searchd
|
96
|
-
prepare_data_dirs
|
97
|
-
write_sphinx_conf
|
98
|
-
|
99
|
-
@searchd_pid = Process.spawn(
|
100
|
-
searchd, "--console", "-c", searchd_config,
|
101
|
-
out: "#{data_dir}/searchd.out",
|
102
|
-
err: "#{data_dir}/searchd.err"
|
103
|
-
)
|
104
|
-
sleep 1
|
105
|
-
end
|
106
|
-
|
107
|
-
# Stop an already running sphinx daemon and wait for it to shutdown.
|
108
|
-
def stop_searchd
|
109
|
-
Process.kill("TERM", @searchd_pid) && Process.wait
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def clean_data_dirs
|
115
|
-
clean_files("#{data_dir}/index/**/*")
|
116
|
-
clean_files("#{data_dir}/binlog/**/*")
|
117
|
-
clean_files("#{data_dir}/searchd.pid")
|
118
|
-
clean_files("#{data_dir}/searchd.out")
|
119
|
-
clean_files("#{data_dir}/searchd.err")
|
120
|
-
clean_files("#{data_dir}/sphinx.conf")
|
121
|
-
end
|
122
|
-
|
123
|
-
def searchd_host
|
124
|
-
{ host: "127.0.0.1", port: 9399 }
|
125
|
-
end
|
126
|
-
|
127
|
-
def searchd_config
|
128
|
-
"#{data_dir}/sphinx.conf"
|
129
|
-
end
|
130
|
-
|
131
|
-
def clean_files(path)
|
132
|
-
Dir[path].each { |f| File.delete(f) unless File.directory?(f) }
|
133
|
-
end
|
134
|
-
|
135
|
-
def data_dir
|
136
|
-
unless @data_dir
|
137
|
-
raise "Path to data directory unknown: call #set_data_dir during test setup"
|
138
|
-
else
|
139
|
-
@data_dir
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def searchd
|
144
|
-
unless @searchd
|
145
|
-
raise "Path to searchd unknown, perhaps you need to set the SEARCHD environment variable"
|
146
|
-
else
|
147
|
-
@searchd
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|