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

com.viaoa.process.OACronProcessor Maven / Gradle / Ivy

package com.viaoa.process;

import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.viaoa.concurrent.OAExecutorService;
import com.viaoa.util.OADateTime;

/**
 * Used to manage OACron jobs, and uses OAExecutorService when it is time to process the cron. 
 * @author vvia
 */
public class OACronProcessor {
    private static Logger LOG = Logger.getLogger(OACronProcessor.class.getName());

    private final OAExecutorService execService;
    private CopyOnWriteArrayList alCron;

    private Thread thread;
    private final Object lock = new Object();
    private final AtomicInteger aiStartStop = new AtomicInteger();
    private final AtomicInteger aiThreadId = new AtomicInteger();
    
    public OACronProcessor() {
        execService = new OAExecutorService();
        alCron = new CopyOnWriteArrayList();
    }
    
    public OACron[] getCrons() {
        return (OACron[]) alCron.toArray(new OACron[0]);
    }

    public void add(OACron cron) {
        LOG.fine("cron="+cron.getName()+", "+cron.getDescription());
        if (!alCron.contains(cron)) {
            alCron.add(cron);
            synchronized (lock) {
                lock.notifyAll();
            }
        }
    }
    public void remove(OACron cron) {
        LOG.fine("cron="+cron.getName()+", "+cron.getDescription());
        alCron.remove(cron);
    }

    public boolean isRunning() {
        return (thread != null);
    }
    
    public void start() {
        aiStartStop.incrementAndGet();

        synchronized (lock) {
            lock.notifyAll();
        }

        LOG.fine("start called, aiStartStop=" + aiStartStop);
        thread = new Thread() {
            @Override
            public void run() {
                runThread();
            }
        };
        thread.setName("OACronProcessor." + aiThreadId.incrementAndGet());
        thread.setDaemon(true);
        thread.start();
    }

    public void stop() {
        aiStartStop.incrementAndGet();

        synchronized (lock) {
            lock.notifyAll();
            thread = null;
        }
        LOG.fine("stop called, aiStartStop=" + aiStartStop);
    }

    /*
     * called by {@link #runProcessInAnotherThread(OACron, boolean)} using an execService thread.
     */
    protected void callProcess(final OACron cron, boolean bManuallyCalled) {
        if (cron == null) return;
        cron.setLast(new OADateTime());
        LOG.fine("processing cron, name = "+cron.getName()+", description="+cron.getDescription());
        cron.process(bManuallyCalled);
    }

    
    /*
     * will use execService to then call {@link #process(OACron,boolean)}
     */
    public void callProcessInAnotherThread(final OACron cron, final boolean bManuallyCalled) {
        if (cron == null) return;
        execService.submit(new Runnable() {
            @Override
            public void run() {
                OACronProcessor.this.callProcess(cron, bManuallyCalled);
            }
        });
    }
    
    protected void runThread() {
        final int iStartStop = aiStartStop.get();
        LOG.fine("created cron processor, cntStartStop=" + iStartStop + ", thread name=" + Thread.currentThread().getName());
        
        OADateTime dtLast = null;
        final ArrayList alLast = new ArrayList<>();
                
        
        for (;;) {
            try {
                if (iStartStop != aiStartStop.get()) break;
                
                OADateTime dtNow = new OADateTime();
                dtNow.clearSecondAndMilliSecond();
                
                OADateTime dtCompare = dtNow.addMinutes(-1);
                dtCompare.clearSecondAndMilliSecond();

                if (dtLast == null || dtLast.before(dtCompare)) {
                    alLast.clear();
                }
                dtLast = dtCompare;
                
                beforeProcess(dtNow);
                for (OACron cron : alCron) {
                    if (!cron.getEnabled()) continue;
                    if (alLast.contains(cron)) {
                        continue;
                    }
                    alLast.add(cron);

                    OADateTime dt = new OADateTime(cron.findNext(dtCompare));
                    dt.clearSecondAndMilliSecond();
                    
                    int d = dt.compareTo(dtNow);
                    if (d == 0) {
                        callProcessInAnotherThread(cron, false);
                    }
                }
                
                synchronized (lock) {
                    lock.wait(30 * 1000);
                }
            }
            catch (Exception e) {
                LOG.log(Level.WARNING, "error processing from queue", e);
            }
        }
        LOG.fine("stopped OACronProcessor thread, cntStartStop=" + iStartStop + ", thread name=" + Thread.currentThread().getName());
    }
    
    protected void beforeProcess(OADateTime dtNow) {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy