From 5fc1b514ac2c4472d417f50aca0393e3cb449db1 Mon Sep 17 00:00:00 2001 From: temi Date: Mon, 29 Jul 2024 17:01:50 +1000 Subject: [PATCH] #817 - improves response time of get profile call --- .../org/ala/profile/api/ApiController.groovy | 27 ++++++++++-- .../au/org/ala/profile/api/ApiService.groovy | 41 +++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/grails-app/controllers/au/org/ala/profile/api/ApiController.groovy b/grails-app/controllers/au/org/ala/profile/api/ApiController.groovy index 73d25ebe..83505ba5 100644 --- a/grails-app/controllers/au/org/ala/profile/api/ApiController.groovy +++ b/grails-app/controllers/au/org/ala/profile/api/ApiController.groovy @@ -328,6 +328,15 @@ class ApiController extends BaseController { type = "boolean", defaultValue = "false" )), + @Parameter(name = "onlyContent", + in = ParameterIn.QUERY, + required = false, + description = "if true, only return the species description and not additional information like opus metadata etc.", + schema = @Schema( + name = "onlyContent", + type = "boolean", + defaultValue = "false" + )), @Parameter(name = "Access-Token", in = ParameterIn.HEADER, required = false, @@ -354,14 +363,24 @@ class ApiController extends BaseController { boolean latest = false final fullClassification = true boolean includeImages = params.getBoolean('includeImages', false) - Map profileAndOpus = profileService.getProfile(params.opusId as String, params.profileId as String, latest, fullClassification) + boolean onlyContent = params.getBoolean('onlyContent', false) + Map profileAndOpus + if (onlyContent) { + profileAndOpus = apiService.getProfile(params.opusId as String, params.profileId as String, latest, fullClassification) + } + else { + profileAndOpus = profileService.getProfile(params.opusId as String, params.profileId as String, latest, fullClassification) + } if (!profileAndOpus) { notFound() } else { - String fullURL = grailsApplication.config.grails.serverURL + (request.contextPath ? "/${request.contextPath}" : "") - profileAndOpus.profile.mapSnapshot = mapService.getSnapshotImageUrlWithUUIDs(fullURL, profileAndOpus.opus.uuid, profileAndOpus.profile.uuid) - apiService.supplementProfileData(profileAndOpus, 20, includeImages) + if (!onlyContent) { + String fullURL = grailsApplication.config.grails.serverURL + (request.contextPath ? "/${request.contextPath}" : "") + profileAndOpus.profile.mapSnapshot = mapService.getSnapshotImageUrlWithUUIDs(fullURL, profileAndOpus.opus.uuid, profileAndOpus.profile.uuid) + apiService.supplementProfileData(profileAndOpus, 20, includeImages) + } + render profileAndOpus.profile as JSON } } diff --git a/grails-app/services/au/org/ala/profile/api/ApiService.groovy b/grails-app/services/au/org/ala/profile/api/ApiService.groovy index fe06f1f0..1f72721c 100644 --- a/grails-app/services/au/org/ala/profile/api/ApiService.groovy +++ b/grails-app/services/au/org/ala/profile/api/ApiService.groovy @@ -4,10 +4,16 @@ import au.org.ala.profile.hub.ImageService import au.org.ala.profile.hub.NslService import au.org.ala.profile.hub.ProfileService import au.org.ala.profile.hub.Utils +import au.org.ala.profile.hub.WebServiceWrapperService import grails.web.mapping.LinkGenerator +import org.apache.http.entity.ContentType import static au.org.ala.profile.hub.Utils.encPath +import static au.org.ala.profile.hub.util.HubConstants.getDEFAULT_OPUS_BANNER_URL +import static au.org.ala.profile.hub.util.HubConstants.getDEFAULT_OPUS_LOGOS +import static au.org.ala.profile.hub.util.HubConstants.getDEFAULT_OPUS_TITLE import static org.apache.http.HttpStatus.SC_OK +import static au.org.ala.profile.hub.Utils.* class ApiService { def grailsApplication @@ -15,6 +21,7 @@ class ApiService { ImageService imageService ProfileService profileService NslService nslService + WebServiceWrapperService webServiceWrapperService def getProfiles(String opusId, String startIndex = "", String pageSize = "", String sort = "", String order = "", String taxonName = "", String taxonRank = "", String rankFilter = "") { if (taxonName && taxonRank) { @@ -135,6 +142,40 @@ class ApiService { profile?.attributes?.findAll { attributes?.contains(it.uuid) || attributes?.contains(it.title?.toLowerCase()) } } + /** + * Faster profile lookup. + * + */ + def getProfile(String opusId, String profileId, boolean latest = false, Boolean fullClassification = false) { + log.debug("Loading profile " + profileId) + + Map result + + try { + String encodedProfileId = encPath(profileId) + def profile = webServiceWrapperService.get("${grailsApplication.config.profile.service.url}/opus/${encPath(opusId)}/profile/${encodedProfileId}?latest=${latest}&fullClassification=${fullClassification}", [:], ContentType.APPLICATION_JSON, true, false, profileService.getCustomHeaderWithUserId())?.resp + + if (!profile) { + return null + } + + profileService.injectThumbnailUrls(profile) + + result = [ + profile : profile + ] + + } catch (FileNotFoundException e) { + log.error("Profile ${profileId} not found") + result = null + } catch (Exception e) { + log.error("Failed to retrieve profile ${profileId}", e) + result = [error: "Failed to retrieve profile ${profileId} due to ${e.getMessage()}"] + } + + result + } + /** Returns true for HTTP status codes from 200 to 299 */ protected isSuccessful(int statusCode) { return statusCode >= SC_OK && statusCode <= 299