All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fi.evolver.basics.spring.clean.MaxRowsCleaner Maven / Gradle / Ivy

package fi.evolver.basics.spring.clean;

import static fi.evolver.utils.timing.TimingUtils.begin;

import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import fi.evolver.basics.spring.job.ResultState;
import fi.evolver.basics.spring.job.TaskStatusService;
import fi.evolver.basics.spring.job.entity.TaskStatus.TaskState;
import fi.evolver.basics.spring.triggerable.TriggerableException;
import fi.evolver.utils.arg.Arg;
import fi.evolver.utils.arg.LongArg;
import fi.evolver.utils.timing.TimingUtils.AutoCloser;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.TypedQuery;


@Component
public class MaxRowsCleaner extends GenericCleaner {
	private static final LongArg ARG_MAX_ROWS = new LongArg("MaxRows", 0L, null);

	@PersistenceContext
	private EntityManager em;


	@Autowired
	public MaxRowsCleaner(DataCleaner dataCleaner, TaskStatusService taskStatusService) {
		super(dataCleaner, taskStatusService);
	}


	@Override
	protected ResultState clean(Class table, Map args) throws TriggerableException {
		Instant maxStartTime = Instant.now().plusMillis(ARG_MAX_RUN_TIME_MS.get(args));
		long maxBatchSize = ARG_MAX_BATCH_SIZE.get(args);
		long maxRows = ARG_MAX_ROWS.get(args);

		int deleted = 0;
		int batch = 0;

		long originalCount = countRows(table);
		long count = originalCount;
		if (count <= maxRows)
			return new ResultState(TaskState.NOTHING_TO_DO, "%s count %s within limits", table.getSimpleName(), count);

		while (count > maxRows) {
			try (AutoCloser t = begin("Batch")) {
				taskStatusService.updateMessage("Deleted %d / %d %s rows", deleted, originalCount - maxRows, table.getSimpleName());
				long minId = queryMinId(table);
				long delete = Math.min(count - maxRows, maxBatchSize);
				deleted += dataCleaner.deleteByIdLessThan(table, minId + delete);
				++batch;
				count = countRows(table);
			}

			if (Instant.now().isAfter(maxStartTime)) {
				LOG.info("Out of time after {} batches: stopping", batch);
				break;
			}
		}

		return ResultState.ok(deleted > 0, "Deleted %s of %s %s rows", deleted, originalCount, table.getSimpleName());
	}


	private long queryMinId(Class table) {
		try (AutoCloser t = begin("MinId")) {
			TypedQuery query = em.createQuery("SELECT min(id) FROM " + table.getSimpleName(), Long.class);
			return query.getSingleResult();
		}
	}


	private long countRows(Class table) {
		try (AutoCloser t = begin("Count")) {
			taskStatusService.updateMessage("Counting %s entities", table.getSimpleName());
			TypedQuery query = em.createQuery("SELECT count(t) FROM " + table.getSimpleName() + " t", Long.class);
			return query.getSingleResult();
		}
	}


	@Override
	protected List> getAdditionalArgs() {
		return Arrays.asList(ARG_MAX_ROWS);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy