Class: BorrowDirectAdaptor

Inherits:
Service
  • Object
show all
Includes:
MetadataHelper
Defined in:
app/service_adaptors/borrow_direct_adaptor.rb

Overview

optional parameter http_timeout, in seconds, for HTTP with BD. BD can be slow. default to 20 seconds. Much longer, you might start running into Umlaut’s own global request processing timeouts. If timeout is reached, service should produce a URL linking into a DIY BD search, AND display an error.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ BorrowDirectAdaptor

Returns a new instance of BorrowDirectAdaptor.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 14

def initialize(config)
  # testing shows truncating titles to 5 words results in fewer
  # false negatives seemingly without significant false positives. 
  # but you can set to nil/empty to disable truncation, or
  # set to a different number. 
  @limit_title_words = 5 
  @display_name = "BorrowDirect"
  @http_timeout = 20

  # Log BD API calls to logger -- defaults to Rails.logger
  @bd_api_logger = Rails.logger

  # set to 'warn', 'info', 'debug', etc to turn on logging
  # of succesful FindItem api requests. Useful for looking at error rate. 
  # nil means don't log. 
  @bd_api_logger_level = nil
  # Abort for these rfr_id's -- keep from searching BD when
  # we came from BD. 
  @suppress_rfr_ids = ["info:sid/BD", "info:sid/BD-Unfilled"]

  # Should we use the api at all? Set to false to disable API
  # entirely, because you think it performs too crappily or
  # because it's not yet avail in production. 
  @use_bd_api = true

  super
end

Instance Attribute Details

#http_timeoutObject

Returns the value of attribute http_timeout.



12
13
14
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 12

def http_timeout
  @http_timeout
end

#library_symbolObject

Returns the value of attribute library_symbol.



12
13
14
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 12

def library_symbol
  @library_symbol
end

#use_bd_apiObject

Returns the value of attribute use_bd_api.



12
13
14
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 12

def use_bd_api
  @use_bd_api
end

Instance Method Details

#appropriate_citation_type?(request) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 46

def appropriate_citation_type?(request)
  return ! title_is_serial?(request.referent)
end

#bd_api_log(isbn, action, result, timing) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 134

def bd_api_log(isbn, action, result, timing)
  if result.kind_of? Exception
    result = "#{result.class}/#{result.message}"
    if result.respond_to?(:bd_code) && result.bd_code.present?
      result += "/#{result.bd_code}"
    end
  end

  if @bd_api_log_level
    @bd_api_logger.send(@bd_api_log_level, "BD API log\t#{action}\t#{result}\t#{timing.round(1) if timing}\tisbn=#{isbn}")
  end
end

#can_precheck_borrow_direct?(request) ⇒ Boolean

Right now, if and only if we have an ISBN and the API is enabled.

Returns:

  • (Boolean)


128
129
130
131
132
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 128

def can_precheck_borrow_direct?(request)
  return false unless @use_bd_api

  isbn(request).present?
end

#handle(request) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 55

def handle(request)
  if request.referrer_id && @suppress_rfr_ids.include?(request.referrer_id)
    return request.dispatched(self, true)
  end

  if ! appropriate_citation_type?(request)
    # we do nothing if it looks like an article or journal title. 
    return request.dispatched(self, true)
  end

  if locally_available?(request)
    # We do nothing if it looks like it's locally available
    return request.dispatched(self, true)
  end

  # Always add a manual link to search results
  make_link_to_search_response(request)

  if can_precheck_borrow_direct?(request)
    # pre-check it with BD api, this will take a while
    begin
      finditem = BorrowDirect::FindItem.new(@find_item_patron_barcode, @library_symbol)
      finditem.timeout = @http_timeout
      response = finditem.find(:isbn => isbn(request))

      # Log success if configured, used for looking at error rate
      bd_api_log(isbn(request), "FindItem", "SUCCESS", finditem.last_request_time)

      if response.requestable?
        # Mark it requestable!
        request.add_service_response( 
          :service=>self, 
          :display_text => "Choose your delivery location",
          :display_text_i18n => "bd_request_prompt.display_text",
          :service_type_value => :bd_request_prompt,
          :pickup_locations => response.pickup_locations)
      else
        request.add_service_response( 
          :service=>self, 
          :display_text => "This item is not currently available from BorrowDirect",
          :display_text_i18n => "bd_not_available.display_text", 
          :service_type_value => :bd_not_available)
      end
    rescue BorrowDirect::Error => e 
      # BD didn't let us check availability, log it and give them
      # a consolation direct link response
      msg =  "BorrowDirect returned error on FindItem, resorting to a bd_link_to_search response instead.\n"
      msg += "    * Returned error: #{e.inspect}\n"
      msg += "    * BD url: #{finditem.last_request_uri}\n"
      msg += "    * Posted with json payload: #{finditem.last_request_json}\n"
      Rails.logger.error(msg)

      # Special BD error log if configured
      bd_api_log(isbn(request), "FindItem", e, finditem.last_request_time)

      # And mark it as an error so error message will be displayed. Let's
      # mark it a temporary error, so it'll be tried again later, it might
      # be a temporary problem on BD, esp timeout.         
      return request.dispatched(self, DispatchedService::FailedTemporary, e)
    end
  end

  return request.dispatched(self, true)
end

#isbn(request) ⇒ Object

Make sure there are no hyphens, BD doesn’t seem to like it



51
52
53
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 51

def isbn(request)
  request.referent.isbn && request.referent.isbn.gsub('-', '')
end

#locally_available?(request) ⇒ Boolean

Does Umlaut have info to think the item is locally available? By default, check for Umlaut holding responses, but can be customized with config.

Returns:

  • (Boolean)


123
124
125
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 123

def locally_available?(request)
  UmlautBorrowDirect.locally_available? request
end


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 147

def make_link_to_search_response(request)
  # We used to try and include ISBN in our query too, as (ISBN OR (author AND title))
  # But some BD z3950 endpoints can't handle this query (harvard apparently), and
  # it's just generally touchier. We'll just use author/title, keeping things
  # simple seems to the key to predictable BD results. 
  title  = raw_search_title(request.referent)
  author = get_search_creator(request.referent)

  url = BorrowDirect::GenerateQuery.new(@html_query_base_url).normalized_author_title_query(
    :title  => title,
    :author => author,
    :max_title_words => @limit_title_words
  )

  request.add_service_response( 
    :service=>self, 
    :display_text => "Check BorrowDirect for availability",
    :display_text_i18n => "bd_link_to_search.display_text",
    :notes => "May be available in BorrowDirect",
    :notes_i18n => "bd_link_to_search.notes",
    :url => url, 
    :service_type_value => :bd_link_to_search)
end

#service_types_generatedObject



42
43
44
# File 'app/service_adaptors/borrow_direct_adaptor.rb', line 42

def service_types_generated
  return [ServiceTypeValue[:bd_link_to_search], ServiceTypeValue[:bd_request_prompt], ServiceTypeValue[:bd_not_available], ServiceTypeValue[:bd_request_status]]
end