CustomArchiveRemover extends SizeAndTimeBasedArchiveRemover {
/*
* Code taken from Logback
* https://github.com/qos-ch/logback/blob/master/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TimeBasedArchiveRemover.java
*/
private void totalSizeCap(Date now) {
logEntityManager.updateDeleteType(DeleteType.ROLLOVER, filename, directory);
}
}
@ManagedBean
public class LogChecker implements Runnable {
public void run() {
transactionTemplate.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
List<LogFile> logFiles = logEntityManager.getUnrolledOverLogFiles();
// calculate listOfUnexpectedlyDeletedFiles
if (!listOfUnexpectedlyDeletedFiles.isEmpty()) {
logEntityManager.updateDeleteTypeForFiles(DeleteType.UNEXPECTED, "Some reason", listOfUnexpectedlyDeletedFiles.stream().map(String::valueOf).collect(Collectors.joining(",")));
}
return null;
}
});
}
}
@ManagedBean
public class LogFileEntityManager {
@Inject
private JDBCTemplate jdbcTemplate;
private static final String LIST_UNROLLED_OVER_LOG_FILES = "SELECT * FROM {0}.LogFile WHERE fileName != '?' AND (deleteType NOT IN (?,?) OR deleteType IS NULL)";
private static final String UPDATE_DELETE_TYPE_FOR_LOG_FILES = "UPDATE {0}.LogFile SET deleteType = ? , deleteReason = ? WHERE id in({1})";
private static final String UPDATE_DELETE_TYPE_FOR_LOG_FILE = "UPDATE {0}.LogFile SET deleteType = ? WHERE fileName = ? AND fileLocation = ?";
//single file
@Transactional
public void updateDeleteTypeForLogFile(DeleteType deleteType, String fileName, String fileLocation) {
jdbcTemplate.update(MessageFormat.format(UPDATE_DELETE_TYPE_FOR_LOG_FILE, "schema1"), deleteType.name(), fileName, fileLocation);
}
// Multiple files
// Do i need to remove readonly ? as
@Transactional(readOnly = true)
public List<LogFile> getUnrolledOverLogFiles() {
return jdbcTemplate.query(MessageFormat.format(LIST_UNROLLED_OVER_LOG_FILES, "schema1"), new Object[] { LOG_FILE_NAME, DeleteType.ROLLOVER, DeleteType.VALID_DELETE }, new BeanPropertyRowMapper<LogFile>(LogFile.class));
}
// Multiple files
@Transactional
public void updateDeleteTypeForLogFiles(DeleteType deleteType, String deleteReason, String commaSeparatedIds) {
jdbcTemplate.update(MessageFormat.format(UPDATE_DELETE_TYPE_FOR_LOG_FILES, "schema1", commaSeparatedIds), deleteType == null ? null : deleteType.name(), deleteReason);
}
}
我以前使用过spring事务注解,但通常我们不确定是否有多个线程在更新同一列。
我有两个并行线程可以更新给定行的一列。
当日志文件大小超过一个给定的值时,customarchiveremover会运行多次(与log4j相关的线程)。
logchecker是按计划运行的计划作业。
假设我已经安排了logchecker在上午12点,同时日志文件的大小增加了它必须删除旧的日志文件作为滚动删除的一部分。
在这种情况下,文件将被log4j删除,然后我希望数据库中填充rollover(customarchiveremover?),而不是意外的(logchecker)。
我不清楚以下几点。
如何确保一个线程优先于另一个线程?customarchiveremover是优先级,这意味着,在两个线程并行运行的情况下,我希望delete type是rollover而不是unexpected
我应该使用什么事务级别来读取和更新?
transactioncallback将如何与@transactional协作
我需要使用select进行更新吗?因此它会锁定行以进行更新。在这种情况下,我觉得logchecker线程的优先级是我不想要的。何时使用选择。。。更新?
暂无答案!
目前还没有任何答案,快来回答吧!