Analytic controller - improved caching

This commit is contained in:
Ralph Soika 2024-11-25 11:20:43 +01:00
parent 6c538355d7
commit c34ed64445
4 changed files with 73 additions and 36 deletions

View file

@ -84,8 +84,8 @@ public class AGLAnalyticControllerDebitor implements Serializable {
String chartData = ""; String chartData = "";
public void onEvent(@Observes AnalyticEvent event) { 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 // no op
return; return;
} }
@ -96,13 +96,20 @@ public class AGLAnalyticControllerDebitor implements Serializable {
// load all invoices? // load all invoices?
if (invoices == null || (!dbtrNumber.isEmpty() && !dbtrNumber.equals(dbtrNumberLast))) { if (invoices == null || (!dbtrNumber.isEmpty() && !dbtrNumber.equals(dbtrNumberLast))) {
resetStats(); resetStats(event);
event.getWorkitem().setItemValue("dbtr.number.last", dbtrNumber); event.getWorkitem().setItemValue("dbtr.number.last", dbtrNumber);
logger.info("Analyse new debitor data for : " + dbtrNumber); logger.info("Analyse new debitor data for : " + dbtrNumber);
loadRechnungen(); loadRechnungen(event);
chartData = buildChartData(); 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(); String link = "/pages/workitems/worklist.xhtml" + "?phrase=" + getDbtNr();
logger.fine("process ref=" + workflowController.getWorkitem().getItemValueString("process.ref")); logger.fine("process ref=" + workflowController.getWorkitem().getItemValueString("process.ref"));
ItemCollection process = documentService ItemCollection process = documentService
@ -185,7 +192,7 @@ public class AGLAnalyticControllerDebitor implements Serializable {
return label; return label;
} }
private void loadRechnungen() { private void loadRechnungen(AnalyticEvent event) {
if (getDbtNr().isEmpty()) { if (getDbtNr().isEmpty()) {
invoices = new ArrayList(); invoices = new ArrayList();
stats = null; stats = null;
@ -196,7 +203,7 @@ public class AGLAnalyticControllerDebitor implements Serializable {
try { try {
logger.info(" ├──refresh invoice stats for " + getDbtNr() + "...."); logger.info(" ├──refresh invoice stats for " + getDbtNr() + "....");
invoices = documentService.find(query, 999, 0, "$created", false); invoices = documentService.find(query, 999, 0, "$created", false);
calculateStats(); calculateStats(event);
} catch (QueryException e) { } catch (QueryException e) {
logger.warning("Failed to query invoices: " + query + " - Error: " + e.getMessage()); logger.warning("Failed to query invoices: " + query + " - Error: " + e.getMessage());
invoices = new ArrayList(); invoices = new ArrayList();
@ -208,7 +215,7 @@ public class AGLAnalyticControllerDebitor implements Serializable {
/** /**
* Läd die statistik daten zu einem debitor aus den aktuellen Rechnungen * Läd die statistik daten zu einem debitor aus den aktuellen Rechnungen
*/ */
private void calculateStats() { private void calculateStats(AnalyticEvent event) {
countAll = 0; countAll = 0;
countOpen = 0; countOpen = 0;
countDue = 0; countDue = 0;
@ -274,7 +281,7 @@ public class AGLAnalyticControllerDebitor implements Serializable {
} else { } else {
// reset data because no invoices are available ... // reset data because no invoices are available ...
resetStats(); resetStats(event);
} }
@ -283,7 +290,7 @@ public class AGLAnalyticControllerDebitor implements Serializable {
/** /**
* Setzt alle Statistikwerte zurück * Setzt alle Statistikwerte zurück
*/ */
private void resetStats() { private void resetStats(AnalyticEvent event) {
logger.info(" ├──reset stats for " + getDbtNr() + "...."); logger.info(" ├──reset stats for " + getDbtNr() + "....");
stats = null; stats = null;
@ -301,6 +308,16 @@ public class AGLAnalyticControllerDebitor implements Serializable {
averagePaymentDue = 0; averagePaymentDue = 0;
averagePaymentDays = 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() { private void getDurchschnittZahlungsziel() {

View file

@ -51,18 +51,18 @@ public class AGLAnalyticControllerOPListe implements Serializable {
String departmentID; String departmentID;
String departmentIDLast = null; String departmentIDLast = null;
String departmentName; // String departmentName;
ItemCollection department; ItemCollection department;
int countAll = 0; int countAll = 0;
int countOpen = 0; int countOpen = 0;
int countDue = 0; int countDue = 0;
int countDunning = 0; int countDunning = 0;
boolean refreshCalculation = true; boolean refreshCalculation = false;
public void onEvent(@Observes AnalyticEvent event) { 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 // no op
return; return;
} }
@ -70,25 +70,30 @@ public class AGLAnalyticControllerOPListe implements Serializable {
department = null; department = null;
departmentID = event.getWorkitem().getItemValueString("space.ref"); departmentID = event.getWorkitem().getItemValueString("space.ref");
if ((!departmentID.isEmpty() && !departmentID.equals(departmentIDLast))) { if (departmentIDLast == null || !departmentID.equals(departmentIDLast)) {
department = documentService.load(departmentID); department = documentService.load(departmentID);
departmentName = department.getItemValueString("name"); if (department != null) {
event.getWorkitem().setItemValue("space.name", department.getItemValueString("name"));
}
departmentIDLast = departmentID; departmentIDLast = departmentID;
resetStats(event);
calculateStats();
refreshCalculation = true; refreshCalculation = true;
} }
if (refreshCalculation) { // use cache?
calculateStats(); if (event.getWorkitem().hasItem(event.getKey())) {
refreshCalculation = false; // logger.info(" use cache for " + event.getKey());
// no op
return;
} }
String link = "/pages/workitems/worklist.xhtml"; String link = "/pages/workitems/worklist.xhtml";
logger.fine("process ref=" + workflowController.getWorkitem().getItemValueString("process.ref")); logger.fine("process ref=" + workflowController.getWorkitem().getItemValueString("process.ref"));
ItemCollection process = documentService ItemCollection process = documentService
.load(workflowController.getWorkitem().getItemValueString("process.ref")); .load(workflowController.getWorkitem().getItemValueString("process.ref"));
if (process != null) { if (process != null) {
link = link + "&processref=" + process.getUniqueID() link = link + "&processref=" + process.getUniqueID()
+ "&phrase=" + departmentName; + "&spaceref=" + departmentID;
} }
if ("analytic.invoices.count.all".equals(event.getKey())) { if ("analytic.invoices.count.all".equals(event.getKey())) {
event.setValue("" + countAll); 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 * Läd die statistik daten zu einem department die Anzahl an aktuellen
* Rechnungen zu ermitteln * Rechnungen zu ermitteln
@ -134,6 +150,7 @@ public class AGLAnalyticControllerOPListe implements Serializable {
* *
*/ */
private void calculateStats() { private void calculateStats() {
long l = System.currentTimeMillis();
countAll = 0; countAll = 0;
countOpen = 0; countOpen = 0;
countDue = 0; countDue = 0;
@ -161,6 +178,7 @@ public class AGLAnalyticControllerOPListe implements Serializable {
logger.warning("Failed to query invoices: " + e.getMessage()); logger.warning("Failed to query invoices: " + e.getMessage());
} }
logger.info(" ├──calculate stats took " + (System.currentTimeMillis() - l) + "ms");
} }

View file

@ -56,6 +56,12 @@ public class AGLAnalyticControllerSteuer implements Serializable {
public void onEvent(@Observes AnalyticEvent event) { public void onEvent(@Observes AnalyticEvent event) {
if (!"workitem".equals(event.getWorkitem().getType())
|| !event.getWorkitem().getModelVersion().startsWith("analyse-steuer")) {
// no op
return;
}
ItemCollection process = documentService ItemCollection process = documentService
.load(workflowController.getWorkitem().getItemValueString("process.ref")); .load(workflowController.getWorkitem().getItemValueString("process.ref"));
String link = "/pages/workitems/worklist.xhtml"; String link = "/pages/workitems/worklist.xhtml";

View file

@ -114,15 +114,17 @@ public class AnalyticController implements Serializable {
} }
/** /**
* Computes am analytic value. The method cache the value in the item * Computes an analytic value. The method cache the value in the
* 'analytic.KEY' to avoid feierring repeated AnalyticEvents. * item key.
*
* An observer controller is responsible to cache or reset the cached values if
* needed.
* *
* @param key * @param key
* @return * @return
*/ */
protected ItemCollection computeValue(String key) { protected ItemCollection computeValue(String key) {
if (workflowController.getWorkitem() != null) { if (workflowController.getWorkitem() != null) {
logger.fine("fire analytic event for key '" + key + "'"); logger.fine("fire analytic event for key '" + key + "'");
// Fire the Analytics Event for this key // Fire the Analytics Event for this key
AnalyticEvent event = new AnalyticEvent(key, workflowController.getWorkitem()); AnalyticEvent event = new AnalyticEvent(key, workflowController.getWorkitem());
@ -134,21 +136,10 @@ public class AnalyticController implements Serializable {
details.setItemValue("label", event.getLabel()); details.setItemValue("label", event.getLabel());
details.setItemValue("description", event.getDescription()); details.setItemValue("description", event.getDescription());
details.setItemValue("link", event.getLink()); details.setItemValue("link", event.getLink());
// cache result
implodeDetails(key, details); 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! // analytic value is now already cached!
@ -180,7 +171,12 @@ public class AnalyticController implements Serializable {
return itemCol; return itemCol;
} }
// return empty collection // return empty collection
return new ItemCollection(); ItemCollection dummy = new ItemCollection();
dummy.setItemValue("value", "");
dummy.setItemValue("label", "");
dummy.setItemValue("description", "No data available");
return dummy;
} }
} }