Merge branch 'origin/release-7.1'

This commit is contained in:
hengsin 2020-04-02 10:01:29 +08:00
commit ee4ec74a88
5 changed files with 72 additions and 70 deletions

View File

@ -29,6 +29,7 @@ import org.atmosphere.cpr.AtmosphereResource;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.zkoss.lang.Library; import org.zkoss.lang.Library;
import org.zkoss.zk.au.out.AuEcho;
import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.au.out.AuScript;
import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.DesktopUnavailableException; import org.zkoss.zk.ui.DesktopUnavailableException;
@ -62,6 +63,7 @@ public class AtmosphereServerPush implements ServerPush {
private ExecutionCarryOver _carryOver; private ExecutionCarryOver _carryOver;
private final Object _mutex = new Object(); private final Object _mutex = new Object();
private List<Schedule<Event>> schedules = new ArrayList<>(); private List<Schedule<Event>> schedules = new ArrayList<>();
private long lastPiggyBack = 0;
public AtmosphereServerPush() { public AtmosphereServerPush() {
String timeoutString = Library.getProperty("fi.jawsy.jawwa.zk.atmosphere.timeout"); String timeoutString = Library.getProperty("fi.jawsy.jawwa.zk.atmosphere.timeout");
@ -162,6 +164,7 @@ public class AtmosphereServerPush implements ServerPush {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void onPiggyback() { public void onPiggyback() {
lastPiggyBack = System.currentTimeMillis();
Schedule<Event>[] pendings = null; Schedule<Event>[] pendings = null;
synchronized (schedules) { synchronized (schedules) {
if (!schedules.isEmpty()) { if (!schedules.isEmpty()) {
@ -171,6 +174,7 @@ public class AtmosphereServerPush implements ServerPush {
} }
if (pendings != null && pendings.length > 0) { if (pendings != null && pendings.length > 0) {
for(Schedule<Event> p : pendings) { for(Schedule<Event> p : pendings) {
//schedule and execute in desktop's onPiggyBack listener
p.scheduler.schedule(p.task, p.event); p.scheduler.schedule(p.task, p.event);
} }
} }
@ -180,53 +184,54 @@ public class AtmosphereServerPush implements ServerPush {
@Override @Override
public <T extends Event> void schedule(EventListener<T> task, T event, public <T extends Event> void schedule(EventListener<T> task, T event,
Scheduler<T> scheduler) { Scheduler<T> scheduler) {
if (Executions.getCurrent() == null) { if (Executions.getCurrent() == null) {
//save for schedule at on piggyback event //schedule and execute in desktop's onPiggyBack listener
synchronized (schedules) { scheduler.schedule(task, event);
schedules.add(new Schedule(task, event, scheduler)); boolean ok = false;
}
boolean ok = false;
try { try {
ok = commitResponse(); ok = commitResponse();
} catch (IOException e) { } catch (IOException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
if (!ok) { if (!ok) {
long l = lastPiggyBack;
for(int i = 0; i < 3 && !ok; i++) { for(int i = 0; i < 3 && !ok; i++) {
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e1) {} } catch (InterruptedException e1) {}
if (schedules.size() > 0) { if (l == lastPiggyBack) {
try { try {
ok = commitResponse(); ok = commitResponse();
} catch (IOException e) { } catch (IOException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
} else { } else {
ok = true; ok = true;
} }
} }
if (!ok) { if (!ok) {
Desktop d = desktop.get(); Desktop d = desktop.get();
log.warn("Failed to resume long polling resource" + (d != null ? " for desktop " + d.getId() : "")); log.warn("Failed to resume long polling resource" + (d != null ? " for desktop " + d.getId() : ""));
if (d != null) { if (d != null) {
Integer count = (Integer) d.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); AdempiereWebUI.increaseScheduleFailures(d);
if (count != null)
count = Integer.valueOf(count.intValue()+1);
else
count = Integer.valueOf(1);
d.setAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES, count);
} }
} }
} }
} else { } else {
//in event listener thread, can schedule immediately // in event listener thread, use echo to execute async
scheduler.schedule(task, event); synchronized (schedules) {
schedules.add(new Schedule(task, event, scheduler));
}
if (Executions.getCurrent().getAttribute("AtmosphereServerPush.Echo") == null) {
Executions.getCurrent().setAttribute("AtmosphereServerPush.Echo", Boolean.TRUE);
Clients.response(new AuEcho());
}
} }
} }
@Override @Override
public void start(Desktop desktop) { public void start(Desktop desktop) {
Desktop oldDesktop = this.desktop.getAndSet(desktop); Desktop oldDesktop = this.desktop.getAndSet(desktop);
if (oldDesktop != null) { if (oldDesktop != null) {

View File

@ -594,4 +594,31 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
} }
return uploadSetting.toString(); return uploadSetting.toString();
} }
/**
* Increase server push schedule failures count
* @param d
*/
public static void increaseScheduleFailures(Desktop d) {
Integer count = (Integer) d.getAttribute(SERVERPUSH_SCHEDULE_FAILURES);
if (count != null)
count = Integer.valueOf(count.intValue()+1);
else
count = Integer.valueOf(1);
d.setAttribute(SERVERPUSH_SCHEDULE_FAILURES, count);
}
/**
*
* @param d
* @return server push schedule failures count
*/
public static int getScheduleFailures(Desktop d) {
int failures = 0;
Object attr = d.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES);
if (attr != null && attr instanceof Integer)
failures = ((Integer)attr).intValue();
return failures;
}
} }

View File

@ -31,13 +31,11 @@ import org.adempiere.base.event.EventManager;
import org.adempiere.base.event.IEventManager; import org.adempiere.base.event.IEventManager;
import org.adempiere.base.event.IEventTopics; import org.adempiere.base.event.IEventTopics;
import org.adempiere.model.MBroadcastMessage; import org.adempiere.model.MBroadcastMessage;
import org.adempiere.util.ServerContext;
import org.adempiere.webui.ClientInfo; import org.adempiere.webui.ClientInfo;
import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.adwindow.ADWindow; import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.apps.BusyDialog; import org.adempiere.webui.apps.BusyDialog;
import org.adempiere.webui.apps.DesktopRunnable;
import org.adempiere.webui.apps.ProcessDialog; import org.adempiere.webui.apps.ProcessDialog;
import org.adempiere.webui.apps.WReport; import org.adempiere.webui.apps.WReport;
import org.adempiere.webui.component.Tab; import org.adempiere.webui.component.Tab;
@ -54,15 +52,11 @@ import org.adempiere.webui.panel.BroadcastMessageWindow;
import org.adempiere.webui.panel.HeaderPanel; import org.adempiere.webui.panel.HeaderPanel;
import org.adempiere.webui.panel.HelpController; import org.adempiere.webui.panel.HelpController;
import org.adempiere.webui.panel.TimeoutPanel; import org.adempiere.webui.panel.TimeoutPanel;
import org.adempiere.webui.session.SessionContextListener;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.IServerPushCallback;
import org.adempiere.webui.util.ServerPushTemplate;
import org.adempiere.webui.util.UserPreference; import org.adempiere.webui.util.UserPreference;
import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.util.ZKUpdateUtil;
import org.adempiere.webui.window.FDialog; import org.adempiere.webui.window.FDialog;
import org.compiere.Adempiere;
import org.compiere.model.GridField; import org.compiere.model.GridField;
import org.compiere.model.GridTab; import org.compiere.model.GridTab;
import org.compiere.model.I_AD_Preference; import org.compiere.model.I_AD_Preference;
@ -382,30 +376,10 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
layout.getDesktop().enableServerPush(true); layout.getDesktop().enableServerPush(true);
} }
Runnable runnable = new Runnable() { Executions.schedule(layout.getDesktop(), event -> {
public void run() { renderHomeTab();
try { automaticOpen(Env.getCtx());
Thread.sleep(100); }, new Event("onRenderHomeTab"));
} catch (InterruptedException e) {}
IServerPushCallback callback = new IServerPushCallback() {
public void updateUI() {
Properties ctx = (Properties)layout.getDesktop().getSession().getAttribute(SessionContextListener.SESSION_CTX);
try {
ServerContext.setCurrentInstance(ctx);
renderHomeTab();
automaticOpen(ctx);
} finally {
ServerContext.dispose();
}
}
};
ServerPushTemplate template = new ServerPushTemplate(layout.getDesktop());
template.executeAsync(callback);
}
};
Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(runnable,layout.getDesktop()));
ToolBar toolbar = windowContainer.getToobar(); ToolBar toolbar = windowContainer.getToobar();

View File

@ -918,11 +918,8 @@ ContextMenuListener, IZoomableEditor
} }
private void refreshLookupList() { private void refreshLookupList() {
int failures = 0;
Desktop desktop = editor.getComponent().getDesktop(); Desktop desktop = editor.getComponent().getDesktop();
Object attr = desktop.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); int failures = AdempiereWebUI.getScheduleFailures(desktop);
if (attr != null && attr instanceof Integer)
failures = ((Integer)attr).intValue();
Executions.schedule(desktop, new EventListener<Event>() { Executions.schedule(desktop, new EventListener<Event>() {
@Override @Override
public void onEvent(Event event) { public void onEvent(Event event) {
@ -932,12 +929,9 @@ ContextMenuListener, IZoomableEditor
} catch (Exception e) {} } catch (Exception e) {}
} }
}, new Event("onResetLookupList")); }, new Event("onResetLookupList"));
attr = desktop.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); int f = AdempiereWebUI.getScheduleFailures(desktop);
if (attr != null && attr instanceof Integer) { if (f > failures) {
int f = ((Integer)attr).intValue(); ((ITableDirEditor)editor.getComponent()).cleanup();
if (f > failures) {
((ITableDirEditor)editor.getComponent()).cleanup();
}
} }
} }

View File

@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.AdempiereWebUI;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.zkoss.zk.au.out.AuEcho;
import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.au.out.AuScript;
import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.DesktopUnavailableException; import org.zkoss.zk.ui.DesktopUnavailableException;
@ -177,6 +178,7 @@ public class WebSocketServerPush implements ServerPush {
} }
if (pendings != null && pendings.length > 0) { if (pendings != null && pendings.length > 0) {
for(Schedule<Event> p : pendings) { for(Schedule<Event> p : pendings) {
//schedule and execute in desktop's onPiggyBack listener
p.scheduler.schedule(p.task, p.event); p.scheduler.schedule(p.task, p.event);
} }
} }
@ -199,25 +201,25 @@ public class WebSocketServerPush implements ServerPush {
public <T extends Event> void schedule(EventListener<T> task, T event, public <T extends Event> void schedule(EventListener<T> task, T event,
Scheduler<T> scheduler) { Scheduler<T> scheduler) {
if (Executions.getCurrent() == null) { if (Executions.getCurrent() == null) {
//save for schedule at on piggyback event //schedule and execute in desktop's onPiggyBack listener
synchronized (schedules) { scheduler.schedule(task, event);
schedules.add(new Schedule(task, event, scheduler));
}
boolean ok = echo(); boolean ok = echo();
if (!ok) { if (!ok) {
Desktop d = desktop.get(); Desktop d = desktop.get();
log.warn("Failed to resume long polling resource" + (d != null ? " for desktop " + d.getId() : ""));
if (d != null) { if (d != null) {
Integer count = (Integer) d.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); AdempiereWebUI.increaseScheduleFailures(d);
if (count != null)
count = Integer.valueOf(count.intValue()+1);
else
count = Integer.valueOf(1);
d.setAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES, count);
} }
} }
} else { } else {
//in event listener thread, can schedule immediately // in event listener thread, use echo to execute async
scheduler.schedule(task, event); synchronized (schedules) {
schedules.add(new Schedule(task, event, scheduler));
}
if (Executions.getCurrent().getAttribute("AtmosphereServerPush.Echo") == null) {
Executions.getCurrent().setAttribute("AtmosphereServerPush.Echo", Boolean.TRUE);
Clients.response(new AuEcho());
}
} }
} }