package org.joget.workflow.shark; import org.joget.commons.util.LogUtil; import org.joget.workflow.model.service.WorkflowManager; import org.joget.workflow.util.WorkflowUtil; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.enhydra.shark.client.utilities.LimitStruct; import org.enhydra.shark.utilities.MiscUtilities; import org.joget.commons.util.HostManager; import org.springframework.context.i18n.LocaleContext; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.web.servlet.LocaleContextResolver; public class DeadlineChecker extends Thread { protected String profile; protected long delay; protected int instancesPerTransaction; protected int failuresToIgnore; protected boolean stopped = true; protected List limitStructs; protected boolean isInitialized = false; protected boolean deadlineReeval = false; public DeadlineChecker(String profile, List limitStructs, long delay, int instPerTrans, int failToIgnore, boolean startImmediatelly) { this.profile = profile; this.limitStructs = limitStructs; this.delay = delay; this.setDaemon(true); this.instancesPerTransaction = instPerTrans; this.failuresToIgnore = failToIgnore; if (startImmediatelly) { startChecker(); } LogUtil.info(getClass().getName(), "Deadline checking time initialized to " + delay + " ms. Deadline times: " + limitStructs + ". Checking " + instancesPerTransaction + " instances per transaction, ignoring " + failuresToIgnore + " failures for profile " + profile); } public String getProfile() { return profile; } public void setProfile(String profile) { this.profile = profile; } public long getDelay() { return delay; } public void setDelay(long delay) { this.delay = delay; } public List getLimitStructs() { return this.limitStructs; } public void setLimitStructs(List ls) { this.limitStructs = ls; } public void setLimitStructsByString(String str) { List lcStrLst = new ArrayList(); try { String[] lcStructs = MiscUtilities.tokenize(str, ","); if (lcStructs != null) { for (int i = 0; i < lcStructs.length; i++) { String lcstruct = lcStructs[i]; try { String[] hma = MiscUtilities.tokenize(lcstruct, ":"); String h = hma[0]; String m = hma[1]; String a = hma[2]; lcStrLst.add(new LimitStruct(Integer.parseInt(h), Integer.parseInt(m), Integer.parseInt(a))); } catch (Exception ex) { } } } } catch (Exception ex) { System.err.println("DeadlineChecker: Problem while setting limit structures through string!"); } setLimitStructs(lcStrLst); } public int getInstancesPerTransaction() { return instancesPerTransaction; } public void setInstancesPerTransaction(int insPerTrans) { this.instancesPerTransaction = insPerTrans; } public int getFailuresToIgnore() { return failuresToIgnore; } public void setFailuresToIgnore(int failToIgnore) { this.failuresToIgnore = failToIgnore; } public void stopChecker() { stopped = true; } public void startChecker() { stopped = false; if (!isInitialized) { isInitialized = true; start(); } } @Override public void run() { while (true) { try { sleep(delay); if (!stopped) { runMe(); } } catch (Exception ex) { LogUtil.error(getClass().getName(), ex, ""); } } } protected void runMe() { try { LogUtil.debug(getClass().getName(), "Checking deadlines for profile " + profile); long start = System.currentTimeMillis(); HostManager.setCurrentProfile(profile); WorkflowManager workflowManager = (WorkflowManager) WorkflowUtil.getApplicationContext().getBean("workflowManager"); LocaleContextResolver localeResolver = (LocaleContextResolver) WorkflowUtil.getApplicationContext().getBean("localeResolver"); if (localeResolver != null) { LocaleContext localeContext = localeResolver.resolveLocaleContext(null); LocaleContextHolder.setLocaleContext(localeContext, true); } int sizeToCheck = 0; List<String> instancesFailed2check = new ArrayList<String>(); Collection<String> instancesToCheck = workflowManager.getRunningProcessIds(); if (instancesToCheck != null && !instancesToCheck.isEmpty()) { sizeToCheck = instancesToCheck.size(); Iterator iterProcesses = instancesToCheck.iterator(); List<String> currentBatch = null; do { currentBatch = new ArrayList<String>(); try { for (int n = 0; n < this.instancesPerTransaction; ++n) { if (!iterProcesses.hasNext()) { break; } String procId = (String) iterProcesses.next(); iterProcesses.remove(); currentBatch.add(procId); } String[] pids = new String[currentBatch.size()]; currentBatch.toArray(pids); workflowManager.internalCheckDeadlines(pids); } catch (Exception ex) { LogUtil.error(getClass().getName(), ex, "Profile : " + profile); instancesFailed2check.addAll(currentBatch); } } while (instancesFailed2check.size() <= this.failuresToIgnore && iterProcesses.hasNext()); } long end = System.currentTimeMillis(); LogUtil.debug(getClass().getName(), "Deadline check lasted " + (end - start) + " ms for profile " + profile + ". Checked:" + sizeToCheck + ". Failed:" + instancesFailed2check.size()); } catch (Exception e) { LogUtil.error(getClass().getName(), e, ""); } } public boolean isStopped(){ return stopped; } }