1 package OpenILS::Application::Search;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Utils::ModsParser;
8 use OpenSRF::Utils::SettingsClient;
9 use OpenSRF::Utils::Cache;
12 use OpenILS::Application::Search::StaffClient;
13 use OpenILS::Application::Search::Web;
15 use OpenILS::Application::AppUtils;
17 use Time::HiRes qw(time);
18 use OpenSRF::EX qw(:try);
20 # Houses generic search utilites
23 OpenILS::Application::SearchCache->child_init();
28 __PACKAGE__->register_method(
29 method => "biblio_search_marc",
30 api_name => "open-ils.search.biblio.marc",
32 note => "Searches biblio information by marc tag",
35 sub biblio_search_marc {
37 my( $self, $client, $search_hash, $string ) = @_;
39 warn "Building biblio marc session\n";
40 my $session = OpenSRF::AppSession->create("open-ils.storage");
42 warn "Sending biblio marc request\n";
43 my $request = $session->request(
44 "open-ils.storage.metabib.full_rec.search_fts.index_vector",
45 $search_hash, $string );
47 warn "Waiting complete\n";
48 $request->wait_complete();
50 warn "Calling recv\n";
51 my $response = $request->recv(20);
54 if($response and UNIVERSAL::isa($response,"OpenSRF::EX")) {
55 throw $response ($response->stringify);
60 if($response and UNIVERSAL::can($response,"content")) {
61 $data = $response->content;
63 warn "finishing request\n";
67 $session->disconnect();
75 __PACKAGE__->register_method(
76 method => "get_org_tree",
77 api_name => "open-ils.search.actor.org_tree.retrieve",
79 note => "Returns the entire org tree structure",
84 my( $self, $client, $user_session ) = @_;
86 if( $user_session ) { # keep for now for backwards compatibility
89 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
91 my $session = OpenSRF::AppSession->create("open-ils.storage");
92 my $request = $session->request(
93 "open-ils.storage.actor.org_unit.retrieve", $user_obj->home_ou );
94 my $response = $request->recv();
97 throw OpenSRF::EX::ERROR (
98 "No response from storage for org_unit retrieve");
100 if(UNIVERSAL::isa($response,"Error")) {
101 throw $response ($response->stringify);
104 my $home_ou = $response->content;
106 $session->disconnect();
111 return OpenILS::Application::AppUtils->get_org_tree();
116 __PACKAGE__->register_method(
117 method => "get_org_sub_tree",
118 api_name => "open-ils.search.actor.org_subtree.retrieve",
120 note => "Returns the entire org tree structure",
123 sub get_sub_org_tree {
125 my( $self, $client, $user_session ) = @_;
128 throw OpenSRF::EX::InvalidArg
129 ("No User session provided to org_subtree.retrieve");
132 if( $user_session ) {
135 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
138 my $session = OpenSRF::AppSession->create("open-ils.storage");
139 my $request = $session->request(
140 "open-ils.storage.actor.org_unit.retrieve", $user_obj->home_ou );
141 my $response = $request->recv();
144 throw OpenSRF::EX::ERROR (
145 "No response from storage for org_unit retrieve");
147 if(UNIVERSAL::isa($response,"Error")) {
148 throw $response ($response->stringify);
151 my $home_ou = $response->content;
153 # XXX grab descendants and build org tree from them
155 my $request = $session->request(
156 "open-ils.storage.actor.org_unit_descendants" );
157 my $response = $request->recv();
159 throw OpenSRF::EX::ERROR (
160 "No response from storage for org_unit retrieve");
162 if(UNIVERSAL::isa($response,"Error")) {
163 throw $response ($response->stringify);
166 my $descendants = $response->content;
170 $session->disconnect();
182 # ---------------------------------------------------------------------------
183 # takes a list of record id's and turns the docs into friendly
184 # mods structures. Creates one MODS structure for each doc id.
185 # ---------------------------------------------------------------------------
186 sub _records_to_mods {
192 my $session = OpenSRF::AppSession->create("open-ils.storage");
193 my $request = $session->request(
194 "open-ils.storage.biblio.record_marc.batch.retrieve", @ids );
196 my $last_content = undef;
198 while( my $response = $request->recv() ) {
200 if( $last_content ) {
201 my $u = OpenILS::Utils::ModsParser->new();
202 $u->start_mods_batch( $last_content->marc );
203 my $mods = $u->finish_mods_batch();
204 $mods->{doc_id} = $last_content->id();
205 warn "Turning doc " . $mods->{doc_id} . " into MODS\n";
206 $last_content = undef;
207 push @results, $mods;
210 next unless $response;
212 if($response->isa("OpenSRF::EX")) {
213 throw $response ($response->stringify);
216 $last_content = $response->content;
220 if( $last_content ) {
221 my $u = OpenILS::Utils::ModsParser->new();
222 $u->start_mods_batch( $last_content->marc );
223 my $mods = $u->finish_mods_batch();
224 $mods->{doc_id} = $last_content->id();
225 push @results, $mods;
230 $session->disconnect();
236 __PACKAGE__->register_method(
237 method => "record_id_to_mods",
238 api_name => "open-ils.search.biblio.record.mods.retrieve",
240 note => "Provide ID, we provide the mods"
243 # converts a record into a mods object with copy counts attached
244 sub record_id_to_mods {
246 my( $self, $client, $org_id, $id ) = @_;
248 my $mods_list = _records_to_mods( $id );
249 my $mods_obj = $mods_list->[0];
250 my $cmethod = $self->method_lookup(
251 "open-ils.search.biblio.record.copy_count");
252 my ($count) = $cmethod->run($org_id, $id);
253 $mods_obj->{copy_count} = $count;
260 # Returns the number of copies attached to a record based on org location
261 __PACKAGE__->register_method(
262 method => "record_id_to_copy_count",
263 api_name => "open-ils.search.biblio.record.copy_count",
265 note => "Provide ID, we provide the copy count"
268 sub record_id_to_copy_count {
269 my( $self, $client, $org_id, $record_id ) = @_;
271 my $session = OpenSRF::AppSession->create("open-ils.storage");
272 warn "mods retrieve $record_id\n";
273 my $request = $session->request(
274 "open-ils.storage.biblio.record_copy_count", $org_id, $record_id );
276 warn "mods retrieve wait $record_id\n";
277 $request->wait_complete;
279 warn "mods retrieve recv $record_id\n";
280 my $response = $request->recv();
281 return undef unless $response;
283 warn "mods retrieve after recv $record_id\n";
285 if( $response and UNIVERSAL::isa($response, "Error")) {
286 throw $response ($response->stringify);
289 my $count = $response->content;
293 $session->disconnect();
302 package OpenILS::Application::SearchCache;
303 use strict; use warnings;
310 my $config_client = OpenSRF::Utils::SettingsClient->new();
311 my $memcache_servers =
312 $config_client->config_value(
313 "apps","open-ils.search", "app_settings","memcache" );
315 if( !$memcache_servers ) {
316 throw OpenSRF::EX::Config ("
317 No Memcache servers specified for open-ils.search!");
320 if(!ref($memcache_servers)) {
321 $memcache_servers = [$memcache_servers];
323 $cache_handle = OpenSRF::Utils::Cache->new( "open-ils.search", 0, $memcache_servers );
324 $max_timeout = $config_client->config_value(
325 "apps", "open-ils.search", "app_settings", "max_cache_time" );
327 if(ref($max_timeout) eq "ARRAY") {
328 $max_timeout = $max_timeout->[0];
333 sub new {return bless({},shift());}
336 my($self, $key, $data, $timeout) = @_;
337 return undef unless( $key and $data );
339 $timeout ||= $max_timeout;
340 $timeout = ($timeout <= $max_timeout) ? $timeout : $max_timeout;
342 warn "putting $key into cache for $timeout seconds\n";
343 $cache_handle->put_cache( "_open-ils.search_$key", JSON->perl2JSON($data), $timeout );
347 my( $self, $key ) = @_;
348 my $json = $cache_handle->get_cache("_open-ils.search_$key");
350 warn "retrieving from cache $key\n =>>> $json";
352 return JSON->JSON2perl($json);