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

com.redhat.lightblue.migrator.CleanupThread Maven / Gradle / Ivy

package com.redhat.lightblue.migrator;

import java.util.List;
import java.util.ArrayList;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.redhat.lightblue.client.*;
import com.redhat.lightblue.client.request.data.*;
import java.io.Closeable;
import java.io.IOException;

public class CleanupThread extends Thread {

    private static final Logger LOGGER = LoggerFactory.getLogger(CleanupThread.class);

    private long period = 40l * 60l * 1000l; // 40 minutes, 4*threadMonitor
    private long oldJobThreshold = 1000l * 60l * 60l * 24l * 7l; // 7 days

    private final Controller controller;

    public CleanupThread(Controller controller) {
        this.controller = controller;
    }

    public long getPeriod() {
        return period;
    }

    public void setPeriod(long l) {
        period = l;
    }

    public long getOldJobThreshold() {
        return oldJobThreshold;
    }

    public void setOldJobThreshold(long l) {
        oldJobThreshold = l;
    }

    private Literal[] ids(MigrationJob[] jobs) {
        List ids = new ArrayList<>();
        for (MigrationJob j : jobs) {
            ids.add(Literal.value(j.get_id()));
        }
        return ids.toArray(new Literal[ids.size()]);
    }

    public void cleanupOldJobs(LightblueClient cli, Date cleanupBefore) {
        DataFindRequest findRequest = new DataFindRequest("migrationJob", null);
        // Find completed generated jobs whose jobexecutions don't have a completed job that's close
        Query q = Query.and(Query.withValue("status", Query.eq, MigrationJob.STATE_COMPLETED),
                Query.withValue("generated", Query.eq, true),
                Query.not(Query.arrayMatch("jobExecutions",
                        Query.and(Query.withValue("status", Query.eq, MigrationJob.STATE_COMPLETED),
                                Query.withValue("actualEndDate", Query.gt, new Literal(cleanupBefore))))));

        findRequest.where(q);
        LOGGER.debug("Query:{}", q);
        findRequest.select(Projection.includeField("_id"));
        findRequest.range(0, 250);
        LOGGER.debug("Cleaning up old jobs");
        for (int loop = 0; loop < 10; loop++) {
            // We loop at most 10 times to not starve other processes
            try {
                MigrationJob[] jobs = cli.data(findRequest, MigrationJob[].class);
                if (jobs != null && jobs.length > 0) {
                    LOGGER.debug("Deleting {} jobs", jobs.length);
                    DataDeleteRequest del = new DataDeleteRequest("migrationJob", null);
                    del.where(Query.withValues("_id", Query.in, ids(jobs)));
                    cli.data(del);
                } else {
                    break;
                }
            } catch (Exception e) {
                // Log and ignore errors
                LOGGER.error("Error during cleanup", e);
            }
        }
    }

    public void enableStuckJobs(LightblueClient cli, Date enableBefore) {
        DataFindRequest findRequest = new DataFindRequest("migrationJob", null);
        // Find active jobs that's been sitting for too long
        findRequest.where(Query.and(Query.withValue("status", Query.eq, MigrationJob.STATE_ACTIVE),
                Query.arrayMatch("jobExecutions",
                        Query.and(Query.withValue("status", Query.eq, MigrationJob.STATE_ACTIVE),
                                Query.withValue("actualStartDate", Query.lt, new Literal(enableBefore))))));
        findRequest.select(Projection.includeField("_id"));
        findRequest.range(0, 250);
        LOGGER.debug("Re-enabling stuck jobs");
        for (int loop = 0; loop < 10; loop++) {
            try {
                MigrationJob[] jobs = cli.data(findRequest, MigrationJob[].class);
                if (jobs != null && jobs.length > 0) {
                    LOGGER.warn("Re-enabling {} active stuck jobs", jobs.length);
                    DataUpdateRequest upd = new DataUpdateRequest("migrationJob", null);
                    upd.where(Query.withValues("_id", Query.in, ids(jobs)));
                    upd.updates(Update.set("status", MigrationJob.STATE_AVAILABLE));
                    LOGGER.debug("update:{}", upd.getBodyJson());
                    cli.data(upd);
                } else {
                    break;
                }
            } catch (Exception e) {
                LOGGER.error("Error re-activating jobs", e);
            }
        }
    }

    @Override
    public void run() {
        LOGGER.debug("Starting with period:{}", period);
        while (true) {
            try {
                Thread.sleep(period);
            } catch (InterruptedException e) {
                return;
            }

            LOGGER.debug("Woke up");

            LightblueClient cli = null;
            
            try {
                cli = controller.getLightblueClient();

                Date d = new Date(System.currentTimeMillis() - oldJobThreshold);
                cleanupOldJobs(cli, d);
                d = new Date(System.currentTimeMillis() - period * 3); // 3 times period=too long            
                enableStuckJobs(cli, d);
            } finally {
                if (cli != null && cli instanceof Closeable) {
                    try {
                        ((Closeable)cli).close();
                    } catch (IOException ex) {
                        LOGGER.warn("Unable to close LightblueClient, resource leak possible!");
                    }
                }
            }
            LOGGER.debug("Completed");
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy