]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/WWW/AddedContent.pm
more debugging
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / WWW / AddedContent.pm
1 package OpenILS::WWW::AddedContent;
2 use strict; use warnings;
3
4 use lib qw(/usr/lib/perl5/Bundle/);
5
6 use CGI;
7 use Apache2::Log;
8 use Apache2::Const -compile => qw(OK REDIRECT DECLINED NOT_FOUND :log);
9 use APR::Const    -compile => qw(:error SUCCESS);
10 use Apache2::RequestRec ();
11 use Apache2::RequestIO ();
12 use Apache2::RequestUtil;
13 use Data::Dumper;
14
15 use OpenSRF::EX qw(:try);
16 use OpenSRF::Utils::Cache;
17 use OpenSRF::System;
18 use OpenSRF::Utils::Logger qw/$logger/;
19
20 use LWP::UserAgent;
21 use MIME::Base64;
22
23 my $AC = __PACKAGE__;
24
25
26 # set the bootstrap config when this module is loaded
27 my $bs_config;
28
29 sub import {
30     my $self = shift;
31     $bs_config = shift;
32 }
33
34
35 my $handler; # added content handler class handle
36 my $cache; # memcache handle
37 my $net_timeout; # max seconds to wait for a response from the added content vendor
38 my $max_errors; # max consecutive lookup failures before added content is temporarily disabled
39 my $error_countdown; # current consecutive errors countdown
40
41 # number of seconds to wait before next lookup 
42 # is attempted after lookups have been disabled
43 my $error_retry_timeout;
44
45
46 sub child_init {
47
48     OpenSRF::System->bootstrap_client( config_file => $bs_config );
49     $cache = OpenSRF::Utils::Cache->new;
50
51     my $sclient = OpenSRF::Utils::SettingsClient->new();
52     my $ac_data = $sclient->config_value("added_content");
53
54     return unless $ac_data;
55     my $ac_handler = $ac_data->{module};
56     return unless $ac_handler;
57
58     $net_timeout = $ac_data->{timeout} || 1;
59     $error_countdown = $max_errors = $ac_data->{max_errors} || 10;
60     $error_retry_timeout = $ac_data->{retry_timeout} || 600;
61
62     $logger->debug("Attempting to load Added Content handler: $ac_handler");
63
64     eval "use $ac_handler";
65
66     if($@) {    
67         $logger->error("Unable to load Added Content handler [$ac_handler]: $@"); 
68         return; 
69     }
70
71     $handler = $ac_handler->new($ac_data);
72     $logger->debug("added content loaded handler: $handler");
73 }
74
75
76 sub handler {
77
78     my $r   = shift;
79     my $cgi = CGI->new;
80     my $path = $r->path_info;
81     my $res;
82
83     my( undef, $type, $format, $key ) = split(/\//, $r->path_info);
84
85     child_init() unless $handler;
86
87     return Apache2::Const::NOT_FOUND unless $handler and $type and $format and $key;
88     return $res if defined($res = $AC->serve_from_cache($type, $format, $key));
89     return Apache2::Const::NOT_FOUND unless $AC->lookups_enabled;
90
91     my $err;
92     my $data;
93     my $method = "${type}_${format}";
94
95     return Apache2::Const::NOT_FOUND unless $handler->can($method);
96
97     try {
98         $data = $handler->$method($key);
99     } catch Error with { 
100         $err = shift; 
101         decr_error_countdown();
102         $logger->error("added content handler failed: $method($key) => $err");
103     };
104
105     return Apache2::Const::NOT_FOUND if $err;
106
107     if(!$data) {
108         # if the AC lookup found no corresponding data, cache that information
109         $logger->debug("added content handler returned no results $method($key)") unless $data;
110         $AC->cache_result($type, $format, $key, {nocontent=>1});
111         return Apache2::Const::NOT_FOUND;
112     }
113     
114     $AC->print_content($data);
115     $AC->cache_result($type, $format, $key, $data);
116
117     reset_error_countdown();
118     return Apache2::Const::OK;
119 }
120
121 sub print_content {
122     my($class, $data, $from_cache) = @_;
123     return Apache2::Const::NOT_FOUND if $data->{nocontent};
124
125     my $ct = $data->{content_type};
126     my $content = $data->{content};
127     print "Content-type: $ct\n\n";
128
129     if($data->{binary}) {
130         binmode STDOUT;
131         # if it hasn't been cached yet, it's still in binary form
132         print( ($from_cache) ? decode_base64($content) : $content );
133     } else {
134         print $content;
135     }
136
137
138     return Apache2::Const::OK;
139 }
140
141
142
143
144 # returns an HTPP::Response object
145 sub get_url {
146     my( $self, $url ) = @_;
147
148     $logger->info("added content getting [timeout=$net_timeout, errors_remaining=$error_countdown] URL = $url");
149     my $agent = LWP::UserAgent->new(timeout => $net_timeout);
150
151     my $res = $agent->get($url); 
152     $logger->info("added content request returned with code " . $res->code);
153     die "added content request failed: " . $res->status_line ."\n" unless $res->is_success;
154
155     return $res;
156 }
157
158 sub lookups_enabled {
159     if( $cache->get_cache('ac.no_lookup') ) {
160         $logger->info("added content lookup disabled");
161         return undef;
162     }
163     return 1;
164 }
165
166 sub disable_lookups {
167     $cache->put_cache('ac.no_lookup', 1, $error_retry_timeout);
168 }
169
170 sub decr_error_countdown {
171     $error_countdown--;
172     if($error_countdown < 1) {
173         $logger->warn("added content error count exhausted.  Disabling lookups for $error_retry_timeout seconds");
174         $AC->disable_lookups;
175     }
176 }
177
178 sub reset_error_countdown {
179     $error_countdown = $max_errors;
180 }
181
182 sub cache_result {
183     my($class, $type, $format, $key, $data) = @_;
184     $logger->debug("caching $type/$format/$key");
185     $data->{content} = encode_base64($data->{content}) if $data->{binary};
186     return $cache->put_cache("ac.$type.$format.$key", $data);
187 }
188
189 sub serve_from_cache {
190     my($class, $type, $format, $key) = @_;
191     my $data = $cache->get_cache("ac.$type.$format.$key");
192     return undef unless $data;
193     $logger->debug("serving $type/$format/$key from cache");
194     return $class->print_content($data, 1);
195 }
196
197
198
199 1;