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

LUI-198: Optimize patient dashboard loading by implementing pagination for observations #209

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public class PortletController implements Controller {

protected Log log = LogFactory.getLog(this.getClass());

private static final int DEFAULT_PAGE_SIZE = 50;

/**
* This method produces a model containing the following mappings:
*
Expand Down Expand Up @@ -101,7 +103,7 @@ 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 = "";
Expand All @@ -112,8 +114,8 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons
String lastRequestId = (String) session.getAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID);
if (uniqueRequestId.equals(lastRequestId)) {
model = (Map<String, Object>) session.getAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL);
// remove cached parameters

// remove cached parameters
List<String> parameterKeys = (List<String>) model.get("parameterKeys");
if (parameterKeys != null) {
for (String key : parameterKeys) {
Expand All @@ -128,11 +130,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", "");
Expand Down Expand Up @@ -160,8 +162,9 @@ 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 there's an authenticated user, put them, and their patient set, in the
// model
if (Context.getAuthenticatedUser() != null) {
model.put("authenticatedUser", Context.getAuthenticatedUser());
}
Expand Down Expand Up @@ -195,8 +198,24 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons
}

if (Context.hasPrivilege(PrivilegeConstants.GET_OBS)) {
List<Obs> patientObs = Context.getObsService().getObservationsByPerson(p);
model.put("patientObs", patientObs);
// Get pagination parameters
Integer page = getPageParameter(request);
Integer pageSize = getPageSizeParameter(request, as);

// Get all observations
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each time that one moves through the pages, you are still fetching and loading all the patient's observations in memory. My impression was that you would load in memory only those observations for the current page.

List<Obs> allObs = Context.getObsService().getObservationsByPerson(p);

// Manual pagination
int startIndex = page * pageSize;
int endIndex = Math.min(startIndex + pageSize, allObs.size());
List<Obs> paginatedObs = allObs.subList(startIndex, endIndex);

// Add pagination metadata to the model
model.put("currentPage", page);
model.put("pageSize", pageSize);
model.put("totalObsCount", allObs.size());
model.put("patientObs", paginatedObs);

Obs latestWeight = null;
Obs latestHeight = null;
String bmiAsString = "?";
Expand All @@ -211,7 +230,10 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons
if (StringUtils.hasLength(heightString)) {
heightConcept = cs.getConceptNumeric(GeneralUtils.getConcept(heightString).getConceptId());
}
for (Obs obs : patientObs) {

// 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) {
Expand Down Expand Up @@ -354,7 +376,8 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons
}
}

// if an encounter id is available, put "encounter" and "encounterObs" in the model
// if an encounter id is available, put "encounter" and "encounterObs" in the
// model
o = request.getAttribute("org.openmrs.portlet.encounterId");
if (o != null && !model.containsKey("encounterId")) {
if (!model.containsKey("encounter") && Context.hasPrivilege(PrivilegeConstants.GET_ENCOUNTERS)) {
Expand Down Expand Up @@ -425,4 +448,31 @@ public ModelAndView handleRequest(HttpServletRequest request, HttpServletRespons
protected void populateModel(HttpServletRequest request, Map<String, Object> model) {
}

private Integer getPageParameter(HttpServletRequest request) {
try {
return Integer.parseInt(request.getParameter("page"));
}
catch (NumberFormatException e) {
return 0;
}
}

private Integer getPageSizeParameter(HttpServletRequest request, AdministrationService as) {
try {
String pageSizeParam = request.getParameter("pageSize");
if (pageSizeParam != null) {
return Integer.parseInt(pageSizeParam);
}

String globalPageSize = as.getGlobalProperty("dashboard.defaultPageSize");
if (globalPageSize != null) {
return Integer.parseInt(globalPageSize);
}
}
catch (NumberFormatException e) {
log.debug("Unable to parse page size parameter, using default", e);
}
return DEFAULT_PAGE_SIZE;
}

}
Loading