Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance by using cached location details #1733

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion app/models/folio/campus.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# frozen_string_literal: true

module Folio
Campus = Data.define(:id, :code)
Campus = Data.define(:id, :code) do
def self.from_dynamic(dyn)
new(
id: dyn.fetch('id'),
code: dyn.fetch('code')
)
end
end
end
27 changes: 16 additions & 11 deletions app/models/folio/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,20 @@ module Folio
# See https://github.com/sul-dlss/searchworks_traject_indexer/blob/02192452815de3861dcfafb289e1be8e575cb000/lib/traject/config/sirsi_config.rb#L2379
# NOTE, barcode and callnumber may be nil. see instance_hrid: 'in00000063826'
class Item
attr_reader :barcode, :status, :type, :callnumber, :public_note, :effective_location, :permanent_location, :material_type,
attr_reader :barcode, :status, :type, :callnumber, :public_note, :effective_location_id, :permanent_location_id, :material_type,
:loan_type

# rubocop:disable Metrics/ParameterLists
def initialize(barcode:, status:, type:, callnumber:, public_note:,
effective_location:, permanent_location: nil, material_type: nil, loan_type: nil,
effective_location_id:, permanent_location_id: nil, material_type: nil, loan_type: nil,
due_date: nil)
@barcode = barcode
@status = status
@type = type
@callnumber = callnumber
@public_note = public_note
@effective_location = effective_location
@permanent_location = permanent_location || effective_location
@effective_location_id = effective_location_id
@permanent_location_id = permanent_location_id || effective_location_id
@material_type = material_type
@loan_type = loan_type
@due_date = due_date
Expand Down Expand Up @@ -129,7 +129,7 @@ def hold_recallable?
HOLD_RECALL_STATUSES.include?(status)
end

# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def self.from_hash(dyn)
new(barcode: dyn['barcode'],
status: dyn.dig('status', 'name'),
Expand All @@ -138,16 +138,21 @@ def self.from_hash(dyn)
callnumber: [dyn.dig('effectiveCallNumberComponents', 'callNumber'), dyn['volume'], dyn['enumeration'],
dyn['chronology']].filter_map(&:presence).join(' '),
public_note: dyn.fetch('notes').find { |note| note.dig('itemNoteType', 'name') == 'Public' }&.fetch('note'),
effective_location: Location.from_hash(dyn.fetch('effectiveLocation')),
effective_location_id: dyn['effectiveLocationId'],
permanent_location_id: dyn['permanentLocationId'] || dyn.dig('holdingsRecord', 'effectiveLocationId'),
# fall back to the holding record's effective Location; we're no longer guaranteed an item-level permanent location.
permanent_location: (if dyn['permanentLocation']
Location.from_hash(dyn.fetch('permanentLocation'))
end) || (Location.from_hash(dyn.dig('holdingsRecord', 'effectiveLocation')) if dyn.dig('holdingsRecord',
'effectiveLocation')),
material_type: MaterialType.new(id: dyn.dig('materialType', 'id'), name: dyn.dig('materialType', 'name')),
loan_type: LoanType.new(id: dyn.fetch('tempooraryLoanTypeId', dyn.fetch('permanentLoanTypeId'))))
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
# rubocop:enable Metrics/AbcSize

def permanent_location
@permanent_location ||= Folio::Types.locations.find_by(id: permanent_location_id)
end

def effective_location
@effective_location ||= Folio::Types.locations.find_by(id: effective_location_id)
end

private

Expand Down
36 changes: 29 additions & 7 deletions app/models/folio/location.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,45 @@
# frozen_string_literal: true

module Folio
Location = Data.define(:id, :campus, :library, :library_id, :institution, :code, :discovery_display_name,
:name, :primary_service_point_id, :details) do
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
# Models a location from Folio
class Location
# rubocop:disable Metrics/ParameterLists
def initialize(id:, campus_id:, library_id:, institution_id:, code:, discovery_display_name:,
name:, primary_service_point_id:, details:)
@id = id
@library_id = library_id
@campus_id = campus_id
@institution_id = institution_id
@code = code
@discovery_display_name = discovery_display_name
@name = name
@primary_service_point_id = primary_service_point_id
@details = details
end
# rubocop:enable Metrics/ParameterLists

attr_reader :id, :campus_id, :library_id, :institution_id, :code, :discovery_display_name, :name, :primary_service_point_id, :details

def self.from_hash(dyn)
new(
id: dyn.fetch('id'),
campus: (Campus.new(**dyn.fetch('campus')) if dyn['campus']),
library: (Library.new(**dyn.fetch('library').symbolize_keys) if dyn['library']),
campus_id: dyn.fetch('campusId'),
library_id: dyn['libraryId'] || dyn.dig('library', 'id'),
institution: (Institution.new(id: dyn.fetch('institutionId')) if dyn['institutionId']),
institution_id: dyn.fetch('institutionId'),
code: dyn.fetch('code'),
discovery_display_name: dyn['discoveryDisplayName'] || dyn['name'] || dyn.fetch('id'),
name: dyn['name'],
details: dyn.fetch('details', {}),
primary_service_point_id: dyn['primaryServicePoint'] # present in every location in json, but not from Graphql
)
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength

def library
@library ||= Folio::Types.libraries.find_by(id: library_id)
end

def campus
@campus ||= Folio::Types.campuses.find_by(id: campus_id)
end
end
end
3 changes: 1 addition & 2 deletions app/models/folio/request_abilities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ def pageable?
!mediateable? && !hold_recallable? && any_holdings_pageable?
end

# FOLIO
def pickup_destinations
return (default_pickup_service_points + additional_pickup_service_points).uniq if location_restricted_service_point_codes.empty?

Expand Down Expand Up @@ -97,7 +96,7 @@ def additional_pickup_service_points
# Retrieve the service points associated with specific locations
def location_restricted_service_point_codes
request.holdings.flat_map do |item|
Array(item.effective_location.details['pageServicePoints']).pluck('code')
Array(item.effective_location.details['pageServicePointCodes']&.split(','))
end.compact.uniq
end

Expand Down
16 changes: 16 additions & 0 deletions app/services/folio/campuses_store.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module Folio
# A cache of campus data
class CampusesStore
def initialize(data_from_cache)
@data = data_from_cache.map { |lib_data| Folio::Campus.from_dynamic(lib_data) }
end

attr_reader :data

def find_by(id:)
data.find { |candidate| candidate.id == id }
end
end
end
6 changes: 3 additions & 3 deletions app/services/folio/circulation_rules/policy_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ def item_notice_policy(item)
def item_rule(item)
index.search('material-type' => item.material_type.id,
'loan-type' => item.loan_type.id,
'location-institution' => item.effective_location.institution.id,
'location-campus' => item.effective_location.campus.id,
'location-library' => item.effective_location.library.id,
'location-institution' => item.effective_location.institution_id,
'location-campus' => item.effective_location.campus_id,
'location-library' => item.effective_location.library_id,
'location-location' => item.effective_location.id)
end

Expand Down
6 changes: 5 additions & 1 deletion app/services/folio/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Folio
class Types
class << self
delegate :policies, :circulation_rules, :criteria,
:locations, :libraries, :service_points, to: :instance
:locations, :libraries, :service_points, :campuses, to: :instance
end

def self.instance
Expand Down Expand Up @@ -48,6 +48,10 @@ def service_points
@service_points ||= ServicePointStore.new(get_type('service_points'))
end

def campuses
@campuses ||= CampusesStore.new(get_type('campuses'))
end

def policies
@policies ||= {
request: get_type('request_policies').index_by { |p| p['id'] },
Expand Down
50 changes: 3 additions & 47 deletions app/services/folio_graphql_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,56 +91,12 @@ def instance(hrid:)
name
}
}
effectiveLocation {
id
campusId
libraryId
institutionId
code
discoveryDisplayName
name
servicePoints {
id
code
pickupLocation
}
library {
id
code
}
campus {
id
code
}
details {
pageAeonSite
pageMediationGroupKey
pageServicePoints {
id
code
name
}
scanServicePointCode
availabilityClass
}
}
permanentLocation {
id
code
details {
pagingSchedule
}
}
effectiveLocationId
permanentLocationId
permanentLoanTypeId
temporaryLoanTypeId
holdingsRecord {
effectiveLocation {
id
code
details {
pagingSchedule
}
}
effectiveLocationId
}
}
}
Expand Down
Loading