solr_cloud-connection 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{.env.local → .env.github} +2 -2
- data/CHANGELOG.md +16 -1
- data/README.md +65 -107
- data/Rakefile +16 -1
- data/compose.yml +2 -2
- data/{env.development → env.test} +0 -1
- data/lib/solr_cloud/alias.rb +25 -18
- data/lib/solr_cloud/collection.rb +92 -22
- data/lib/solr_cloud/configset.rb +21 -4
- data/lib/solr_cloud/connection/alias_admin.rb +43 -41
- data/lib/solr_cloud/connection/collection_admin.rb +58 -39
- data/lib/solr_cloud/connection/configset_admin.rb +41 -29
- data/lib/solr_cloud/connection/version.rb +1 -1
- data/lib/solr_cloud/connection.rb +52 -14
- data/lib/solr_cloud/errors.rb +2 -0
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e273d22bc3c74c27f96e2e4441695c47c8561634d339b8dabdc0d9c0075922e6
|
4
|
+
data.tar.gz: e208564f23b12ad6554a075caf48f65d57e7dfbe15b800e85eb639f4d2dc6791
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a1ba3738d5908c753c49b6f813b14465ddb4213d925aa7c075d6665c01229d0aecd59b8479bf5ae54f1d94511579876e7d3c392847f1c0845eb130a0f9c0897
|
7
|
+
data.tar.gz: 14f6c01885f6d97b477311099e4399b9e74c400fce40c42cdccb3e56a798df3f0ce8b0475aa57299ad3054681c4de059bf80908102a9b98b3b67cd14ecbfb50b
|
data/{.env.local → .env.github}
RENAMED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
-
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.3.0] - 2023-12-06
|
4
|
+
|
5
|
+
- Major overhaul of the interface to use more-explicit and less-confusing method names
|
6
|
+
- Remove code that tried to "version" collections and configsets, since it was dumb
|
7
|
+
- Get github actions working to run tests
|
8
|
+
- Make aliases even more of a paper-thin wrapper around collections, such that, e.g.
|
9
|
+
`coll = get_collection(alias_name)` will return the appropriate alias. Use
|
10
|
+
`coll.alias?` to determine if it's an alias or collection if that becomes important.
|
11
|
+
|
12
|
+
## [0.2.0] - 2023-12-01
|
13
|
+
|
14
|
+
- Added options `:date` and `:datetime` to the `version:` argument to `create_collection`
|
15
|
+
to automatically generate, e.g., "2023-12-01" or "2023-12-01-09-50-56"
|
16
|
+
- Added utility method `legal_solr_name?` to check for validity for collection names
|
2
17
|
|
3
18
|
## [0.1.0] - 2023-11-29
|
4
19
|
|
data/README.md
CHANGED
@@ -2,150 +2,108 @@
|
|
2
2
|
|
3
3
|
Do basic administrative tasks on a running Solr cloud instance, including:
|
4
4
|
|
5
|
+
* create (i.e., upload) a configSet when given a `conf` directory
|
5
6
|
* list, create, and delete configsets, collections, and aliases
|
6
7
|
* get basic version information for the running solr
|
7
8
|
* check on the health of individual collections
|
8
|
-
* treat an alias (mostly) as a collection
|
9
|
+
* treat an alias (mostly) as a collection
|
9
10
|
* TODO automatically generate methods to talk to defined requestHandlers
|
10
|
-
* TODO
|
11
|
+
* TODO Add something useful for configsets to do
|
12
|
+
|
13
|
+
In almost all cases, you can treat an alias to a collection like the underlying collection.
|
14
|
+
|
15
|
+
## A note about deleting things
|
16
|
+
|
17
|
+
Collections, aliases, and configsets all have a `#delete!` method. Keep in mind that solr
|
18
|
+
enforces a rule that nothing in-use can be deleted. This gem will throw appropriate errors
|
19
|
+
if you try to delete a configset that's being used by a collection, or try to delete
|
20
|
+
a collections that's pointed to by an alias.
|
11
21
|
|
12
22
|
## Caveats
|
13
23
|
|
14
|
-
* At this point the API is unstable
|
15
|
-
*
|
16
|
-
|
17
|
-
|
24
|
+
* At this point the API is unstable
|
25
|
+
* Performance is desperately, hilariously terrible. Solr has no sense of an atomic action and plenty of other ways
|
26
|
+
(e.g, the admin interface) to mess with things, so nothing is cached.
|
27
|
+
This means that individual actions can involve several round-trips to solr. If you're doing so much admin
|
28
|
+
that this becomes a bottleneck, you're well outside this gem's target case.
|
18
29
|
* While solr aliases can point to more than one collection at a time, this gem enforces one collection
|
19
30
|
per alias (although many aliases can point to the same collection)
|
20
31
|
|
21
32
|
## Usage
|
22
33
|
|
23
|
-
|
24
|
-
|
25
|
-
The connection object is the basis of all the other stuff. Everything will be created, directly
|
26
|
-
or indirectly, through the connection. While using the collection/alias/configset objects
|
27
|
-
is preferred, the connection on its own can do most anything. See SolrCloud::Connection for
|
28
|
-
the docs.
|
29
|
-
|
30
|
-
A simple connection is made if you pass in basic info, or you can create a faraday connection
|
31
|
-
and pass it in yourself.
|
34
|
+
The code below covers all the basics. See the docs for full sets of parameters, which errors are
|
35
|
+
thrown, etc.
|
32
36
|
|
33
37
|
```ruby
|
34
38
|
|
35
39
|
require "solr_cloud/connection"
|
36
40
|
|
37
|
-
|
38
|
-
# #=> <SolrCloud::Connection http://localhost:
|
41
|
+
server = SolrCloud::connect.new(url: "http://localhost:8023", username: "user", password: "password")
|
42
|
+
# #=> <SolrCloud::Connection http://localhost:8023/>
|
39
43
|
|
40
44
|
# or bring your own Faraday object
|
41
|
-
|
42
|
-
|
43
|
-
```
|
44
|
-
|
45
|
-
### Configsets
|
46
|
-
|
47
|
-
Configuration sets can be created by giving a path to the `conf` directory (with
|
48
|
-
`solrconfig.xml` and the schema and such) and a name.
|
49
|
-
|
50
|
-
```ruby
|
51
|
-
connect.configset_names #=> []
|
52
|
-
cset = connect.create_configset(name: "myconfig", confdir: "/path/to/yourconfig/conf")
|
53
|
-
|
54
|
-
# Get a list of existing configsets
|
55
|
-
arr_of_configsets_objects = @connect.configsets
|
56
|
-
arr_of_names_as_strings = @connect.configset_names
|
57
|
-
|
58
|
-
# Test and see if it exists by name
|
59
|
-
connect.configset?("myconfig") #=> true
|
60
|
-
|
61
|
-
# If it already exists, you can just grab it by name
|
62
|
-
|
63
|
-
def_config = connect.configset("_default")
|
45
|
+
# server = SolrCloud::connect.new_with_faraday(faraday_connection)
|
64
46
|
|
65
|
-
|
66
|
-
|
67
|
-
#=> WontOverwriteError
|
47
|
+
server.configset_names #=> ["_default"]
|
48
|
+
default = server.get_configset("_default") #=> <SolrCloud::Configset '_default' at http://localhost:8983>
|
68
49
|
|
69
|
-
#
|
70
|
-
|
50
|
+
# Create a new one by taking a directory, zipping it up, and sending it to solr
|
51
|
+
cset = server.create_configset(name: "my_awesome_configset_for_cars", confdir: "/path/to/mycore/conf")
|
52
|
+
server.configset_names #=> ["_default", "my_awesome_configset_for_cars"]
|
71
53
|
|
72
|
-
#
|
73
|
-
|
74
|
-
|
54
|
+
# That's a dumb name. We'll try again.
|
55
|
+
cset.delete!
|
56
|
+
cset = server.create_configset(name: "cars_config", confdir: "/path/to/mycore/conf")
|
75
57
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
Collections can be listed, tested for health and aliases, used to create an alias, and deleted.
|
81
|
-
|
82
|
-
```ruby
|
83
|
-
|
84
|
-
connect.collection_names #=> []
|
85
|
-
connect.create_collection(name: "mycoll", configset: "does_not_exist") #=> SolrCloud::NoSuchConfigSetError: Configset does_not_exist doesn't exist
|
86
|
-
mycoll = connect.create_collection(name: "mycoll", configset: "_default")
|
87
|
-
mycoll.name #=> "mycoll"
|
58
|
+
# Collections and aliases are mostly treated the same
|
59
|
+
server.collection_names #=> ["cars_v1", "cars_v2", "cars"] -- collections AND aliases
|
60
|
+
server.only_collection_names #=> ["cars_v1", "cars_v2"]
|
61
|
+
server.alias_names #=> ["cars"]
|
88
62
|
|
89
|
-
|
90
|
-
|
63
|
+
typo = server.get_collection("cars__V2") #=> nil, doesn't exist
|
64
|
+
cars_v2 = server.get_collection("cars_v2")
|
91
65
|
|
92
|
-
|
66
|
+
cars_v2.alive? #=> true
|
67
|
+
cars_v2.count #=> 133 -- we're assuming there's stuff in it.
|
93
68
|
|
94
|
-
arr_of_collection_objects = connect.collections
|
95
|
-
arr_of_names_as_strings = connect.collection_names
|
96
69
|
|
97
|
-
#
|
98
|
-
|
70
|
+
# Find out about its aliases, if any
|
71
|
+
cars_v2.alias? #=> false. It's a true collection
|
72
|
+
cars_v2.aliased? #=> true
|
73
|
+
cars_v2.aliases #=> [<SolrCloud::Alias "cars" (alias of "cars_v2")> ]
|
74
|
+
cars_v2.has_alias?("cars") #=> true
|
99
75
|
|
100
|
-
|
101
|
-
mycoll.healthy? #=> true. I'm not sure how these are different
|
76
|
+
cars_v2.delete! #=> SolrCloud::CollectionAliasedError: Collection 'cars_v2' can't be deleted; it's in use by aliases ["cars"]
|
102
77
|
|
103
|
-
|
78
|
+
# Make a new collection
|
79
|
+
cars_v3 = server.create_collection(name: "cars_v3", configset: "cars_config")
|
80
|
+
cars_v3.aliased? #=> false
|
81
|
+
cars_v3.count #=> 0
|
82
|
+
cars_v3.configset #=> <SolrCloud::Configset 'cars_config' at http://localhost:8023>
|
104
83
|
|
105
|
-
#
|
106
|
-
|
84
|
+
# Work directly with an alias as if it's a collection
|
85
|
+
cars = server.get_collection("cars")
|
86
|
+
cars.alias? #=> true
|
87
|
+
cars.collection #=> <SolrCloud::Collection 'cars_v2' (aliased by 'cars')>
|
107
88
|
|
108
|
-
#
|
109
|
-
|
110
|
-
|
89
|
+
# Make a new alias to v2
|
90
|
+
old_cars = cars_v2.alias_as("old_cars") #=> <SolrCloud::Alias "old_cars" (alias of "cars_v2")>
|
91
|
+
cars_v2.aliases #=> [<SolrCloud::Alias "cars" (alias of "cars_v2")>, <SolrCloud::Alias "old_cars" (alias of "cars_v2")>]
|
111
92
|
|
112
|
-
|
113
|
-
|
93
|
+
# Now lets point the "cars" alias at cars_v3
|
94
|
+
cars.switch_collection_to cars_v3
|
114
95
|
|
115
|
-
|
116
|
-
|
117
|
-
mycoll.collection #=>
|
118
|
-
mycoll.collection.get("path/from/connection/url", arg1: "One", arg2: "Two")
|
96
|
+
cars.collection.name #=> "cars_v3"
|
97
|
+
cars_v2.alias_names #=> ["old_cars"]
|
119
98
|
|
120
|
-
#
|
121
|
-
|
122
|
-
myalias.delete!
|
123
|
-
|
124
|
-
mycoll.delete!
|
99
|
+
# cars_v1 isn't doing anything for us anymore. Ditch it.
|
100
|
+
cars_v1.delete!
|
125
101
|
|
126
102
|
```
|
127
103
|
|
128
|
-
|
129
|
-
|
130
|
-
In all the important ways, aliases can be treated like collections. Here are the exceptions.
|
104
|
+
## Documentation
|
131
105
|
|
132
|
-
|
133
|
-
|
134
|
-
# You can create an alias from the collection you're aliasing
|
135
|
-
myalias = mycoll.alias_as("myalias")
|
136
|
-
|
137
|
-
# Ask the connection object if it exists, and get it
|
138
|
-
connect.alias?("myalias") #=> true
|
139
|
-
myalias = connect.alias("myalias")
|
140
|
-
|
141
|
-
# As this object if it's an alias, as opposed to a collection
|
142
|
-
myalias.alias? #=> true
|
143
|
-
|
144
|
-
# Set the collection this alias points to, removing its link from its existing collection
|
145
|
-
myalias.collection = my_other_collection #=> sets myalias to point at my_other_collection
|
146
|
-
|
147
|
-
myalias.delete!
|
148
|
-
```
|
106
|
+
Run `bundle exec rake docs` to generate the documentation in `docs/`
|
149
107
|
|
150
108
|
## Installation
|
151
109
|
|
@@ -168,4 +126,4 @@ This repository is set up to run tests under docker.
|
|
168
126
|
|
169
127
|
## Contributing
|
170
128
|
|
171
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/mlibrary/solr_cloud-
|
129
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/mlibrary/solr_cloud-connection.
|
data/Rakefile
CHANGED
@@ -7,4 +7,19 @@ RSpec::Core::RakeTask.new(:spec)
|
|
7
7
|
|
8
8
|
require "standard/rake"
|
9
9
|
|
10
|
-
task default: %i[spec standard]
|
10
|
+
task default: %i[spec standard docs]
|
11
|
+
task docs: %i[yard]
|
12
|
+
|
13
|
+
require 'yard'
|
14
|
+
|
15
|
+
YARD::Rake::YardocTask.new do |t|
|
16
|
+
t.files = ["lib/**/*.rb"] # optional
|
17
|
+
t.options = [
|
18
|
+
"-mmarkdown",
|
19
|
+
"--embed-mixin", "SolrCloud::Connection::CollectionAdmin",
|
20
|
+
"--embed-mixin", "SolrCloud::Connection::ConfigsetAdmin",
|
21
|
+
"--embed-mixin", "SolrCloud::Connection::AliasAdmin",
|
22
|
+
"--hide-void-return"
|
23
|
+
]
|
24
|
+
# t.stats_options = ["--list-undoc"] # optional
|
25
|
+
end
|
data/compose.yml
CHANGED
@@ -9,13 +9,13 @@ services:
|
|
9
9
|
- gem_cache:/gems
|
10
10
|
env_file:
|
11
11
|
- .env
|
12
|
-
- env.
|
12
|
+
- env.test
|
13
13
|
command: "tail -f /dev/null"
|
14
14
|
|
15
15
|
solr:
|
16
16
|
build: spec/data/solr_docker/.
|
17
17
|
ports:
|
18
|
-
- "
|
18
|
+
- "8983:8983"
|
19
19
|
environment:
|
20
20
|
- ZK_HOST=zoo:2181
|
21
21
|
depends_on:
|
data/lib/solr_cloud/alias.rb
CHANGED
@@ -2,51 +2,58 @@
|
|
2
2
|
|
3
3
|
module SolrCloud
|
4
4
|
# An alias can mostly be just treated as a collection. It will identify itself as an alias if you
|
5
|
-
# call #alias
|
5
|
+
# call #alias?, and it can return and change the underlying collection it points to.
|
6
6
|
|
7
7
|
# An alias shouldn't be created directly. Rather, get an existing one with
|
8
8
|
# Connection#alias, or from a collection, or create one with
|
9
9
|
# Collection#alias_as
|
10
10
|
class Alias < Collection
|
11
11
|
# An alias is, shockingly, an alias. Convenience to differentiate aliases from collections.
|
12
|
-
# @see SolrCloud::Connection#
|
12
|
+
# @see SolrCloud::Connection#get_alias?
|
13
13
|
def alias?
|
14
14
|
true
|
15
15
|
end
|
16
16
|
|
17
|
-
# Delete this alias
|
18
|
-
# @return [
|
17
|
+
# Delete this alias. Will be a no-op if it doesn't exist.
|
18
|
+
# @return [Connection] the connection
|
19
19
|
def delete!
|
20
|
-
|
21
|
-
connection.
|
22
|
-
|
20
|
+
return connection unless exist?
|
21
|
+
connection.get("solr/admin/collections", action: "DELETEALIAS", name: name)
|
22
|
+
connection
|
23
|
+
end
|
24
|
+
|
25
|
+
# Does this alias still exist?
|
26
|
+
def exist?
|
27
|
+
connection.alias_names.include?(name)
|
23
28
|
end
|
24
29
|
|
25
30
|
# Get the collection this alias points to.
|
26
31
|
# In real life, Solr will allow an alias to point to more than one collection. Functionality
|
27
32
|
# for this might be added at some point
|
28
|
-
# @return [
|
33
|
+
# @return [Collection]
|
29
34
|
def collection
|
30
|
-
connection.
|
35
|
+
connection.alias_map[name].collection
|
31
36
|
end
|
32
37
|
|
33
38
|
# Redefine what collection this alias points to
|
34
39
|
# This is equivalent to dropping/re-adding the alias, or calling connection.create_alias with `force: true`
|
35
40
|
# @param coll [String, Collection] either the name of the collection, or a collection object itself
|
36
41
|
# @return [Collection] the now-current collection
|
37
|
-
def
|
42
|
+
def switch_collection_to(coll)
|
38
43
|
collect_name = case coll
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
raise NoSuchCollectionError unless connection.
|
44
|
+
when String
|
45
|
+
coll
|
46
|
+
when Collection
|
47
|
+
coll.name
|
48
|
+
else
|
49
|
+
raise "Alias#switch_collection_to only takes a name(string) or a collection, not '#{coll}'"
|
50
|
+
end
|
51
|
+
raise NoSuchCollectionError unless connection.has_collection?(collect_name)
|
47
52
|
connection.create_alias(name: name, collection_name: collect_name, force: true)
|
48
53
|
end
|
49
54
|
|
55
|
+
alias_method :collection=, :switch_collection_to
|
56
|
+
|
50
57
|
# Get basic information on the underlying collection, so inherited methods that
|
51
58
|
# use it (e.g., #healthy?) will work.
|
52
59
|
# @overload info()
|
@@ -1,12 +1,42 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "solr_cloud/connection"
|
4
|
+
require "forwardable"
|
4
5
|
|
5
6
|
module SolrCloud
|
6
7
|
# A Collection provides basic services on the collection -- checking its health,
|
7
8
|
# creating or reporting aliases, and deleting itself.
|
8
9
|
class Collection
|
9
|
-
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
# Forward the HTTP verbs to the underlying connection
|
14
|
+
|
15
|
+
# @!method get
|
16
|
+
# Forwarded on to the underlying SolrCloud connection
|
17
|
+
# @see SolrCloud::Connection#get
|
18
|
+
def_delegator :@connection, :get
|
19
|
+
|
20
|
+
# @!method post
|
21
|
+
# Forwarded on to the underlying SolrCloud connection
|
22
|
+
# @see SolrCloud::Connection#post
|
23
|
+
def_delegator :@connection, :post
|
24
|
+
|
25
|
+
# @!method delete
|
26
|
+
# Forwarded on to the underlying SolrCloud connection
|
27
|
+
# @see SolrCloud::Connection#delete
|
28
|
+
def_delegator :@connection, :delete
|
29
|
+
|
30
|
+
# @!method put
|
31
|
+
# Forwarded on to the underlying SolrCloud connection
|
32
|
+
# @see SolrCloud::Connection#put
|
33
|
+
def_delegator :@connection, :put
|
34
|
+
|
35
|
+
# @return [SolrCloud::Connection] the underlying SolrCloud connection
|
36
|
+
attr_reader :name
|
37
|
+
|
38
|
+
# @return The name of the get_collection
|
39
|
+
attr_reader :connection
|
10
40
|
|
11
41
|
# In general, users shouldn't use Collection.new; instead, use
|
12
42
|
# connection.create_collection(name: "coll_name", configset: "existing_configset_name")
|
@@ -14,22 +44,28 @@ module SolrCloud
|
|
14
44
|
# @param [String] name The name of the (already existing) collection
|
15
45
|
# @param [SolrCloud::Connection] connection Connection to the solr "root" (http://blah:8888/)
|
16
46
|
def initialize(name:, connection:)
|
17
|
-
# raise NoSuchCollectionError.new("No collection #{name}") unless connection.
|
47
|
+
# raise NoSuchCollectionError.new("No collection #{name}") unless connection.has_collection?(name)
|
18
48
|
@connection = connection.dup
|
19
49
|
@name = name
|
20
50
|
@sp = "/solr/#{name}"
|
21
51
|
end
|
22
52
|
|
23
|
-
# Delete this collection.
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# @return [Connection] The underlying SolrCloud::Connection
|
53
|
+
# Delete this collection. Will no-op if the collection somehow doesn't still exist (because it was
|
54
|
+
# deleted via a different method, such as through the API)
|
55
|
+
# @return [Connection] The connection object used to create this collection object
|
27
56
|
def delete!
|
28
|
-
|
29
|
-
|
57
|
+
return connection unless exist?
|
58
|
+
raise CollectionAliasedError.new("Cannot delete collection #{name}; it has alias(s) #{alias_names.join(", ")}") if aliased?
|
59
|
+
connection.get("solr/admin/collections", { action: "DELETE", name: name })
|
30
60
|
connection
|
31
61
|
end
|
32
62
|
|
63
|
+
# Does this collection still exist?
|
64
|
+
# @return [Boolean]
|
65
|
+
def exist?
|
66
|
+
connection.only_collection_names.include?(name)
|
67
|
+
end
|
68
|
+
|
33
69
|
# Check to see if the collection is alive
|
34
70
|
# @return [Boolean]
|
35
71
|
def alive?
|
@@ -38,11 +74,9 @@ module SolrCloud
|
|
38
74
|
false
|
39
75
|
end
|
40
76
|
|
41
|
-
alias_method :exist?, :alive?
|
42
|
-
|
43
77
|
# Is this an alias?
|
44
78
|
# Putting this in here breaks all sorts of isolation principles,
|
45
|
-
# but being able to call #
|
79
|
+
# but being able to call #get_alias? on anything collection-like is
|
46
80
|
# convenient
|
47
81
|
def alias?
|
48
82
|
false
|
@@ -63,7 +97,7 @@ module SolrCloud
|
|
63
97
|
# A (possibly empty) list of aliases targeting this collection
|
64
98
|
# @return [Array<SolrCloud::Alias>] list of aliases that point to this collection
|
65
99
|
def aliases
|
66
|
-
connection.
|
100
|
+
connection.alias_map.select { |_alias_name, ac| ac.collection.name == name }.values.map(&:alias)
|
67
101
|
end
|
68
102
|
|
69
103
|
# The names of the aliases that point to this collection
|
@@ -72,10 +106,26 @@ module SolrCloud
|
|
72
106
|
aliases.map(&:name)
|
73
107
|
end
|
74
108
|
|
109
|
+
# Does this collection have at least one alias?
|
110
|
+
# @return [Boolean] whether or not it has an alias
|
111
|
+
def aliased?
|
112
|
+
!aliases.empty?
|
113
|
+
end
|
114
|
+
|
115
|
+
# Do we have an alias of the given name?
|
75
116
|
# Get a specific alias by name
|
76
|
-
# @param
|
77
|
-
|
78
|
-
|
117
|
+
# @param alias_name [String] name of the alias
|
118
|
+
# @return [Boolean]
|
119
|
+
def has_alias?(alias_name)
|
120
|
+
alias_names.include?(alias_name)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Get an alias that points to this collection by name, or nil if not found
|
124
|
+
# @param alias_name [String] name of the alias
|
125
|
+
# @return [Alias, nil] The alias object, or nil if not found
|
126
|
+
def get_alias(alias_name)
|
127
|
+
return nil unless has_alias?(alias_name)
|
128
|
+
connection.get_alias(alias_name)
|
79
129
|
end
|
80
130
|
|
81
131
|
# Create an alias for this collection. Always forces an overwrite unless you tell it not to
|
@@ -86,9 +136,6 @@ module SolrCloud
|
|
86
136
|
connection.create_alias(name: alias_name, collection_name: name, force: true)
|
87
137
|
end
|
88
138
|
|
89
|
-
alias_method :alias_to, :alias_as
|
90
|
-
alias_method :create_alias, :alias_as
|
91
|
-
|
92
139
|
# Send a commit (soft if unspecified)
|
93
140
|
# @return self
|
94
141
|
def commit(hard: false)
|
@@ -106,13 +153,36 @@ module SolrCloud
|
|
106
153
|
Configset.new(name: info["configName"], connection: connection)
|
107
154
|
end
|
108
155
|
|
156
|
+
# Add a document or array of documents
|
157
|
+
# @todo Gotta check for errors and such!
|
158
|
+
# @param docs [Hash, Array<Hash>] One or more documents to add
|
159
|
+
# @return self
|
160
|
+
|
161
|
+
def add(docs)
|
162
|
+
docarray = if docs === Array
|
163
|
+
docs
|
164
|
+
else
|
165
|
+
[docs]
|
166
|
+
end
|
167
|
+
post("solr/#{name}/update/") do |r|
|
168
|
+
r.body = docarray
|
169
|
+
end
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get a count of how many documents are in the index
|
174
|
+
# @return [Fixnum] the number of documents
|
175
|
+
def count
|
176
|
+
get("solr/#{name}/select", q: "*:*").body["response"]["numFound"]
|
177
|
+
end
|
178
|
+
|
109
179
|
def inspect
|
110
180
|
anames = alias_names
|
111
181
|
astring = if anames.empty?
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
182
|
+
""
|
183
|
+
else
|
184
|
+
" (aliased by #{anames.map { |x| "'#{x}'" }.join(", ")})"
|
185
|
+
end
|
116
186
|
"<#{self.class} '#{name}'#{astring}>"
|
117
187
|
end
|
118
188
|
|
data/lib/solr_cloud/configset.rb
CHANGED
@@ -7,7 +7,12 @@ module SolrCloud
|
|
7
7
|
# throw an error if that's an illegal operation (because a collection is
|
8
8
|
# using it)
|
9
9
|
class Configset
|
10
|
-
|
10
|
+
|
11
|
+
# @return [String] the name of this configset
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
# @return [Connection] the connection object used to build this configset object
|
15
|
+
attr_reader :connection
|
11
16
|
|
12
17
|
def initialize(name:, connection:)
|
13
18
|
@name = name
|
@@ -15,11 +20,23 @@ module SolrCloud
|
|
15
20
|
end
|
16
21
|
|
17
22
|
# Delete this configset.
|
18
|
-
# @see
|
23
|
+
# @see Connection#delete_configset
|
19
24
|
# @return The underlying connection
|
20
25
|
def delete!
|
21
|
-
|
22
|
-
|
26
|
+
connection.delete_configset(name)
|
27
|
+
connection
|
28
|
+
end
|
29
|
+
|
30
|
+
# Which collections use this configset?
|
31
|
+
# @return [Array<Collection>] The collections defined to use this configset
|
32
|
+
def used_by
|
33
|
+
connection.only_collections.select { |coll| coll.configset.name == name }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Are there any collections currently using this configset?
|
37
|
+
# @return [Boolean]
|
38
|
+
def in_use?
|
39
|
+
!used_by.empty?
|
23
40
|
end
|
24
41
|
|
25
42
|
def inspect
|
@@ -5,56 +5,41 @@ module SolrCloud
|
|
5
5
|
# methods having to do with aliases, to be included by the connection object.
|
6
6
|
# These are split out only to make it easier to deal with them.
|
7
7
|
module AliasAdmin
|
8
|
+
|
9
|
+
# A simple data-class to pair an alias with its collection
|
8
10
|
AliasCollectionPair = Struct.new(:alias, :collection)
|
9
11
|
|
10
|
-
# Create an alias for the given collection name
|
11
|
-
#
|
12
|
+
# Create an alias for the given collection name.
|
13
|
+
#
|
14
|
+
# In general, prefer {Collection#alias_as} instead of
|
15
|
+
# running everything through the connection object.
|
12
16
|
# @param name [String] Name of the new alias
|
13
17
|
# @param collection_name [String] name of the collection
|
14
18
|
# @param force [Boolean] whether to overwrite an existing alias
|
15
|
-
# @raise [WontOverwriteError] if the alias exists and force isn't true
|
16
19
|
# @raise [NoSuchCollectionError] if the collections isn't found
|
17
20
|
# @return [Alias] the newly-created alias
|
18
21
|
def create_alias(name:, collection_name:, force: false)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
unless legal_solr_name?(name)
|
23
|
+
raise IllegalNameError.new("'#{name}' is not a valid solr alias name. Use only ASCII letters/numbers, dash, and underscore")
|
24
|
+
end
|
25
|
+
raise NoSuchCollectionError.new("Can't find collection #{collection_name}") unless has_collection?(collection_name)
|
26
|
+
if has_alias?(name) && !force
|
27
|
+
raise WontOverwriteError.new("Alias '#{name}' already points to collection '#{self.get_alias(name).collection.name}'; won't overwrite without force: true")
|
22
28
|
end
|
23
29
|
connection.get("solr/admin/collections", action: "CREATEALIAS", name: name, collections: collection_name)
|
24
|
-
|
30
|
+
get_alias(name)
|
25
31
|
end
|
26
32
|
|
27
33
|
# Is there an alias with this name?
|
28
34
|
# @return [Boolean]
|
29
|
-
def
|
35
|
+
def has_alias?(name)
|
30
36
|
alias_names.include? name
|
31
37
|
end
|
32
38
|
|
33
|
-
# Delete the alias
|
34
|
-
# @param name [String] Name of the alias to delete
|
35
|
-
# @return [SolrCloud::Connection]
|
36
|
-
def delete_alias(name)
|
37
|
-
connection.get("solr/admin/collections", action: "DELETEALIAS", name: name)
|
38
|
-
end
|
39
|
-
|
40
|
-
# The "raw" alias map, which just maps alias names to collection names
|
41
|
-
# @return [Hash<String, String>]
|
42
|
-
def raw_alias_map
|
43
|
-
connection.get("solr/admin/collections", action: "LISTALIASES").body["aliases"]
|
44
|
-
end
|
45
|
-
|
46
|
-
# Get the aliases and create a map of the form
|
47
|
-
# @return [Hash<String,Alias>] A hash mapping alias names to alias objects
|
48
|
-
def alias_map
|
49
|
-
raw_alias_map.keys.each_with_object({}) do |alias_name, h|
|
50
|
-
h[alias_name] = SolrCloud::Alias.new(name: alias_name, connection: self)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
39
|
# List of alias objects
|
55
40
|
# @return [Array<SolrCloud::Alias>] List of aliases
|
56
41
|
def aliases
|
57
|
-
alias_map.values
|
42
|
+
alias_map.values.map(&:alias)
|
58
43
|
end
|
59
44
|
|
60
45
|
# List of alias names
|
@@ -63,23 +48,40 @@ module SolrCloud
|
|
63
48
|
alias_map.keys
|
64
49
|
end
|
65
50
|
|
66
|
-
# Get an alias object for the given name
|
51
|
+
# Get an alias object for the given name, erroring out if not found
|
52
|
+
# @param name [String] the name of the existing alias
|
53
|
+
# @return [Alias, nil] The alias if found, otherwise nil
|
54
|
+
def get_alias(name)
|
55
|
+
return nil unless has_alias?(name)
|
56
|
+
alias_map[name].alias
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get an alias object for the given name, erroring out if not found
|
67
60
|
# @param name [String] the name of the existing alias
|
68
61
|
# @raise [SolrCloud::NoSuchAliasError] if it doesn't exist
|
69
62
|
# @return [SolrCloud::Alias]
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
am[name]
|
63
|
+
def get_alias!(name)
|
64
|
+
raise NoSuchAliasError unless has_alias?(name)
|
65
|
+
get_alias(name)
|
74
66
|
end
|
75
67
|
|
76
|
-
# Get the
|
77
|
-
# @
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
68
|
+
# Get the aliases and create a map of the form AliasName -> AliasObject
|
69
|
+
# @return [Hash<String,Alias>] A hash mapping alias names to alias objects
|
70
|
+
def alias_map
|
71
|
+
raw_alias_map.keys.each_with_object({}) do |alias_name, h|
|
72
|
+
a = Alias.new(name: alias_name, connection: self)
|
73
|
+
c = Collection.new(name: raw_alias_map[alias_name], connection: self)
|
74
|
+
h[alias_name] = AliasCollectionPair.new(a, c)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# The "raw" alias map, which just maps alias names to collection names
|
79
|
+
# @return [Hash<String, String>]
|
80
|
+
def raw_alias_map
|
81
|
+
connection.get("solr/admin/collections", action: "LISTALIASES").body["aliases"]
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
|
+
|
87
|
+
|
@@ -2,79 +2,98 @@
|
|
2
2
|
|
3
3
|
module SolrCloud
|
4
4
|
class Connection
|
5
|
-
# methods having to do with
|
5
|
+
# methods having to do with collections, to be included by the connection object.
|
6
6
|
# These are split out only to make it easier to deal with them.
|
7
|
+
#
|
8
|
+
# For almost everything in here, we treat aliases like collections -- calls to #collections,
|
9
|
+
# #has_collection?, #collection, etc. will respond to, and return, and alias if there is one.
|
10
|
+
# The idea is that you shouldn't need to know if something is an alias or a collection
|
11
|
+
# until it's relevant
|
7
12
|
module CollectionAdmin
|
8
|
-
# Create a new collection
|
13
|
+
# Create and return a new collection.
|
9
14
|
# @param name [String] Name for the new collection
|
10
|
-
# @param configset [String] name of the configset to use for this collection
|
11
|
-
# @param version [String] A "version" which will be appended to the name following an underscore, if given.
|
12
|
-
# Useful for testing and cronjobs.
|
15
|
+
# @param configset [String, Configset] (name of) the configset to use for this collection
|
13
16
|
# @param shards [Integer]
|
14
17
|
# @param replication_factor [Integer]
|
15
|
-
# @
|
18
|
+
# @raise [IllegalNameError]
|
16
19
|
# @raise [NoSuchConfigSetError] if the named configset doesn't exist
|
17
20
|
# @raise [WontOverwriteError] if the collection already exists
|
18
21
|
# @return [Collection] the collection created
|
19
|
-
def create_collection(name:, configset:,
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
name
|
22
|
+
def create_collection(name:, configset:, shards: 1, replication_factor: 1)
|
23
|
+
|
24
|
+
unless legal_solr_name?(name)
|
25
|
+
raise IllegalNameError.new("'#{name}' is not a valid solr name. Use only ASCII letters/numbers, dash, and underscore")
|
24
26
|
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
configset_name = case configset
|
29
|
+
when Configset
|
30
|
+
configset.name
|
31
|
+
else
|
32
|
+
configset.to_s
|
33
|
+
end
|
34
|
+
raise WontOverwriteError.new("Collection #{name} already exists") if has_collection?(name)
|
35
|
+
raise NoSuchConfigSetError.new("Configset '#{configset_name}' doesn't exist") unless has_configset?(configset_name)
|
28
36
|
|
29
37
|
args = {
|
30
38
|
:action => "CREATE",
|
31
|
-
:name =>
|
39
|
+
:name => name,
|
32
40
|
:numShards => shards,
|
33
41
|
:replicationFactor => replication_factor,
|
34
|
-
"collection.configName" =>
|
42
|
+
"collection.configName" => configset_name
|
35
43
|
}
|
36
44
|
connection.get("solr/admin/collections", args)
|
37
|
-
|
45
|
+
get_collection(name)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get a list of _only_ collections, as opposed to the mix of collections and aliases we
|
49
|
+
# usually do.
|
50
|
+
def only_collections
|
51
|
+
connection.get("api/collections").body["collections"].map { |c| Collection.new(name: c, connection: self) }
|
38
52
|
end
|
39
53
|
|
40
|
-
#
|
41
|
-
# @return [Array<
|
54
|
+
# The names of only connections (and not aliases). Useful as a utility.
|
55
|
+
# @return [Array<String>] the names of the connections
|
56
|
+
def only_collection_names
|
57
|
+
only_collections.map(&:name)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get a list of collections (and aliases)
|
61
|
+
# @return [Array<Collection, Alias>] possibly empty list of collection and alias objects
|
42
62
|
def collections
|
43
|
-
|
63
|
+
only_collections.union(aliases)
|
44
64
|
end
|
45
65
|
|
46
|
-
# A list of the names of existing collections
|
47
|
-
# @return [Array<String>] the collection names, or empty array if there are none
|
66
|
+
# A list of the names of existing collections and aliases
|
67
|
+
# @return [Array<String>] the collection/alias names, or empty array if there are none
|
48
68
|
def collection_names
|
49
|
-
|
69
|
+
collections.map(&:name)
|
50
70
|
end
|
51
71
|
|
52
72
|
# @param name [String] name of the collection to check on
|
53
73
|
# @return [Boolean] Whether a collection with the passed name exists
|
54
|
-
def
|
74
|
+
def has_collection?(name)
|
55
75
|
collection_names.include? name
|
56
76
|
end
|
57
77
|
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# @
|
61
|
-
|
62
|
-
|
63
|
-
if
|
64
|
-
|
78
|
+
# Get a collection object specifically for the named collection
|
79
|
+
# @param collection_name [String] name of the (already existing) collection
|
80
|
+
# @return [Collection, Alias, nil] The collection or alias if found, nil if not
|
81
|
+
def get_collection(collection_name)
|
82
|
+
return nil unless has_collection?(collection_name)
|
83
|
+
if only_collection_names.include?(collection_name)
|
84
|
+
Collection.new(name: collection_name, connection: self)
|
85
|
+
else
|
86
|
+
get_alias(collection_name)
|
65
87
|
end
|
66
|
-
self
|
67
|
-
rescue Faraday::BadRequestError
|
68
|
-
raise SolrCloud::CollectionAliasedError.new("Collection '#{name}' can't be deleted; it's in use by aliases #{collection(name).alias_names}")
|
69
88
|
end
|
70
89
|
|
71
|
-
# Get a connection object
|
90
|
+
# Get a connection/alias object, throwing an error if it's not found
|
72
91
|
# @param collection_name [String] name of the (already existing) collection
|
73
|
-
# @return [
|
74
|
-
# @raise [NoSuchCollectionError] if the collection doesn't exist
|
75
|
-
def
|
76
|
-
raise NoSuchCollectionError.new("Collection '#{collection_name}' not found") unless
|
77
|
-
|
92
|
+
# @return [Collection, Alias] The collection or alias
|
93
|
+
# @raise [NoSuchCollectionError] if the collection/alias doesn't exist
|
94
|
+
def get_collection!(collection_name)
|
95
|
+
raise NoSuchCollectionError.new("Collection '#{collection_name}' not found") unless has_collection?(collection_name)
|
96
|
+
get_collection(collection_name)
|
78
97
|
end
|
79
98
|
end
|
80
99
|
end
|
@@ -7,6 +7,34 @@ module SolrCloud
|
|
7
7
|
# methods having to do with configsets, to be included by the connection object.
|
8
8
|
# These are split out only to make it easier to deal with them.
|
9
9
|
module ConfigsetAdmin
|
10
|
+
|
11
|
+
# Given the path to a solr configuration "conf" directory (i.e., the one with
|
12
|
+
# solrconfig.xml in it), zip it up and send it to solr as a new configset.
|
13
|
+
# @param name [String] Name to give the new configset
|
14
|
+
# @param confdir [String, Pathname] Path to the solr configuration "conf" directory
|
15
|
+
# @param force [Boolean] Whether or not to overwrite an existing configset if there is one
|
16
|
+
# @raise [WontOverwriteError] if the configset already exists and "force" is false
|
17
|
+
# @return [Configset] the configset created
|
18
|
+
def create_configset(name:, confdir:, force: false)
|
19
|
+
config_set_name = name
|
20
|
+
unless legal_solr_name?(config_set_name)
|
21
|
+
raise IllegalNameError.new("'#{config_set_name}' is not a valid solr configset name. Use only ASCII letters/numbers, dash, and underscore")
|
22
|
+
end
|
23
|
+
|
24
|
+
if has_configset?(config_set_name) && !force
|
25
|
+
raise WontOverwriteError.new("Won't replace configset #{config_set_name} unless 'force: true' passed ")
|
26
|
+
end
|
27
|
+
zfile = "#{Dir.tmpdir}/solr_add_configset_#{name}_#{Time.now.hash}.zip"
|
28
|
+
z = ZipFileGenerator.new(confdir, zfile)
|
29
|
+
z.write
|
30
|
+
@connection.put("api/cluster/configs/#{config_set_name}") do |req|
|
31
|
+
req.body = File.binread(zfile)
|
32
|
+
end
|
33
|
+
# TODO: Error check in here somewhere
|
34
|
+
FileUtils.rm(zfile, force: true)
|
35
|
+
get_configset(name)
|
36
|
+
end
|
37
|
+
|
10
38
|
# Get a list of the already-defined configSets
|
11
39
|
# @return [Array<Configset>] possibly empty list of configSets
|
12
40
|
def configsets
|
@@ -18,47 +46,29 @@ module SolrCloud
|
|
18
46
|
connection.get("api/cluster/configs").body["configSets"]
|
19
47
|
end
|
20
48
|
|
21
|
-
alias_method :configurations, :configsets
|
22
|
-
|
23
49
|
# Check to see if a configset is defined
|
24
50
|
# @param name [String] Name of the configSet
|
25
51
|
# @return [Boolean] Whether a configset with that name exists
|
26
|
-
def
|
52
|
+
def has_configset?(name)
|
27
53
|
configset_names.include? name.to_s
|
28
54
|
end
|
29
55
|
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
# @param confdir [String, Pathname] Path to the solr configuration "conf" directory
|
34
|
-
# @param force [Boolean] Whether or not to overwrite an existing configset if there is one
|
35
|
-
# @param version [String] A "version" which will be appended to the name if given. Useful for
|
36
|
-
# testing and cronjobs.
|
37
|
-
# @raise [WontOverwriteError] if the configset already exists and "force" is false
|
38
|
-
# @return [String] the name of the configset created
|
39
|
-
def create_configset(name:, confdir:, force: false, version: "")
|
40
|
-
config_set_name = name + version.to_s
|
41
|
-
if configset?(config_set_name) && !force
|
42
|
-
raise WontOverwriteError.new("Won't replace configset #{config_set_name} unless 'force: true' passed ")
|
43
|
-
end
|
44
|
-
zfile = "#{Dir.tmpdir}/solr_add_configset_#{name}_#{Time.now.hash}.zip"
|
45
|
-
z = ZipFileGenerator.new(confdir, zfile)
|
46
|
-
z.write
|
47
|
-
@raw_connection.put("api/cluster/configs/#{config_set_name}") do |req|
|
48
|
-
req.body = File.binread(zfile)
|
49
|
-
end
|
50
|
-
# TODO: Error check in here somewhere
|
51
|
-
FileUtils.rm(zfile, force: true)
|
52
|
-
config_set_name
|
56
|
+
# Get an existing configset
|
57
|
+
def get_configset(name)
|
58
|
+
Configset.new(name: name, connection: self)
|
53
59
|
end
|
54
60
|
|
55
61
|
# Remove the configuration set with the given name. No-op if the
|
56
|
-
# configset doesn't actually exist.
|
57
|
-
#
|
62
|
+
# configset doesn't actually exist. Test with {#has_configset?} and
|
63
|
+
# {Configset#in_use?} manually if need be.
|
64
|
+
#
|
65
|
+
# In general, prefer using {Configset#delete!} instead of running everything
|
66
|
+
# through the connection object.
|
67
|
+
# @param [String] name The name of the configuration set
|
58
68
|
# @raise [InUseError] if the configset can't be deleted because it's in use by a live collection
|
59
69
|
# @return [Connection] self
|
60
70
|
def delete_configset(name)
|
61
|
-
if
|
71
|
+
if has_configset? name
|
62
72
|
connection.delete("api/cluster/configs/#{name}")
|
63
73
|
end
|
64
74
|
self
|
@@ -73,6 +83,8 @@ module SolrCloud
|
|
73
83
|
|
74
84
|
# Pulled from the examples for rubyzip. No idea why it's not just a part
|
75
85
|
# of the normal interface, but I guess I'm not one to judge.
|
86
|
+
#
|
87
|
+
# Code taken wholesale from https://github.com/rubyzip/rubyzip/blob/master/samples/example_recursive.rb
|
76
88
|
class ZipFileGenerator
|
77
89
|
# Initialize with the directory to zip and the location of the output archive.
|
78
90
|
def initialize(input_dir, output_file)
|
@@ -28,9 +28,36 @@ module SolrCloud
|
|
28
28
|
include CollectionAdmin
|
29
29
|
include AliasAdmin
|
30
30
|
|
31
|
-
|
31
|
+
# @return [String] String representation of the URL to solr
|
32
|
+
attr_reader :url
|
32
33
|
|
33
|
-
|
34
|
+
# @return [#info] The logger
|
35
|
+
attr_reader :logger
|
36
|
+
|
37
|
+
# @return [Faraday::Connection] the underlying Faraday connection
|
38
|
+
attr_reader :connection
|
39
|
+
|
40
|
+
# let the underlying connection handle HTTP verbs
|
41
|
+
|
42
|
+
# @!method get
|
43
|
+
# Forwarded on to the underlying Faraday connection
|
44
|
+
# @see Faraday::Connection.get
|
45
|
+
def_delegator :@connection, :get
|
46
|
+
|
47
|
+
# @!method post
|
48
|
+
# Forwarded on to the underlying Faraday connection
|
49
|
+
# @see Faraday::Connection.post
|
50
|
+
def_delegator :@connection, :post
|
51
|
+
|
52
|
+
# @!method delete
|
53
|
+
# Forwarded on to the underlying Faraday connection
|
54
|
+
# @see Faraday::Connection.delete
|
55
|
+
def_delegator :@connection, :delete
|
56
|
+
|
57
|
+
# @!method put
|
58
|
+
# Forwarded on to the underlying Faraday connection
|
59
|
+
# @see Faraday::Connection.put
|
60
|
+
def_delegator :@connection, :put
|
34
61
|
|
35
62
|
# Create a new connection to talk to solr
|
36
63
|
# @param url [String] URL to the "root" of the solr installation. For a default solr setup, this will
|
@@ -38,21 +65,21 @@ module SolrCloud
|
|
38
65
|
# @param user [String] username for basic auth, if you're using it
|
39
66
|
# @param password [String] password for basic auth, if you're using it
|
40
67
|
# @param logger [#info, :off, nil] An existing logger to pass in. The symbol ":off" means
|
41
|
-
#
|
68
|
+
# don't do logging. If left undefined, will create a standard ruby logger to $stdout
|
42
69
|
# @param adapter [Symbol] The underlying http library to use within Faraday
|
43
70
|
def initialize(url:, user: nil, password: nil, logger: nil, adapter: :httpx)
|
44
71
|
@url = url
|
45
72
|
@user = user
|
46
73
|
@password = password
|
47
74
|
@logger = case logger
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
@
|
75
|
+
when :off, :none
|
76
|
+
Logger.new(File::NULL, level: Logger::FATAL)
|
77
|
+
when nil
|
78
|
+
Logger.new($stderr, level: Logger::WARN)
|
79
|
+
else
|
80
|
+
logger
|
81
|
+
end
|
82
|
+
@connection = create_raw_connection(url: url, adapter: adapter, user: user, password: password, logger: @logger)
|
56
83
|
bail_if_incompatible!
|
57
84
|
@logger.info("Connected to supported solr at #{url}")
|
58
85
|
end
|
@@ -61,7 +88,7 @@ module SolrCloud
|
|
61
88
|
# @param faraday_connection [Faraday::Connection] A pre-build faraday connection object
|
62
89
|
def self.new_from_faraday(faraday_connection)
|
63
90
|
c = allocate
|
64
|
-
c.instance_variable_set(:@
|
91
|
+
c.instance_variable_set(:@connection, faraday_connection)
|
65
92
|
c.instance_variable_set(:@url, faraday_connection.build_url.to_s)
|
66
93
|
c
|
67
94
|
end
|
@@ -69,7 +96,7 @@ module SolrCloud
|
|
69
96
|
# Create a Faraday connection object to base the API client off of
|
70
97
|
# @see #initialize
|
71
98
|
def create_raw_connection(url:, adapter: :httpx, user: nil, password: nil, logger: nil)
|
72
|
-
Faraday.new(request: {params_encoder: Faraday::FlatParamsEncoder}, url: URI(url)) do |faraday|
|
99
|
+
Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }, url: URI(url)) do |faraday|
|
73
100
|
faraday.use Faraday::Response::RaiseError
|
74
101
|
faraday.request :url_encoded
|
75
102
|
if user
|
@@ -87,7 +114,7 @@ module SolrCloud
|
|
87
114
|
|
88
115
|
# Allow accessing the raw_connection via "connection". Yes, connection.connection
|
89
116
|
# can be confusing, but it makes the *_admin stuff easier to read.
|
90
|
-
alias_method :connection, :
|
117
|
+
alias_method :connection, :connection
|
91
118
|
|
92
119
|
# Check to see if we can actually talk to the solr in question
|
93
120
|
# raise [UnsupportedSolr] if the solr version isn't at least 8
|
@@ -145,6 +172,15 @@ module SolrCloud
|
|
145
172
|
_version_part_int(2)
|
146
173
|
end
|
147
174
|
|
175
|
+
# Check to see if the given string follows solr's rules for thing
|
176
|
+
# Solr only allows ASCII letters and numbers, underscore, and dash,
|
177
|
+
# and it can't start with an underscore.
|
178
|
+
# @param str [String] string to check
|
179
|
+
# @return [Boolean]
|
180
|
+
def legal_solr_name?(str)
|
181
|
+
!(/[^a-zA-Z_\-0-9]/.match?(str) or str.start_with?("_"))
|
182
|
+
end
|
183
|
+
|
148
184
|
def inspect
|
149
185
|
"<#{self.class} #{@url}>"
|
150
186
|
end
|
@@ -156,3 +192,5 @@ module SolrCloud
|
|
156
192
|
end
|
157
193
|
end
|
158
194
|
end
|
195
|
+
|
196
|
+
|
data/lib/solr_cloud/errors.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solr_cloud-connection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bill Dueber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
description:
|
112
126
|
email:
|
113
127
|
- bill@dueber.com
|
@@ -115,7 +129,7 @@ executables: []
|
|
115
129
|
extensions: []
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
118
|
-
- ".env.
|
132
|
+
- ".env.github"
|
119
133
|
- ".rspec"
|
120
134
|
- ".standard.yml"
|
121
135
|
- CHANGELOG.md
|
@@ -124,7 +138,7 @@ files:
|
|
124
138
|
- README.md
|
125
139
|
- Rakefile
|
126
140
|
- compose.yml
|
127
|
-
- env.
|
141
|
+
- env.test
|
128
142
|
- lib/solr_cloud/alias.rb
|
129
143
|
- lib/solr_cloud/collection.rb
|
130
144
|
- lib/solr_cloud/configset.rb
|