IDEMPIERE-4628 Implement configurable query timeout for info window (#532)
* IDEMPIERE-4628 Implement configurable query timeout for info window * IDEMPIERE-4628 Implement configurable query timeout for info window Move migration script from i8.2z to i8.2
This commit is contained in:
parent
1afe4fe0c6
commit
59b83c3361
|
@ -0,0 +1,18 @@
|
||||||
|
SET SQLBLANKLINES ON
|
||||||
|
SET DEFINE OFF
|
||||||
|
|
||||||
|
-- Jan 18, 2021, 1:40:41 PM MYT
|
||||||
|
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200169,0,0,TO_DATE('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_INFO_QUERY_TIME_OUT','120','Query timeout in seconds for info window. 0 means no timeout.','D','C','f5953385-1c8a-4df2-92dd-ad46aaeefb8e')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Jan 18, 2021, 1:47:51 PM MYT
|
||||||
|
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The search took too long to return results. Please refine your search criteria.',0,0,'Y',TO_DATE('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,200655,'INFO_QUERY_TIME_OUT_ERROR','D','ea2c33af-7c98-4208-8ed0-ea59b7f0ec58')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Jan 18, 2021, 2:20:33 PM MYT
|
||||||
|
UPDATE AD_Message SET Value='InfoQueryTimeOutError',Updated=TO_DATE('2021-01-18 14:20:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200655
|
||||||
|
;
|
||||||
|
|
||||||
|
SELECT register_migration_script('202001180600_IDEMPIERE-4628.sql') FROM dual
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
-- Jan 18, 2021, 1:40:41 PM MYT
|
||||||
|
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200169,0,0,TO_TIMESTAMP('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2021-01-18 13:40:40','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_INFO_QUERY_TIME_OUT','120','Query timeout in seconds for info window. 0 means no timeout.','D','C','f5953385-1c8a-4df2-92dd-ad46aaeefb8e')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Jan 18, 2021, 1:47:51 PM MYT
|
||||||
|
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The search took too long to return results. Please refine your search criteria.',0,0,'Y',TO_TIMESTAMP('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-01-18 13:47:50','YYYY-MM-DD HH24:MI:SS'),100,200655,'INFO_QUERY_TIME_OUT_ERROR','D','ea2c33af-7c98-4208-8ed0-ea59b7f0ec58')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Jan 18, 2021, 2:20:33 PM MYT
|
||||||
|
UPDATE AD_Message SET Value='InfoQueryTimeOutError',Updated=TO_TIMESTAMP('2021-01-18 14:20:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200655
|
||||||
|
;
|
||||||
|
|
||||||
|
SELECT register_migration_script('202001180600_IDEMPIERE-4628.sql') FROM dual
|
||||||
|
;
|
|
@ -20,6 +20,7 @@ import java.math.BigDecimal;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.Driver;
|
import java.sql.Driver;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLTimeoutException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
@ -468,6 +469,13 @@ public interface AdempiereDatabase
|
||||||
*/
|
*/
|
||||||
public String getSQLModify (MTable table, MColumn column, boolean setNullOption);
|
public String getSQLModify (MTable table, MColumn column, boolean setNullOption);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param ex
|
||||||
|
* @return true if ex is caused by query timeout
|
||||||
|
*/
|
||||||
|
public default boolean isQueryTimeout(SQLException ex) {
|
||||||
|
return ex instanceof SQLTimeoutException;
|
||||||
|
}
|
||||||
} // AdempiereDatabase
|
} // AdempiereDatabase
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,7 @@ public class MSysConfig extends X_AD_SysConfig
|
||||||
public static final String ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR = "ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR";
|
public static final String ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR = "ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR";
|
||||||
public static final String ZK_GRID_VIEW_USE_DEFER_RENDERING = "ZK_GRID_VIEW_USE_DEFER_RENDERING";
|
public static final String ZK_GRID_VIEW_USE_DEFER_RENDERING = "ZK_GRID_VIEW_USE_DEFER_RENDERING";
|
||||||
public static final String ZK_INFO_NUM_PAGE_PRELOAD = "ZK_INFO_NUM_PAGE_PRELOAD";
|
public static final String ZK_INFO_NUM_PAGE_PRELOAD = "ZK_INFO_NUM_PAGE_PRELOAD";
|
||||||
|
public static final String ZK_INFO_QUERY_TIME_OUT = "ZK_INFO_QUERY_TIME_OUT";
|
||||||
public static final String ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD = "ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD";
|
public static final String ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD = "ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD";
|
||||||
public static final String ZK_LOGIN_ALLOW_REMEMBER_ME = "ZK_LOGIN_ALLOW_REMEMBER_ME";
|
public static final String ZK_LOGIN_ALLOW_REMEMBER_ME = "ZK_LOGIN_ALLOW_REMEMBER_ME";
|
||||||
public static final String ZK_LOGO_LARGE = "ZK_LOGO_LARGE";
|
public static final String ZK_LOGO_LARGE = "ZK_LOGO_LARGE";
|
||||||
|
|
|
@ -1930,6 +1930,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
*/
|
*/
|
||||||
protected boolean testCount(boolean promptError)
|
protected boolean testCount(boolean promptError)
|
||||||
{
|
{
|
||||||
|
if (useQueryTimeoutFromSysConfig)
|
||||||
|
queryTimeout = MSysConfig.getIntValue(MSysConfig.ZK_INFO_QUERY_TIME_OUT, 0, Env.getAD_Client_ID(Env.getCtx()));
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
String dynWhere = getSQLWhere();
|
String dynWhere = getSQLWhere();
|
||||||
StringBuilder sql = new StringBuilder (m_sqlMain);
|
StringBuilder sql = new StringBuilder (m_sqlMain);
|
||||||
|
@ -1972,7 +1975,17 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.log(Level.SEVERE, countSql, e);
|
if (e instanceof SQLException && DB.getDatabase().isQueryTimeout((SQLException) e))
|
||||||
|
{
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.log(Level.INFO, countSql, e);
|
||||||
|
FDialog.error(p_WindowNo, INFO_QUERY_TIME_OUT_ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.log(Level.SEVERE, countSql, e);
|
||||||
|
FDialog.error(p_WindowNo, "DBExecuteError", e.getMessage());
|
||||||
|
}
|
||||||
m_count = -2;
|
m_count = -2;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
@ -67,6 +67,7 @@ import org.adempiere.webui.part.ITabOnSelectHandler;
|
||||||
import org.adempiere.webui.part.WindowContainer;
|
import org.adempiere.webui.part.WindowContainer;
|
||||||
import org.adempiere.webui.session.SessionManager;
|
import org.adempiere.webui.session.SessionManager;
|
||||||
import org.adempiere.webui.util.ZKUpdateUtil;
|
import org.adempiere.webui.util.ZKUpdateUtil;
|
||||||
|
import org.adempiere.webui.window.FDialog;
|
||||||
import org.compiere.minigrid.ColumnInfo;
|
import org.compiere.minigrid.ColumnInfo;
|
||||||
import org.compiere.minigrid.IDColumn;
|
import org.compiere.minigrid.IDColumn;
|
||||||
import org.compiere.model.GridField;
|
import org.compiere.model.GridField;
|
||||||
|
@ -122,6 +123,7 @@ import org.zkoss.zul.ext.Sortable;
|
||||||
*/
|
*/
|
||||||
public abstract class InfoPanel extends Window implements EventListener<Event>, WTableModelListener, Sortable<Object>, IHelpContext
|
public abstract class InfoPanel extends Window implements EventListener<Event>, WTableModelListener, Sortable<Object>, IHelpContext
|
||||||
{
|
{
|
||||||
|
protected static final String INFO_QUERY_TIME_OUT_ERROR = "InfoQueryTimeOutError";
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -312,7 +314,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
try {
|
try {
|
||||||
int t = Integer.parseInt(pair[1]);
|
int t = Integer.parseInt(pair[1]);
|
||||||
if (t > 0)
|
if (t > 0)
|
||||||
this.queryTimeout = t;
|
setFixedQueryTimeout(t);
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
} else if (pair[0].equalsIgnoreCase("pagesize")) {
|
} else if (pair[0].equalsIgnoreCase("pagesize")) {
|
||||||
try {
|
try {
|
||||||
|
@ -327,6 +329,15 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set fixed query timeout value, overwrite the value from sysconfig
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
public void setFixedQueryTimeout(int timeout) {
|
||||||
|
this.queryTimeout = timeout;
|
||||||
|
useQueryTimeoutFromSysConfig = false;
|
||||||
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
if (isLookup())
|
if (isLookup())
|
||||||
|
@ -465,6 +476,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
protected boolean isAutoComplete = false;
|
protected boolean isAutoComplete = false;
|
||||||
|
|
||||||
protected int queryTimeout = 0;
|
protected int queryTimeout = 0;
|
||||||
|
protected boolean useQueryTimeoutFromSysConfig = true;
|
||||||
|
|
||||||
protected String autoCompleteSearchColumn = null;
|
protected String autoCompleteSearchColumn = null;
|
||||||
|
|
||||||
|
@ -898,6 +910,9 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Object> readLine(int start, int end) {
|
private List<Object> readLine(int start, int end) {
|
||||||
|
if (useQueryTimeoutFromSysConfig)
|
||||||
|
queryTimeout = MSysConfig.getIntValue(MSysConfig.ZK_INFO_QUERY_TIME_OUT, 0, Env.getAD_Client_ID(Env.getCtx()));
|
||||||
|
|
||||||
//cacheStart & cacheEnd - 1 based index, start & end - 0 based index
|
//cacheStart & cacheEnd - 1 based index, start & end - 0 based index
|
||||||
if (getCacheStart() >= 1 && cacheEnd > getCacheStart())
|
if (getCacheStart() >= 1 && cacheEnd > getCacheStart())
|
||||||
{
|
{
|
||||||
|
@ -996,7 +1011,17 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
|
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
{
|
{
|
||||||
log.log(Level.SEVERE, dataSql, e);
|
if (DB.getDatabase().isQueryTimeout(e))
|
||||||
|
{
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.log(Level.INFO, dataSql, e);
|
||||||
|
FDialog.error(p_WindowNo, INFO_QUERY_TIME_OUT_ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.log(Level.SEVERE, dataSql, e);
|
||||||
|
FDialog.error(p_WindowNo, "DBExecuteError", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finally
|
finally
|
||||||
|
@ -1239,6 +1264,9 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
*/
|
*/
|
||||||
protected boolean testCount()
|
protected boolean testCount()
|
||||||
{
|
{
|
||||||
|
if (useQueryTimeoutFromSysConfig)
|
||||||
|
queryTimeout = MSysConfig.getIntValue(MSysConfig.ZK_INFO_QUERY_TIME_OUT, 0, Env.getAD_Client_ID(Env.getCtx()));
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
String dynWhere = getSQLWhere();
|
String dynWhere = getSQLWhere();
|
||||||
StringBuilder sql = new StringBuilder (m_sqlCount);
|
StringBuilder sql = new StringBuilder (m_sqlCount);
|
||||||
|
@ -1262,6 +1290,8 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pstmt = DB.prepareStatement(countSql, null);
|
pstmt = DB.prepareStatement(countSql, null);
|
||||||
|
if (queryTimeout > 0)
|
||||||
|
pstmt.setQueryTimeout(queryTimeout);
|
||||||
setParameters (pstmt, true);
|
setParameters (pstmt, true);
|
||||||
rs = pstmt.executeQuery();
|
rs = pstmt.executeQuery();
|
||||||
|
|
||||||
|
@ -1269,8 +1299,18 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
m_count = rs.getInt(1);
|
m_count = rs.getInt(1);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.log(Level.SEVERE, countSql, e);
|
if (e instanceof SQLException && DB.getDatabase().isQueryTimeout((SQLException) e))
|
||||||
|
{
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.log(Level.INFO, countSql, e);
|
||||||
|
FDialog.error(p_WindowNo, INFO_QUERY_TIME_OUT_ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.log(Level.SEVERE, countSql, e);
|
||||||
|
FDialog.error(p_WindowNo, "DBExecuteError", e.getMessage());
|
||||||
|
}
|
||||||
m_count = -2;
|
m_count = -2;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
@ -1532,4 +1532,12 @@ public class DB_Oracle implements AdempiereDatabase
|
||||||
//
|
//
|
||||||
return sql.toString();
|
return sql.toString();
|
||||||
} // getSQLModify
|
} // getSQLModify
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryTimeout(SQLException ex) {
|
||||||
|
//java.sql.SQLTimeoutException: ORA-01013: user requested cancel of current operation
|
||||||
|
return "72000".equals(ex.getSQLState()) && ex.getErrorCode() == 1013;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // DB_Oracle
|
} // DB_Oracle
|
||||||
|
|
|
@ -1422,4 +1422,11 @@ public class DB_PostgreSQL implements AdempiereDatabase
|
||||||
return sql.toString();
|
return sql.toString();
|
||||||
} // getSQLModify
|
} // getSQLModify
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryTimeout(SQLException ex) {
|
||||||
|
//org.postgresql.util.PSQLException: ERROR: canceling statement due to user request | SQL Code: 0 | SQL State: 57014
|
||||||
|
return "57014".equals(ex.getSQLState());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // DB_PostgreSQL
|
} // DB_PostgreSQL
|
||||||
|
|
Loading…
Reference in New Issue