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

com.aol.micro.server.events.JobsBeingExecuted Maven / Gradle / Ivy

package com.aol.micro.server.events;

import java.util.Optional;
import java.util.Random;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;

import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.eventbus.EventBus;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Aspect
public class JobsBeingExecuted {

    private static final Random r = new Random();
    private final ActiveEvents events = new ActiveEvents();
    @Getter(AccessLevel.PACKAGE)
    private final ConcurrentHashMultiset statCounter = ConcurrentHashMultiset.create();
    private final EventBus eventBus;
    private final JobName.Types jobNameType;

    private final LoggingRateLimiter loggingRateLimiter;

    private final long maxLoggingCapacity;

    public JobsBeingExecuted(@Qualifier("microserverEventBus") EventBus bus,
            @Value("${system.logging.max.per.hour:10}") long maxLoggingCapacity,
            @Value("${micro.events.job.name.format:SIMPLE}") JobName.Types jobNameType) {
        this.eventBus = bus;
        this.jobNameType = jobNameType;
        this.loggingRateLimiter = new LoggingRateLimiter<>();
        this.maxLoggingCapacity = maxLoggingCapacity;
    }

    public JobsBeingExecuted(EventBus bus) {
        this(
             bus, 10, JobName.Types.SIMPLE);
    }

    @Around("execution(* com.aol.micro.server.events.ScheduledJob.scheduleAndLog(..))")
    public Object aroundScheduledJob(ProceedingJoinPoint pjp) throws Throwable {

        String type = jobNameType.getCreator()
                                 .getType(pjp.getSignature()
                                             .getDeclaringType());

        return executeScheduledJob(pjp, type);

    }

    public int size() {
        return events.size();
    }

    public int events() {
        return events.events();
    }

    @Override
    public String toString() {
        return events.toString();
    }

    private Object executeScheduledJob(final ProceedingJoinPoint pjp, final String type) throws Throwable {
        addTypeToStatCounter(type);
        JobExecutingData data = new JobExecutingData(
                                                     type, statCounter.count(type));
        String id = buildId(type, data.getProcessingThread());
        events.active(id, data);

        SystemData retVal = null;
        long correlationId = r.nextLong();
        eventBus.post(new JobStartEvent(
                                        correlationId, type));
        try {

            retVal = Optional.ofNullable(((SystemData) pjp.proceed()))
                             .map(sd -> sd.withCorrelationId(id))
                             .orElse(null);
            return retVal;
        } finally {
            logSystemEvent(pjp, type, data, retVal);
            retVal = Optional.ofNullable(retVal)
                             .orElse(SystemData.builder()
                                               .correlationId("" + correlationId)
                                               .errors(0l)
                                               .processed(0l)
                                               .build());
            eventBus.post(new JobCompleteEvent(
                                               correlationId, type, retVal.getErrors(), retVal.getProcessed()));
        }
    }

    private void logSystemEvent(final ProceedingJoinPoint pjp, final String type, JobExecutingData data,
            SystemData retVal) {
        final SystemData active = retVal;
        loggingRateLimiter.addAndEnsureFrequency(pjp.getTarget()
                                                    .getClass());
        loggingRateLimiter.capacityAvailable(pjp.getTarget()
                                                .getClass(),
                                             this.maxLoggingCapacity, new Runnable() {
                                                 @Override
                                                 public void run() {
                                                     postEvent(pjp, type, data, active);
                                                 }
                                             });
    }

    private void postEvent(ProceedingJoinPoint pjp, String type, JobExecutingData data, SystemData retVal) {
        if (retVal != null) {

            eventBus.post(retVal);
        }
        events.finished(buildId(type, data.getProcessingThread()));
    }

    private void addTypeToStatCounter(String type) {
        try {
            statCounter.add(type);
        } catch (Exception e) {
            statCounter.clear();
            statCounter.add(type);
        }
    }

    private String buildId(String type, long threadId) {
        return "id_" + type + "-" + threadId;
    }

    @AllArgsConstructor
    @XmlAccessorType(XmlAccessType.FIELD)
    static class JobExecutingData extends BaseEventInfo {
        private final String type;
        private final int timesExecuted;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy