From c34ed644454d9711330248eff3462619dc11760e Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Mon, 25 Nov 2024 11:20:43 +0100 Subject: [PATCH] Analytic controller - improved caching --- .../AGLAnalyticControllerDebitor.java | 35 +++++++++++----- .../AGLAnalyticControllerOPListe.java | 40 ++++++++++++++----- .../AGLAnalyticControllerSteuer.java | 6 +++ .../office/forms/AnalyticController.java | 28 ++++++------- 4 files changed, 73 insertions(+), 36 deletions(-) diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerDebitor.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerDebitor.java index 631e973..81c382b 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerDebitor.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerDebitor.java @@ -84,8 +84,8 @@ public class AGLAnalyticControllerDebitor implements Serializable { String chartData = ""; public void onEvent(@Observes AnalyticEvent event) { - - if (!"workitem".equals(event.getWorkitem().getType())) { + if (!"workitem".equals(event.getWorkitem().getType()) + || !event.getWorkitem().getModelVersion().startsWith("analyse-debitor")) { // no op return; } @@ -96,13 +96,20 @@ public class AGLAnalyticControllerDebitor implements Serializable { // load all invoices? if (invoices == null || (!dbtrNumber.isEmpty() && !dbtrNumber.equals(dbtrNumberLast))) { - resetStats(); + resetStats(event); event.getWorkitem().setItemValue("dbtr.number.last", dbtrNumber); logger.info("Analyse new debitor data for : " + dbtrNumber); - loadRechnungen(); + loadRechnungen(event); chartData = buildChartData(); } + // use cache? + if (event.getWorkitem().hasItem(event.getKey())) { + // logger.info(" use cache for " + event.getKey()); + // no op + return; + } + String link = "/pages/workitems/worklist.xhtml" + "?phrase=" + getDbtNr(); logger.fine("process ref=" + workflowController.getWorkitem().getItemValueString("process.ref")); ItemCollection process = documentService @@ -185,7 +192,7 @@ public class AGLAnalyticControllerDebitor implements Serializable { return label; } - private void loadRechnungen() { + private void loadRechnungen(AnalyticEvent event) { if (getDbtNr().isEmpty()) { invoices = new ArrayList(); stats = null; @@ -196,7 +203,7 @@ public class AGLAnalyticControllerDebitor implements Serializable { try { logger.info(" ├──refresh invoice stats for " + getDbtNr() + "...."); invoices = documentService.find(query, 999, 0, "$created", false); - calculateStats(); + calculateStats(event); } catch (QueryException e) { logger.warning("Failed to query invoices: " + query + " - Error: " + e.getMessage()); invoices = new ArrayList(); @@ -208,7 +215,7 @@ public class AGLAnalyticControllerDebitor implements Serializable { /** * Läd die statistik daten zu einem debitor aus den aktuellen Rechnungen */ - private void calculateStats() { + private void calculateStats(AnalyticEvent event) { countAll = 0; countOpen = 0; countDue = 0; @@ -274,7 +281,7 @@ public class AGLAnalyticControllerDebitor implements Serializable { } else { // reset data because no invoices are available ... - resetStats(); + resetStats(event); } @@ -283,7 +290,7 @@ public class AGLAnalyticControllerDebitor implements Serializable { /** * Setzt alle Statistikwerte zurück */ - private void resetStats() { + private void resetStats(AnalyticEvent event) { logger.info(" ├──reset stats for " + getDbtNr() + "...."); stats = null; @@ -301,6 +308,16 @@ public class AGLAnalyticControllerDebitor implements Serializable { averagePaymentDue = 0; averagePaymentDays = 0; + + event.getWorkitem().removeItem("analytic.invoices.count.all"); + event.getWorkitem().removeItem("analytic.invoices.count.open"); + event.getWorkitem().removeItem("analytic.invoices.count.due"); + event.getWorkitem().removeItem("analytic.invoices.count.dunning"); + + event.getWorkitem().removeItem("analytic.payment.avg.due"); + event.getWorkitem().removeItem("analytic.payment.avg.days"); + event.getWorkitem().removeItem("analytic.invoices.trend"); + } private void getDurchschnittZahlungsziel() { diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerOPListe.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerOPListe.java index d318fee..b3d33e5 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerOPListe.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerOPListe.java @@ -51,18 +51,18 @@ public class AGLAnalyticControllerOPListe implements Serializable { String departmentID; String departmentIDLast = null; - String departmentName; + // String departmentName; ItemCollection department; int countAll = 0; int countOpen = 0; int countDue = 0; int countDunning = 0; - boolean refreshCalculation = true; + boolean refreshCalculation = false; public void onEvent(@Observes AnalyticEvent event) { - - if (!"workitem".equals(event.getWorkitem().getType())) { + if (!"workitem".equals(event.getWorkitem().getType()) + || !event.getWorkitem().getModelVersion().startsWith("analyse-opliste")) { // no op return; } @@ -70,25 +70,30 @@ public class AGLAnalyticControllerOPListe implements Serializable { department = null; departmentID = event.getWorkitem().getItemValueString("space.ref"); - if ((!departmentID.isEmpty() && !departmentID.equals(departmentIDLast))) { + if (departmentIDLast == null || !departmentID.equals(departmentIDLast)) { department = documentService.load(departmentID); - departmentName = department.getItemValueString("name"); + if (department != null) { + event.getWorkitem().setItemValue("space.name", department.getItemValueString("name")); + } departmentIDLast = departmentID; + resetStats(event); + calculateStats(); refreshCalculation = true; } - if (refreshCalculation) { - calculateStats(); - refreshCalculation = false; + // use cache? + if (event.getWorkitem().hasItem(event.getKey())) { + // logger.info(" use cache for " + event.getKey()); + // no op + return; } - String link = "/pages/workitems/worklist.xhtml"; logger.fine("process ref=" + workflowController.getWorkitem().getItemValueString("process.ref")); ItemCollection process = documentService .load(workflowController.getWorkitem().getItemValueString("process.ref")); if (process != null) { link = link + "&processref=" + process.getUniqueID() - + "&phrase=" + departmentName; + + "&spaceref=" + departmentID; } if ("analytic.invoices.count.all".equals(event.getKey())) { event.setValue("" + countAll); @@ -123,6 +128,17 @@ public class AGLAnalyticControllerOPListe implements Serializable { } + /** + * Reset cached analytic keys + */ + private void resetStats(AnalyticEvent event) { + event.getWorkitem().removeItem("analytic.invoices.count.all"); + event.getWorkitem().removeItem("analytic.invoices.count.open"); + event.getWorkitem().removeItem("analytic.invoices.count.due"); + event.getWorkitem().removeItem("analytic.invoices.count.dunning"); + + } + /** * Läd die statistik daten zu einem department die Anzahl an aktuellen * Rechnungen zu ermitteln @@ -134,6 +150,7 @@ public class AGLAnalyticControllerOPListe implements Serializable { * */ private void calculateStats() { + long l = System.currentTimeMillis(); countAll = 0; countOpen = 0; countDue = 0; @@ -161,6 +178,7 @@ public class AGLAnalyticControllerOPListe implements Serializable { logger.warning("Failed to query invoices: " + e.getMessage()); } + logger.info(" ├──calculate stats took " + (System.currentTimeMillis() - l) + "ms"); } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerSteuer.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerSteuer.java index 213189f..59d09ac 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerSteuer.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticControllerSteuer.java @@ -56,6 +56,12 @@ public class AGLAnalyticControllerSteuer implements Serializable { public void onEvent(@Observes AnalyticEvent event) { + if (!"workitem".equals(event.getWorkitem().getType()) + || !event.getWorkitem().getModelVersion().startsWith("analyse-steuer")) { + // no op + return; + } + ItemCollection process = documentService .load(workflowController.getWorkitem().getItemValueString("process.ref")); String link = "/pages/workitems/worklist.xhtml"; diff --git a/office-alexander-logistics-app/src/main/java/org/imixs/workflow/office/forms/AnalyticController.java b/office-alexander-logistics-app/src/main/java/org/imixs/workflow/office/forms/AnalyticController.java index 7c435cf..923a98c 100644 --- a/office-alexander-logistics-app/src/main/java/org/imixs/workflow/office/forms/AnalyticController.java +++ b/office-alexander-logistics-app/src/main/java/org/imixs/workflow/office/forms/AnalyticController.java @@ -114,15 +114,17 @@ public class AnalyticController implements Serializable { } /** - * Computes am analytic value. The method cache the value in the item - * 'analytic.KEY' to avoid feierring repeated AnalyticEvents. + * Computes an analytic value. The method cache the value in the + * item key. + * + * An observer controller is responsible to cache or reset the cached values if + * needed. * * @param key * @return */ protected ItemCollection computeValue(String key) { if (workflowController.getWorkitem() != null) { - logger.fine("fire analytic event for key '" + key + "'"); // Fire the Analytics Event for this key AnalyticEvent event = new AnalyticEvent(key, workflowController.getWorkitem()); @@ -134,21 +136,10 @@ public class AnalyticController implements Serializable { details.setItemValue("label", event.getLabel()); details.setItemValue("description", event.getDescription()); details.setItemValue("link", event.getLink()); + // cache result implodeDetails(key, details); } } - - // try loading from cache - ItemCollection details = explodeDetails(key); - if (details == null) { - // set dummy value - details = new ItemCollection(); - details.setItemValue("value", ""); - details.setItemValue("label", ""); - details.setItemValue("description", "No data available"); - implodeDetails(key, details); - } - } // analytic value is now already cached! @@ -180,7 +171,12 @@ public class AnalyticController implements Serializable { return itemCol; } // return empty collection - return new ItemCollection(); + ItemCollection dummy = new ItemCollection(); + dummy.setItemValue("value", ""); + dummy.setItemValue("label", ""); + dummy.setItemValue("description", "No data available"); + + return dummy; } }