1
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);
    }
}

I have used spring transaction annotation earlier but usually, we are not sure if multiple threads are updating the same column.

I have 2 parallel threads that can update a column of a given row.

CustomArchiveRemover runs multiple times when the log file size exceeds a given value when it gets rolled over(log4j related thread).

LogChecker is a scheduled job that runs as per schedule.

Say I have scheduled LogChecker at 12 AM and at the same time log file size increased it had to delete the older log file as part of rollover delete.

In that case, file will be deleted by log4j and after that I want the DB to be populated with rollover(CustomArchiveRemover?) and not unexpected(LogChecker).

I am not clear on the following.

  1. How to ensure one thread is prioritized over the other? CustomArchiveRemover is priority, that means, in case two thread runs in parallel, I want delete type to be ROLLOVER instead of UNEXPECTED
  2. What transaction-level should I use for read and update?
  3. How will TransactionCallback collaborate with @Transactional
  4. Do I need to use SELECT FOR UPDATE ? so that it locks the row for update. In this case, I feel LogChecker thread is prioritized which I don't want. When to use SELECT ... FOR UPDATE?
sandeep kamath
  • 133
  • 2
  • 11
  • Some helpful docs i came across which gave a lot of info https://www.marcobehler.com/guides/spring-transaction-management-transactional-in-depth – sandeep kamath Feb 15 '21 at 03:31

0 Answers0