bento_search 1.0.1 → 1.0.2
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/app/models/bento_search/multi_searcher.rb +115 -102
- data/lib/bento_search/version.rb +1 -1
- metadata +3 -3
@@ -1,118 +1,131 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'celluloid'
|
2
3
|
|
3
|
-
# Based on Celluloid, concurrently runs multiple searches in
|
4
|
-
# seperate threads. You must include 'celluloid' gem dependency
|
5
|
-
# into your local app to use this class. Requires celluloid 0.12.0
|
6
|
-
# or above (for new preferred async syntax).
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# searcher.
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# Can only call #results once per #start, after that it'll return empty hash.
|
25
|
-
# (should we make it actually raise instead?). .
|
26
|
-
#
|
27
|
-
# important to call results at some point after calling start, in order
|
28
|
-
# to make sure Celluloid::Actors are properly terminated to avoid
|
29
|
-
# resource leakage. May want to do it in an ensure block.
|
30
|
-
#
|
31
|
-
# Note that celluloid uses multi-threading in such a way that you
|
32
|
-
# may have to set config.cache_classes=true even in development
|
33
|
-
# to avoid problems. Rails class reloading is not thread-safe.
|
34
|
-
#
|
35
|
-
#
|
36
|
-
# TODO: have a method that returns Futures instead of only supplying the blocking
|
37
|
-
# results method? Several tricks, including making sure to properly terminate actors.
|
38
|
-
class BentoSearch::MultiSearcher
|
39
|
-
|
40
|
-
def initialize(*engine_ids)
|
41
|
-
@engines = []
|
42
|
-
@actors = []
|
43
|
-
engine_ids.each do |id|
|
44
|
-
add_engine( BentoSearch.get_engine id )
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Adds an instantiated engine directly, rather than by id from global
|
49
|
-
# registry.
|
50
|
-
def add_engine(engine)
|
51
|
-
@engines << engine
|
52
|
-
end
|
53
|
-
|
54
|
-
# Starts all searches, returns self so you can chain method calls if you like.
|
55
|
-
def search(*search_args)
|
56
|
-
@engines.each do |engine|
|
57
|
-
a = Actor.new(engine)
|
58
|
-
@actors << a
|
59
|
-
a.async.start *search_args
|
60
|
-
end
|
61
|
-
return self
|
62
|
-
end
|
63
|
-
alias_method :start, :search # backwards compat
|
64
|
-
|
65
|
-
# Call after #start. Blocks until each included engine is finished
|
66
|
-
# then returns a Hash keyed by engine registered id, value is a
|
67
|
-
# BentoSearch::Results object.
|
4
|
+
# Based on Celluloid, concurrently runs multiple searches in
|
5
|
+
# seperate threads. You must include 'celluloid' gem dependency
|
6
|
+
# into your local app to use this class. Requires celluloid 0.12.0
|
7
|
+
# or above (for new preferred async syntax).
|
8
|
+
#
|
9
|
+
# Warning, if you don't have celluloid in your app, this class simply
|
10
|
+
# won't load. TODO: We should put this file in a different directory
|
11
|
+
# so it's never auto-loaded, and requires a "require 'bento_search/multi_searcher'",
|
12
|
+
# such that it will raise without celluloid only then, and we don't need this
|
13
|
+
# rescue LoadError stuff.
|
14
|
+
#
|
15
|
+
# I am not an expert at use of Celluloid, it's possible there's a better
|
16
|
+
# way to do this all, but seems to work.
|
17
|
+
#
|
18
|
+
# ## Usage
|
19
|
+
#
|
20
|
+
# initialize with id's of registered engines:
|
21
|
+
# searcher = BentoBox::MultiSearcher.new(:gbs, :scopus)
|
22
|
+
#
|
23
|
+
# start the concurrent searches, params same as engine.search
|
24
|
+
# searcher.search( query_params )
|
68
25
|
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
|
72
|
-
|
26
|
+
# retrieve results, blocking until each is completed:
|
27
|
+
# searcher.results
|
28
|
+
#
|
29
|
+
# returns a Hash keyed by engine id, values BentoSearch::Results objects.
|
30
|
+
#
|
31
|
+
# Can only call #results once per #start, after that it'll return empty hash.
|
32
|
+
# (should we make it actually raise instead?). .
|
33
|
+
#
|
34
|
+
# important to call results at some point after calling start, in order
|
35
|
+
# to make sure Celluloid::Actors are properly terminated to avoid
|
36
|
+
# resource leakage. May want to do it in an ensure block.
|
37
|
+
#
|
38
|
+
# Note that celluloid uses multi-threading in such a way that you
|
39
|
+
# may have to set config.cache_classes=true even in development
|
40
|
+
# to avoid problems. Rails class reloading is not thread-safe.
|
41
|
+
#
|
42
|
+
#
|
43
|
+
# TODO: have a method that returns Futures instead of only supplying the blocking
|
44
|
+
# results method? Several tricks, including making sure to properly terminate actors.
|
45
|
+
class BentoSearch::MultiSearcher
|
73
46
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
true
|
47
|
+
def initialize(*engine_ids)
|
48
|
+
@engines = []
|
49
|
+
@actors = []
|
50
|
+
engine_ids.each do |id|
|
51
|
+
add_engine( BentoSearch.get_engine id )
|
52
|
+
end
|
82
53
|
end
|
83
54
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
include Celluloid
|
90
|
-
|
91
|
-
attr_accessor :engine
|
55
|
+
# Adds an instantiated engine directly, rather than by id from global
|
56
|
+
# registry.
|
57
|
+
def add_engine(engine)
|
58
|
+
@engines << engine
|
59
|
+
end
|
92
60
|
|
93
|
-
|
94
|
-
|
61
|
+
# Starts all searches, returns self so you can chain method calls if you like.
|
62
|
+
def search(*search_args)
|
63
|
+
@engines.each do |engine|
|
64
|
+
a = Actor.new(engine)
|
65
|
+
@actors << a
|
66
|
+
a.async.start *search_args
|
67
|
+
end
|
68
|
+
return self
|
95
69
|
end
|
70
|
+
alias_method :start, :search # backwards compat
|
96
71
|
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
72
|
+
# Call after #start. Blocks until each included engine is finished
|
73
|
+
# then returns a Hash keyed by engine registered id, value is a
|
74
|
+
# BentoSearch::Results object.
|
75
|
+
#
|
76
|
+
# Can only call _once_ per invocation of #start, after that it'll return
|
77
|
+
# an empty hash.
|
78
|
+
def results
|
79
|
+
results = {}
|
80
|
+
|
81
|
+
# we use #delete_if to get an iterator that deletes
|
82
|
+
# each item after iteration.
|
83
|
+
@actors.delete_if do |actor|
|
84
|
+
result_key = (actor.engine.configuration.id || actor.engine.class.name)
|
85
|
+
results[result_key] = actor.results
|
86
|
+
actor.terminate
|
106
87
|
|
107
|
-
|
108
|
-
@results.error["exception"] = e
|
88
|
+
true
|
109
89
|
end
|
90
|
+
|
91
|
+
return results
|
110
92
|
end
|
111
93
|
|
112
|
-
|
113
|
-
|
94
|
+
|
95
|
+
class Actor
|
96
|
+
include Celluloid
|
97
|
+
|
98
|
+
attr_accessor :engine
|
99
|
+
|
100
|
+
def initialize(a_engine)
|
101
|
+
self.engine = a_engine
|
102
|
+
end
|
103
|
+
|
104
|
+
# call as .async.start, to invoke async.
|
105
|
+
def start(*search_args)
|
106
|
+
begin
|
107
|
+
@results = self.engine.search(*search_args)
|
108
|
+
rescue Exception => e
|
109
|
+
Rails.logger.error("\nBentoSearch:MultiSearcher caught exception: #{e}\n#{e.backtrace.join(" \n")}")
|
110
|
+
# Make a fake results with caught exception.
|
111
|
+
@results = BentoSearch::Results.new
|
112
|
+
self.engine.fill_in_search_metadata_for(@results, self.engine.normalized_search_arguments(search_args))
|
113
|
+
|
114
|
+
@results.error ||= {}
|
115
|
+
@results.error["exception"] = e
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def results
|
120
|
+
@results
|
121
|
+
end
|
122
|
+
|
114
123
|
end
|
115
124
|
|
116
125
|
end
|
117
|
-
|
126
|
+
|
127
|
+
rescue LoadError
|
128
|
+
# you can use bento_search without celluloid, just not
|
129
|
+
# this class.
|
118
130
|
end
|
131
|
+
|
data/lib/bento_search/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bento_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -400,7 +400,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
400
400
|
version: '0'
|
401
401
|
segments:
|
402
402
|
- 0
|
403
|
-
hash:
|
403
|
+
hash: 4585903005501564692
|
404
404
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
405
405
|
none: false
|
406
406
|
requirements:
|
@@ -409,7 +409,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
409
409
|
version: '0'
|
410
410
|
segments:
|
411
411
|
- 0
|
412
|
-
hash:
|
412
|
+
hash: 4585903005501564692
|
413
413
|
requirements: []
|
414
414
|
rubyforge_project:
|
415
415
|
rubygems_version: 1.8.24
|