triannon 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +2 -6
- data/app/controllers/triannon/annotations_controller.rb +18 -4
- data/app/controllers/triannon/search_controller.rb +9 -0
- data/app/models/triannon/annotation.rb +7 -7
- data/app/services/triannon/ldp_loader.rb +11 -5
- data/app/services/triannon/ldp_writer.rb +26 -24
- data/app/services/triannon/solr_searcher.rb +10 -1
- data/app/services/triannon/solr_writer.rb +25 -10
- data/lib/triannon/error.rb +25 -2
- data/lib/triannon/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2548790e908598e117e457e7e2d051e30a9f40e4
|
4
|
+
data.tar.gz: 92b887940f9dcc100cb1c6aeca47f44b1aa2f641
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fefd1bc5ea2b5e8d69d2c48c4cd7d8422ba861815f6ad79b89a44abf05bd2d81588e2226f41f2c8ab823741e56188023da18b4429ba7eb520dc1b46a7f42ba6
|
7
|
+
data.tar.gz: 87e9f142299da474e9f4ea8ba7405efa549429e883d2d0350986814571dd4d73bee2ad9cc993d2061b55949530cf8e8c6c48188725172a31087e1800bcb35de5
|
data/Rakefile
CHANGED
@@ -11,13 +11,9 @@ require 'jettywrapper'
|
|
11
11
|
|
12
12
|
require 'engine_cart/rake_task'
|
13
13
|
desc 'run the triannon specs'
|
14
|
-
task :ci =>
|
15
|
-
# run the tests
|
14
|
+
task :ci => 'engine_cart:generate' do
|
16
15
|
RAILS_ENV = 'test'
|
17
|
-
|
18
|
-
Jettywrapper.wrap(jetty_params) do
|
19
|
-
Rake::Task['spec'].invoke
|
20
|
-
end
|
16
|
+
Rake::Task['spec'].invoke
|
21
17
|
end
|
22
18
|
|
23
19
|
namespace :triannon do
|
@@ -4,9 +4,11 @@ module Triannon
|
|
4
4
|
class AnnotationsController < ApplicationController
|
5
5
|
include RdfResponseFormats
|
6
6
|
|
7
|
+
rescue_from Triannon::LDPStorageError, with: :ldp_storage_error
|
8
|
+
rescue_from Triannon::ExternalReferenceError, with: :ext_ref_error
|
9
|
+
rescue_from Triannon::SearchError, with: :search_error
|
7
10
|
before_action :default_format_jsonld, only: [:show]
|
8
11
|
before_action :set_annotation, only: [:show, :update, :destroy]
|
9
|
-
rescue_from Triannon::ExternalReferenceError, with: :ext_ref_error
|
10
12
|
|
11
13
|
# GET /annotations
|
12
14
|
def index
|
@@ -133,9 +135,21 @@ private
|
|
133
135
|
@annotation = Annotation.find(params[:id])
|
134
136
|
end
|
135
137
|
|
136
|
-
#
|
137
|
-
def ext_ref_error(
|
138
|
-
render plain:
|
138
|
+
# render Triannon::ExternalReferenceError
|
139
|
+
def ext_ref_error(err)
|
140
|
+
render plain: err.message, status: 403
|
141
|
+
end
|
142
|
+
|
143
|
+
# render Triannon::LDPStorage error
|
144
|
+
def ldp_storage_error(err)
|
145
|
+
render :body => "<h2>#{err.message}</h2>" + err.ldp_resp_body, status: err.ldp_resp_status, content_type: "text/html"
|
146
|
+
end
|
147
|
+
|
148
|
+
# render Triannon::SearchError
|
149
|
+
def search_error(err)
|
150
|
+
render :body => "<h2>#{err.message}</h2>" + (err.search_resp_body ? err.search_resp_body : ""),
|
151
|
+
status: err.search_resp_status ? err.search_resp_status : 400,
|
152
|
+
content_type: "text/html"
|
139
153
|
end
|
140
154
|
|
141
155
|
# render json_ld respecting requested context
|
@@ -5,6 +5,7 @@ module Triannon
|
|
5
5
|
include RdfResponseFormats
|
6
6
|
|
7
7
|
before_action :default_format_jsonld, only: [:find]
|
8
|
+
rescue_from Triannon::SearchError, with: :search_error
|
8
9
|
|
9
10
|
def find
|
10
11
|
anno_graphs_array = solr_searcher.find(params)
|
@@ -40,6 +41,14 @@ module Triannon
|
|
40
41
|
@ss ||= Triannon::SolrSearcher.new
|
41
42
|
end
|
42
43
|
|
44
|
+
private
|
45
|
+
|
46
|
+
# render Triannon::SearchError
|
47
|
+
def search_error(err)
|
48
|
+
render :body => "<h2>#{err.message}</h2>" + (err.search_resp_body ? err.search_resp_body : ""),
|
49
|
+
status: err.search_resp_status ? err.search_resp_status : 400,
|
50
|
+
content_type: "text/html"
|
51
|
+
end
|
43
52
|
|
44
53
|
end # SearchController
|
45
54
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Triannon
|
2
2
|
class Annotation
|
3
3
|
include ActiveModel::Model
|
4
|
-
|
4
|
+
|
5
5
|
define_model_callbacks :save, :destroy
|
6
6
|
after_save :solr_save
|
7
7
|
after_destroy :solr_delete
|
@@ -19,7 +19,7 @@ module Triannon
|
|
19
19
|
|
20
20
|
|
21
21
|
# Class Methods ----------------------------------------------------------------
|
22
|
-
|
22
|
+
|
23
23
|
def self.create(attrs = {})
|
24
24
|
a = Triannon::Annotation.new attrs
|
25
25
|
a.save
|
@@ -77,12 +77,12 @@ module Triannon
|
|
77
77
|
@graph = Triannon::Graph.new g
|
78
78
|
end
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
# @return json-ld representation of anno with OpenAnnotation context as a url
|
82
82
|
def jsonld_oa
|
83
83
|
graph.jsonld_oa
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
# @return json-ld representation of anno with IIIF context as a url
|
87
87
|
def jsonld_iiif
|
88
88
|
graph.jsonld_iiif
|
@@ -109,7 +109,7 @@ protected
|
|
109
109
|
def solr_delete
|
110
110
|
solr_writer.delete(id) if id
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
private
|
114
114
|
|
115
115
|
# loads RDF::Graph from data attribute. If data is in json-ld or rdfxml, converts it to turtle.
|
@@ -130,7 +130,7 @@ private
|
|
130
130
|
else # infer the content type from the content itself
|
131
131
|
case data
|
132
132
|
# \A and \Z and m are needed instead of ^$ due to \n in data
|
133
|
-
when /\A\{.+\}\Z/m
|
133
|
+
when /\A\{.+\}\Z/m
|
134
134
|
g = jsonld_to_graph
|
135
135
|
when /\A<.+>\Z/m
|
136
136
|
g = rdfxml_to_graph
|
@@ -143,7 +143,7 @@ private
|
|
143
143
|
end
|
144
144
|
g
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
# create and load an RDF::Graph object from turtle in data attrib
|
148
148
|
# @return [RDF::Graph] populated RDF::Graph object, or nil
|
149
149
|
def ttl_to_graph
|
@@ -37,7 +37,7 @@ module Triannon
|
|
37
37
|
|
38
38
|
# load body objects into @ldp_annotation's (our Triannon::AnnotationLdp object) graph
|
39
39
|
def load_bodies
|
40
|
-
@ldp_annotation.body_uris.each { |body_uri|
|
40
|
+
@ldp_annotation.body_uris.each { |body_uri|
|
41
41
|
body_obj_path = body_uri.to_s.split(@base_uri + '/').last
|
42
42
|
load_object_into_annotation_graph(body_obj_path)
|
43
43
|
}
|
@@ -45,12 +45,12 @@ module Triannon
|
|
45
45
|
|
46
46
|
# load target objects into @ldp_annotation's (our Triannon::AnnotationLdp object) graph
|
47
47
|
def load_targets
|
48
|
-
@ldp_annotation.target_uris.each { |target_uri|
|
48
|
+
@ldp_annotation.target_uris.each { |target_uri|
|
49
49
|
target_obj_path = target_uri.to_s.split(@base_uri + '/').last
|
50
50
|
load_object_into_annotation_graph(target_obj_path)
|
51
51
|
}
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# @return [Array<Triannon::Annotation>] an array of Triannon::Annotation objects with just the id set. Enough info to build the index page
|
55
55
|
def find_all
|
56
56
|
root_ttl = get_ttl
|
@@ -83,13 +83,17 @@ module Triannon
|
|
83
83
|
req.url "#{sub_path}" if sub_path
|
84
84
|
req.headers['Accept'] = 'application/x-turtle'
|
85
85
|
end
|
86
|
-
resp.
|
86
|
+
if resp.status.between?(400, 600)
|
87
|
+
raise Triannon::LDPStorageError.new("error getting #{sub_path} from LDP", resp.status, resp.body)
|
88
|
+
else
|
89
|
+
resp.body
|
90
|
+
end
|
87
91
|
end
|
88
92
|
|
89
93
|
# turns turtle serialization into Array of RDF::Statements, removing fedora-specific triples
|
90
94
|
# (leaving LDP and OA triples)
|
91
95
|
# @param [String] ttl a String containing RDF serialized as turtle
|
92
|
-
# @return [Array<RDF::Statements>] the RDF statements represented in the ttl
|
96
|
+
# @return [Array<RDF::Statements>] the RDF statements represented in the ttl
|
93
97
|
def statements_from_ttl_minus_fedora ttl
|
94
98
|
# RDF::Turtle::Reader.new(ttl).statements.to_a
|
95
99
|
g = RDF::Graph.new.from_ttl(ttl) if ttl
|
@@ -98,6 +102,8 @@ module Triannon
|
|
98
102
|
|
99
103
|
def conn
|
100
104
|
@c ||= Faraday.new @base_uri
|
105
|
+
@c.headers['Prefer'] = 'return=respresentation; omit="http://fedora.info/definitions/v4/repository#ServerManaged"'
|
106
|
+
@c
|
101
107
|
end
|
102
108
|
|
103
109
|
end
|
@@ -7,7 +7,7 @@ module Triannon
|
|
7
7
|
# @param [Triannon::Annotation] anno a Triannon::Annotation object, from which we use the graph
|
8
8
|
def self.create_anno(anno)
|
9
9
|
if anno && anno.graph
|
10
|
-
# TODO: special case if the Annotation object already has an id --
|
10
|
+
# TODO: special case if the Annotation object already has an id --
|
11
11
|
# see https://github.com/sul-dlss/triannon/issues/84
|
12
12
|
ldp_writer = Triannon::LdpWriter.new anno
|
13
13
|
id = ldp_writer.create_base
|
@@ -39,11 +39,11 @@ module Triannon
|
|
39
39
|
ldpw.delete_containers id
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
class << self
|
44
44
|
alias_method :delete_anno, :delete_container
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
# @param [Triannon::Annotation] anno a Triannon::Annotation object
|
48
48
|
# @param [String] id the unique id for the LDP container for the passed annotation; defaults to nil
|
49
49
|
def initialize(anno, id=nil)
|
@@ -59,14 +59,14 @@ module Triannon
|
|
59
59
|
if @anno.graph.query([nil, RDF::Triannon.externalReference, nil]).count > 0
|
60
60
|
raise Triannon::ExternalReferenceError, "Incoming annotations may not have http://triannon.stanford.edu/ns/externalReference as a predicate."
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
if @anno.graph.id_as_url && @anno.graph.id_as_url.size > 0
|
64
64
|
raise Triannon::ExternalReferenceError, "Incoming new annotations may not have an existing id (yet)."
|
65
65
|
end
|
66
66
|
|
67
|
-
# TODO: special case if the Annotation object already has an id --
|
67
|
+
# TODO: special case if the Annotation object already has an id --
|
68
68
|
# see https://github.com/sul-dlss/triannon/issues/84
|
69
|
-
|
69
|
+
|
70
70
|
# we need to work with a copy of the graph so we don't change @anno.graph
|
71
71
|
g = RDF::Graph.new
|
72
72
|
@anno.graph.each { |s|
|
@@ -93,7 +93,7 @@ module Triannon
|
|
93
93
|
def create_body_resources
|
94
94
|
create_resources_in_container RDF::OpenAnnotation.hasBody
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
# create the target resources inside the (already created) target container
|
98
98
|
def create_target_resources
|
99
99
|
create_resources_in_container RDF::OpenAnnotation.hasTarget
|
@@ -108,11 +108,11 @@ module Triannon
|
|
108
108
|
ldp_container_uris = [ldp_container_uris]
|
109
109
|
end
|
110
110
|
something_deleted = false
|
111
|
-
ldp_container_uris.each { |uri|
|
111
|
+
ldp_container_uris.each { |uri|
|
112
112
|
ldp_id = uri.to_s.split(@base_uri + '/').last
|
113
113
|
resp = conn.delete { |req| req.url ldp_id }
|
114
114
|
if resp.status != 204
|
115
|
-
raise "Unable to delete LDP container
|
115
|
+
raise Triannon::LDPStorageError.new("Unable to delete LDP container #{ldp_id}", resp.status, resp.body)
|
116
116
|
end
|
117
117
|
something_deleted = true
|
118
118
|
}
|
@@ -121,8 +121,8 @@ module Triannon
|
|
121
121
|
|
122
122
|
protected
|
123
123
|
|
124
|
-
# POSTS a ttl representation of a graph to
|
125
|
-
# @param [String] ttl a turtle representation of RDF data to be put in the
|
124
|
+
# POSTS a ttl representation of a graph to an existing LDP container in the LDP store
|
125
|
+
# @param [String] ttl a turtle representation of RDF data to be put in the LDP container
|
126
126
|
# @param [String] parent_path the path portion of the url for the LDP parent container for this resource
|
127
127
|
# if no path is supplied, then the resource will be created as a child of the root annotation;
|
128
128
|
# expected paths would also be (anno_id)/t for a target resource (inside the target container of anno_id)
|
@@ -136,12 +136,12 @@ module Triannon
|
|
136
136
|
req.body = ttl
|
137
137
|
end
|
138
138
|
if resp.status != 200 && resp.status != 201
|
139
|
-
raise "Unable to create LDP resource in container #{parent_path}
|
139
|
+
raise Triannon::LDPStorageError.new("Unable to create LDP resource in container #{parent_path}; RDF sent: #{ttl}", resp.status, resp.body)
|
140
140
|
end
|
141
141
|
new_url = resp.headers['Location'] ? resp.headers['Location'] : resp.headers['location']
|
142
142
|
new_url.split('/').last if new_url
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
# Creates an empty LDP DirectContainer in LDP Storage that is a member of the base container and has the memberRelation per the oa_vocab_term
|
146
146
|
# The id of the created containter will be (base container id)/b if hasBody or (base container id)/t if hasTarget
|
147
147
|
# @param [RDF::Vocabulary::Term] oa_vocab_term RDF::OpenAnnotation.hasTarget or RDF::OpenAnnotation.hasBody
|
@@ -160,7 +160,7 @@ module Triannon
|
|
160
160
|
req.body = g.to_ttl
|
161
161
|
end
|
162
162
|
if resp.status != 201
|
163
|
-
raise "Unable to create #{oa_vocab_term.fragment.sub('has', '')} LDP container for anno
|
163
|
+
raise Triannon::LDPStorageError.new("Unable to create #{oa_vocab_term.fragment.sub('has', '')} LDP container for anno; RDF sent: #{g.to_ttl}", resp.status, resp.body)
|
164
164
|
end
|
165
165
|
resp
|
166
166
|
end
|
@@ -176,7 +176,7 @@ module Triannon
|
|
176
176
|
if predicate_obj.is_a?(RDF::Node)
|
177
177
|
# we need to use the null relative URI representation of blank nodes to write to LDP
|
178
178
|
predicate_subject = RDF::URI.new
|
179
|
-
else
|
179
|
+
else
|
180
180
|
# it's already a URI, but we need to use the null relative URI representation so we can
|
181
181
|
# write out as a Triannon:externalRef property with the URL, and any addl props too.
|
182
182
|
if predicate_obj.to_str
|
@@ -185,7 +185,7 @@ module Triannon
|
|
185
185
|
:predicate => RDF::Triannon.externalReference,
|
186
186
|
:object => RDF::URI.new(predicate_obj.to_str)})
|
187
187
|
addl_stmts = @anno.graph.query([predicate_obj, nil, nil])
|
188
|
-
addl_stmts.each { |s|
|
188
|
+
addl_stmts.each { |s|
|
189
189
|
graph_for_resource << RDF::Statement({:subject => predicate_subject,
|
190
190
|
:predicate => s.predicate,
|
191
191
|
:object => s.object})
|
@@ -194,13 +194,13 @@ module Triannon
|
|
194
194
|
predicate_subject = predicate_obj
|
195
195
|
end
|
196
196
|
end
|
197
|
-
|
197
|
+
|
198
198
|
# add statements with predicate_obj as the subject
|
199
199
|
orig_hash_uri_objs = [] # the orig URI objects from [targetObject, OA.hasSource/.default/.item, (uri)] statements
|
200
200
|
hash_uri_counter = 1
|
201
201
|
Triannon::Graph.subject_statements(predicate_obj, @anno.graph).each { |s|
|
202
202
|
if s.subject == predicate_obj
|
203
|
-
# deal with any external URI references which may occur in:
|
203
|
+
# deal with any external URI references which may occur in:
|
204
204
|
# OA.hasSource (from SpecificResource), OA.default or OA.item (from Choice, Composite, List)
|
205
205
|
if s.object.is_a?(RDF::URI) && s.object.to_s
|
206
206
|
# do we need to represent the URL as an externalReference with hash URI
|
@@ -218,7 +218,7 @@ module Triannon
|
|
218
218
|
:predicate => s.predicate,
|
219
219
|
:object => s.object})
|
220
220
|
end
|
221
|
-
|
221
|
+
|
222
222
|
if hash_uri_str
|
223
223
|
# represent the object URL as an external ref
|
224
224
|
new_hash_uri_obj = RDF::URI.new(hash_uri_str)
|
@@ -228,7 +228,7 @@ module Triannon
|
|
228
228
|
graph_for_resource << RDF::Statement({:subject => predicate_subject,
|
229
229
|
:predicate => s.predicate,
|
230
230
|
:object => new_hash_uri_obj})
|
231
|
-
|
231
|
+
|
232
232
|
# add externalReference triple to graph
|
233
233
|
graph_for_resource << RDF::Statement({:subject => new_hash_uri_obj,
|
234
234
|
:predicate => RDF::Triannon.externalReference,
|
@@ -251,15 +251,15 @@ module Triannon
|
|
251
251
|
:predicate => s.predicate,
|
252
252
|
:object => s.object})
|
253
253
|
end
|
254
|
-
else
|
255
|
-
# s.subject != predicate_obj
|
254
|
+
else
|
255
|
+
# s.subject != predicate_obj
|
256
256
|
graph_for_resource << s
|
257
257
|
end
|
258
258
|
}
|
259
259
|
# make sure the graph we will write contains no extraneous statements about URIs
|
260
260
|
# now represented as hash URIs
|
261
|
-
orig_hash_uri_objs.each { |uri_node|
|
262
|
-
Triannon::Graph.subject_statements(uri_node, graph_for_resource).each { |s|
|
261
|
+
orig_hash_uri_objs.each { |uri_node|
|
262
|
+
Triannon::Graph.subject_statements(uri_node, graph_for_resource).each { |s|
|
263
263
|
graph_for_resource.delete(s)
|
264
264
|
}
|
265
265
|
}
|
@@ -274,6 +274,8 @@ module Triannon
|
|
274
274
|
|
275
275
|
def conn
|
276
276
|
@c ||= Faraday.new @base_uri
|
277
|
+
@c.headers['Prefer'] = 'return=respresentation; omit="http://fedora.info/definitions/v4/repository#ServerManaged"'
|
278
|
+
@c
|
277
279
|
end
|
278
280
|
|
279
281
|
end
|
@@ -14,7 +14,7 @@ module Triannon
|
|
14
14
|
}
|
15
15
|
result
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
# @note hardcoded Solr search service expectation in generated search params
|
19
19
|
# @note hardcoded mapping of REST params for /search to Solr params
|
20
20
|
#
|
@@ -114,6 +114,8 @@ module Triannon
|
|
114
114
|
end
|
115
115
|
|
116
116
|
|
117
|
+
attr_accessor :rsolr_client
|
118
|
+
|
117
119
|
def initialize
|
118
120
|
@rsolr_client = RSolr.connect :url => Triannon.config[:solr_url]
|
119
121
|
@logger = Rails.logger
|
@@ -145,6 +147,12 @@ module Triannon
|
|
145
147
|
def search(solr_params = {})
|
146
148
|
handler = Proc.new do |exception, attempt_cnt, total_delay|
|
147
149
|
@logger.debug "#{exception.inspect} on Solr search attempt #{attempt_cnt} for #{solr_params.inspect}"
|
150
|
+
if exception.kind_of?(RSolr::Error::Http)
|
151
|
+
# Note there are extra shenanigans b/c RSolr hijacks the Solr error to return RSolr Error
|
152
|
+
raise Triannon::SearchError.new("error searching Solr with params #{solr_params.inspect}: #{exception.message}", exception.response[:status], exception.response[:body])
|
153
|
+
elsif exception.kind_of?(StandardError)
|
154
|
+
raise Triannon::SearchError.new("error searching Solr with params #{solr_params.inspect}: #{exception.message}")
|
155
|
+
end
|
148
156
|
end
|
149
157
|
|
150
158
|
response = nil
|
@@ -154,6 +162,7 @@ module Triannon
|
|
154
162
|
:max_sleep_seconds => @max_sleep_seconds) do |attempt|
|
155
163
|
@logger.debug "Solr search attempt #{attempt} for #{solr_params.inspect}"
|
156
164
|
# use POST in case of long params
|
165
|
+
# RSolr throws RSolr::Error::Http for any Solr response without status 200 or 302
|
157
166
|
response = @rsolr_client.post 'select', :params => solr_params
|
158
167
|
@logger.info "Successfully searched Solr on attempt #{attempt}"
|
159
168
|
end
|
@@ -47,6 +47,7 @@ module Triannon
|
|
47
47
|
doc_hash
|
48
48
|
end
|
49
49
|
|
50
|
+
attr_accessor :rsolr_client
|
50
51
|
|
51
52
|
def initialize
|
52
53
|
@rsolr_client = RSolr.connect :url => Triannon.config[:solr_url]
|
@@ -72,37 +73,51 @@ module Triannon
|
|
72
73
|
|
73
74
|
handler = Proc.new do |exception, attempt_cnt, total_delay|
|
74
75
|
@logger.debug "#{exception.inspect} on Solr add attempt #{attempt_cnt} for #{id}"
|
76
|
+
if exception.kind_of?(RSolr::Error::Http)
|
77
|
+
# Note there are extra shenanigans b/c RSolr hijacks the Solr error to return RSolr Error
|
78
|
+
raise Triannon::SearchError.new("error adding doc #{id} to Solr #{doc.inspect}; #{exception.message}", exception.response[:status], exception.response[:body])
|
79
|
+
elsif exception.kind_of?(StandardError)
|
80
|
+
raise Triannon::SearchError.new("error adding doc #{id} to Solr #{doc.inspect}; #{exception.message}")
|
81
|
+
end
|
75
82
|
end
|
76
83
|
|
77
|
-
with_retries(:handler => handler,
|
78
|
-
:max_tries => @max_retries,
|
79
|
-
:base_sleep_seconds => @base_sleep_seconds,
|
84
|
+
with_retries(:handler => handler,
|
85
|
+
:max_tries => @max_retries,
|
86
|
+
:base_sleep_seconds => @base_sleep_seconds,
|
80
87
|
:max_sleep_seconds => @max_sleep_seconds) do |attempt|
|
81
88
|
@logger.debug "Solr add attempt #{attempt} for #{id}"
|
82
89
|
# add it and commit within 0.5 seconds
|
83
90
|
@rsolr_client.add(doc, :add_attributes => {:commitWithin => 500})
|
91
|
+
# RSolr throws RSolr::Error::Http for any Solr response without status 200 or 302
|
84
92
|
@logger.info "Successfully indexed #{id} to Solr on attempt #{attempt}"
|
85
93
|
end
|
86
94
|
end
|
87
|
-
|
95
|
+
|
88
96
|
# Delete the document from Solr, retrying if an error occurs.
|
89
97
|
# See https://github.com/ooyala/retries for info on with_retries.
|
90
98
|
# @param [String] id the id of the Solr document to be deleted
|
91
99
|
def delete(id)
|
92
100
|
handler = Proc.new do |exception, attempt_cnt, total_delay|
|
93
101
|
@logger.debug "#{exception.inspect} on Solr delete attempt #{attempt_cnt} for #{id}"
|
94
|
-
|
102
|
+
if exception.kind_of?(RSolr::Error::Http)
|
103
|
+
# Note there are extra shenanigans b/c RSolr hijacks the Solr error to return RSolr Error
|
104
|
+
raise Triannon::SearchError.new("error deleting doc #{id} from Solr: #{exception.message}", exception.response[:status], exception.response[:body])
|
105
|
+
elsif exception.kind_of?(StandardError)
|
106
|
+
raise Triannon::SearchError.new("error deleting doc #{id} from Solr: #{exception.message}")
|
107
|
+
end
|
108
|
+
end
|
95
109
|
|
96
|
-
with_retries(:handler => handler,
|
97
|
-
:max_tries => @max_retries,
|
98
|
-
:base_sleep_seconds => @base_sleep_seconds,
|
110
|
+
with_retries(:handler => handler,
|
111
|
+
:max_tries => @max_retries,
|
112
|
+
:base_sleep_seconds => @base_sleep_seconds,
|
99
113
|
:max_sleep_seconds => @max_sleep_seconds) do |attempt|
|
100
114
|
@logger.debug "Solr delete attempt #{attempt} for #{id}"
|
115
|
+
# RSolr throws RSolr::Error::Http for any Solr response without status 200 or 302
|
101
116
|
@rsolr_client.delete_by_id(id)
|
102
117
|
@rsolr_client.commit
|
103
118
|
@logger.info "Successfully deleted #{id} from Solr"
|
104
|
-
end
|
119
|
+
end
|
105
120
|
end
|
106
|
-
|
121
|
+
|
107
122
|
end
|
108
123
|
end
|
data/lib/triannon/error.rb
CHANGED
@@ -2,8 +2,31 @@ module Triannon
|
|
2
2
|
# generic Triannon error allowing rescue to catch all Triannon exceptions
|
3
3
|
class Error < RuntimeError
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
6
|
class ExternalReferenceError < Triannon::Error
|
7
|
+
def initialize(message = nil)
|
8
|
+
super(message)
|
9
|
+
end
|
7
10
|
end
|
8
|
-
|
11
|
+
|
12
|
+
# used to keep HTTP response info from LDP
|
13
|
+
class LDPStorageError < Triannon::Error
|
14
|
+
attr_accessor :ldp_resp_status, :ldp_resp_body
|
15
|
+
def initialize(message = nil, ldp_resp_status = nil, ldp_resp_body = nil)
|
16
|
+
super(message)
|
17
|
+
self.ldp_resp_status = ldp_resp_status if ldp_resp_status
|
18
|
+
self.ldp_resp_body = ldp_resp_body if ldp_resp_body
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# used to keep HTTP response info from Solr
|
23
|
+
class SearchError < Triannon::Error
|
24
|
+
attr_accessor :search_resp_status, :search_resp_body
|
25
|
+
def initialize(message = nil, search_resp_status = nil, search_resp_body = nil)
|
26
|
+
super(message)
|
27
|
+
self.search_resp_status = search_resp_status if search_resp_status
|
28
|
+
self.search_resp_body = search_resp_body if search_resp_body
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
9
32
|
end
|
data/lib/triannon/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: triannon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Beer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-04-
|
13
|
+
date: 2015-04-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|