From ba7a0fcf829bdda22d113538c91b331c8808c6a6 Mon Sep 17 00:00:00 2001 From: AJAL ODORA JONATHAN <43242517+ODORA0@users.noreply.github.com> Date: Fri, 29 Nov 2024 08:23:31 +0300 Subject: [PATCH] DB-level pagination to only load in memory obs for current page --- .../web/controller/PortletController.java | 85 ++++++++++++------- 1 file changed, 55 insertions(+), 30 deletions(-) diff --git a/omod/src/main/java/org/openmrs/web/controller/PortletController.java b/omod/src/main/java/org/openmrs/web/controller/PortletController.java index 512161a0..1062a5c9 100644 --- a/omod/src/main/java/org/openmrs/web/controller/PortletController.java +++ b/omod/src/main/java/org/openmrs/web/controller/PortletController.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -29,6 +30,7 @@ import org.openmrs.Concept; import org.openmrs.ConceptNumeric; import org.openmrs.Encounter; +import org.openmrs.Location; import org.openmrs.Obs; import org.openmrs.Patient; import org.openmrs.Person; @@ -39,6 +41,7 @@ import org.openmrs.api.ConceptService; import org.openmrs.api.context.Context; import org.openmrs.module.legacyui.GeneralUtils; +import org.openmrs.util.OpenmrsConstants.PERSON_TYPE; import org.openmrs.util.PrivilegeConstants; import org.openmrs.web.WebConstants; import org.springframework.util.StringUtils; @@ -103,18 +106,19 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons AdministrationService as = Context.getAdministrationService(); ConceptService cs = Context.getConceptService(); - + // find the portlet that was identified in the openmrs:portlet taglib Object uri = request.getAttribute("javax.servlet.include.servlet_path"); String portletPath = ""; Map model = null; + { HttpSession session = request.getSession(); String uniqueRequestId = (String) request.getAttribute(WebConstants.INIT_REQ_UNIQUE_ID); String lastRequestId = (String) session.getAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID); if (uniqueRequestId.equals(lastRequestId)) { model = (Map) session.getAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL); - + // remove cached parameters List parameterKeys = (List) model.get("parameterKeys"); if (parameterKeys != null) { @@ -130,11 +134,11 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons session.setAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL, model); } } - + if (uri != null) { long timeAtStart = System.currentTimeMillis(); portletPath = uri.toString(); - + // Allowable extensions are '' (no extension) and '.portlet' if (portletPath.endsWith("portlet")) { portletPath = portletPath.replace(".portlet", ""); @@ -162,7 +166,7 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons parameterKeys.addAll(moreParams.keySet()); } model.put("parameterKeys", parameterKeys); // so we can clean these up in the next request - + // if there's an authenticated user, put them, and their patient set, in the // model if (Context.getAuthenticatedUser() != null) { @@ -202,18 +206,32 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons Integer page = getPageParameter(request); Integer pageSize = getPageSizeParameter(request, as); - // Get all observations - List allObs = Context.getObsService().getObservationsByPerson(p); + Person person = (Person) p; + List persons = Collections.singletonList(person); - // Manual pagination - int startIndex = page * pageSize; - int endIndex = Math.min(startIndex + pageSize, allObs.size()); - List paginatedObs = allObs.subList(startIndex, endIndex); + // Setup parameters for database-level pagination + List encounters = null; + List questions = null; + List answers = null; + List personTypes = null; + List locations = null; + List sort = Collections.singletonList("obsDatetime desc"); + Integer obsGroupId = null; + Date fromDate = null; + Date toDate = null; + boolean includeVoided = false; + + // Get observations for the current page + List paginatedObs = Context.getObsService().getObservations(persons, encounters, questions, + answers, personTypes, locations, sort, null, obsGroupId, fromDate, toDate, includeVoided); + + // Get total count for pagination + Integer totalCount = Context.getObsService().getObservationCount(persons, encounters, questions, + answers, personTypes, locations, obsGroupId, fromDate, toDate, includeVoided); - // Add pagination metadata to the model model.put("currentPage", page); model.put("pageSize", pageSize); - model.put("totalObsCount", allObs.size()); + model.put("totalObsCount", totalCount); model.put("patientObs", paginatedObs); Obs latestWeight = null; @@ -231,27 +249,34 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons heightConcept = cs.getConceptNumeric(GeneralUtils.getConcept(heightString).getConceptId()); } - // Use allObs for weight/height calculation since we need all records to find - // the latest - for (Obs obs : allObs) { - if (obs.getConcept().equals(weightConcept)) { - if (latestWeight == null - || obs.getObsDatetime().compareTo(latestWeight.getObsDatetime()) > 0) { - latestWeight = obs; - } - } else if (obs.getConcept().equals(heightConcept) - && (latestHeight == null || obs.getObsDatetime().compareTo( - latestHeight.getObsDatetime()) > 0)) { - latestHeight = obs; + if (weightConcept != null) { + List weightQuestions = Collections.singletonList(weightConcept); + List weightSort = Collections.singletonList("obsDatetime desc"); + + List weightObs = Context.getObsService().getObservations(persons, null, + weightQuestions, null, null, null, weightSort, 1, null, null, null, false); + + if (!weightObs.isEmpty()) { + latestWeight = weightObs.get(0); } } - if (latestWeight != null) { - model.put("patientWeight", latestWeight); - } - if (latestHeight != null) { - model.put("patientHeight", latestHeight); + + if (heightConcept != null) { + List heightQuestions = Collections.singletonList(heightConcept); + List heightSort = Collections.singletonList("obsDatetime desc"); + + List heightObs = Context.getObsService().getObservations(persons, null, + heightQuestions, null, null, null, heightSort, 1, null, null, null, false); + + if (!heightObs.isEmpty()) { + latestHeight = heightObs.get(0); + } } + if (latestWeight != null && latestHeight != null) { + model.put("patientWeight", latestWeight); + model.put("patientHeight", latestHeight); + double weightInKg; double heightInM; if (weightConcept.getUnits().equalsIgnoreCase("kg")) {