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:
hengsin 2021-01-19 10:25:13 +08:00 committed by GitHub
parent 1afe4fe0c6
commit 59b83c3361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 115 additions and 6 deletions

View File

@ -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
;

View File

@ -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
;

View File

@ -20,6 +20,7 @@ import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.SQLTimeoutException;
import java.sql.Timestamp;
import javax.sql.DataSource;
@ -468,6 +469,13 @@ public interface AdempiereDatabase
*/
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

View File

@ -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_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_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_REMEMBER_ME = "ZK_LOGIN_ALLOW_REMEMBER_ME";
public static final String ZK_LOGO_LARGE = "ZK_LOGO_LARGE";

View File

@ -1930,6 +1930,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
*/
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();
String dynWhere = getSQLWhere();
StringBuilder sql = new StringBuilder (m_sqlMain);
@ -1971,8 +1974,18 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
}
catch (Exception 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;
}
finally

View File

@ -67,6 +67,7 @@ import org.adempiere.webui.part.ITabOnSelectHandler;
import org.adempiere.webui.part.WindowContainer;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.util.ZKUpdateUtil;
import org.adempiere.webui.window.FDialog;
import org.compiere.minigrid.ColumnInfo;
import org.compiere.minigrid.IDColumn;
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
{
protected static final String INFO_QUERY_TIME_OUT_ERROR = "InfoQueryTimeOutError";
/**
*
*/
@ -312,7 +314,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
try {
int t = Integer.parseInt(pair[1]);
if (t > 0)
this.queryTimeout = t;
setFixedQueryTimeout(t);
} catch (Exception e) {}
} else if (pair[0].equalsIgnoreCase("pagesize")) {
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()
{
if (isLookup())
@ -465,6 +476,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
protected boolean isAutoComplete = false;
protected int queryTimeout = 0;
protected boolean useQueryTimeoutFromSysConfig = true;
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) {
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
if (getCacheStart() >= 1 && cacheEnd > getCacheStart())
{
@ -995,8 +1010,18 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
}
catch (SQLException 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
@ -1239,6 +1264,9 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
*/
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();
String dynWhere = getSQLWhere();
StringBuilder sql = new StringBuilder (m_sqlCount);
@ -1262,6 +1290,8 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
try
{
pstmt = DB.prepareStatement(countSql, null);
if (queryTimeout > 0)
pstmt.setQueryTimeout(queryTimeout);
setParameters (pstmt, true);
rs = pstmt.executeQuery();
@ -1269,8 +1299,18 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
m_count = rs.getInt(1);
}
catch (Exception 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;
}
finally

View File

@ -1532,4 +1532,12 @@ public class DB_Oracle implements AdempiereDatabase
//
return sql.toString();
} // 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

View File

@ -1422,4 +1422,11 @@ public class DB_PostgreSQL implements AdempiereDatabase
return sql.toString();
} // 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