Search in sources :

Example 6 with PortalEvent

use of org.apereo.portal.events.PortalEvent in project uPortal by Jasig.

the class JpaPortalEventStore method getPortalEvents.

@Override
public void getPortalEvents(DateTime startTime, DateTime endTime, int maxEvents, FunctionWithoutResult<PortalEvent> handler) {
    final Session session = this.getEntityManager().unwrap(Session.class);
    final org.hibernate.Query query = session.createQuery(this.selectQuery);
    query.setParameter(this.startTimeParameter.getName(), startTime);
    query.setParameter(this.endTimeParameter.getName(), endTime);
    if (maxEvents > 0) {
        query.setMaxResults(maxEvents);
    }
    for (final ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY); results.next(); ) {
        final PersistentPortalEvent persistentPortalEvent = (PersistentPortalEvent) results.get(0);
        final PortalEvent portalEvent = this.toPortalEvent(persistentPortalEvent.getEventData(), persistentPortalEvent.getEventType());
        handler.apply(portalEvent);
        persistentPortalEvent.setAggregated(true);
        session.evict(persistentPortalEvent);
    }
}
Also used : PortalEvent(org.apereo.portal.events.PortalEvent) ScrollableResults(org.hibernate.ScrollableResults) Session(org.hibernate.Session)

Example 7 with PortalEvent

use of org.apereo.portal.events.PortalEvent in project uPortal by Jasig.

the class PortalRawEventsAggregatorImpl method doCloseAggregations.

@Override
@AggrEventsTransactional
public EventProcessingResult doCloseAggregations() {
    if (!this.clusterLockService.isLockOwner(AGGREGATION_LOCK_NAME)) {
        throw new IllegalStateException("The cluster lock " + AGGREGATION_LOCK_NAME + " must be owned by the current thread and server");
    }
    final IEventAggregatorStatus cleanUnclosedStatus = eventAggregationManagementDao.getEventAggregatorStatus(IEventAggregatorStatus.ProcessingType.CLEAN_UNCLOSED, true);
    // Update status with current server name
    final String serverName = this.portalInfoProvider.getUniqueServerName();
    cleanUnclosedStatus.setServerName(serverName);
    cleanUnclosedStatus.setLastStart(new DateTime());
    // Determine date of most recently aggregated data
    final IEventAggregatorStatus eventAggregatorStatus = eventAggregationManagementDao.getEventAggregatorStatus(IEventAggregatorStatus.ProcessingType.AGGREGATION, false);
    if (eventAggregatorStatus == null || eventAggregatorStatus.getLastEventDate() == null) {
        // Nothing has been aggregated, skip unclosed cleanup
        cleanUnclosedStatus.setLastEnd(new DateTime());
        eventAggregationManagementDao.updateEventAggregatorStatus(cleanUnclosedStatus);
        return new EventProcessingResult(0, null, null, true);
    }
    final DateTime lastAggregatedDate = eventAggregatorStatus.getLastEventDate();
    // If lastCleanUnclosedDate is null use the oldest date dimension as there can be
    // no aggregations that exist before it
    final DateTime lastCleanUnclosedDate;
    if (cleanUnclosedStatus.getLastEventDate() == null) {
        final DateDimension oldestDateDimension = this.dateDimensionDao.getOldestDateDimension();
        lastCleanUnclosedDate = oldestDateDimension.getDate().toDateTime();
    } else {
        lastCleanUnclosedDate = cleanUnclosedStatus.getLastEventDate();
    }
    if (!(lastCleanUnclosedDate.isBefore(lastAggregatedDate))) {
        logger.debug("No events aggregated since last unclosed aggregation cleaning, skipping clean: {}", lastAggregatedDate);
        return new EventProcessingResult(0, lastCleanUnclosedDate, lastAggregatedDate, true);
    }
    // Switch to flush on commit to avoid flushes during queries
    final EntityManager entityManager = this.getEntityManager();
    entityManager.flush();
    entityManager.setFlushMode(FlushModeType.COMMIT);
    // Track the number of closed aggregations and the last date of a cleaned interval
    int closedAggregations = 0;
    int cleanedIntervals = 0;
    DateTime cleanUnclosedEnd;
    final Thread currentThread = Thread.currentThread();
    final String currentName = currentThread.getName();
    try {
        currentThread.setName(currentName + "-" + lastCleanUnclosedDate + "-" + lastAggregatedDate);
        // Local caches used to reduce db io
        final IntervalsForAggregatorHelper intervalsForAggregatorHelper = new IntervalsForAggregatorHelper();
        final Map<AggregationInterval, AggregationIntervalInfo> previousIntervals = new HashMap<AggregationInterval, AggregationIntervalInfo>();
        // A DateTime within the next interval to close aggregations in
        DateTime nextIntervalDate = lastCleanUnclosedDate;
        do {
            // Reset our goal of catching up to the last aggregated event on every iteration
            cleanUnclosedEnd = lastAggregatedDate;
            // For each interval the aggregator supports, cleanup the unclosed aggregations
            for (final AggregationInterval interval : intervalsForAggregatorHelper.getHandledIntervals()) {
                final AggregationIntervalInfo previousInterval = previousIntervals.get(interval);
                if (previousInterval != null && nextIntervalDate.isBefore(previousInterval.getEnd())) {
                    logger.debug("{} interval before {} has already been cleaned during this execution, ignoring", interval, previousInterval.getEnd());
                    continue;
                }
                // The END date of the last clean session will find us the next interval to
                // clean
                final AggregationIntervalInfo nextIntervalToClean = intervalHelper.getIntervalInfo(interval, nextIntervalDate);
                previousIntervals.put(interval, nextIntervalToClean);
                if (nextIntervalToClean == null) {
                    continue;
                }
                final DateTime start = nextIntervalToClean.getStart();
                final DateTime end = nextIntervalToClean.getEnd();
                if (!end.isBefore(lastAggregatedDate)) {
                    logger.debug("{} interval between {} and {} is still active, ignoring", new Object[] { interval, start, end });
                    continue;
                }
                // Track the oldest interval end, this ensures that nothing is missed
                if (end.isBefore(cleanUnclosedEnd)) {
                    cleanUnclosedEnd = end;
                }
                logger.debug("Cleaning unclosed {} aggregations between {} and {}", new Object[] { interval, start, end });
                for (final IntervalAwarePortalEventAggregator<PortalEvent> portalEventAggregator : intervalAwarePortalEventAggregators) {
                    checkShutdown();
                    final Class<? extends IPortalEventAggregator<?>> aggregatorType = getClass(portalEventAggregator);
                    // Get aggregator specific interval info config
                    final AggregatedIntervalConfig aggregatorIntervalConfig = intervalsForAggregatorHelper.getAggregatorIntervalConfig(aggregatorType);
                    // cleanUnclosedAggregations
                    if (aggregatorIntervalConfig.isIncluded(interval)) {
                        closedAggregations += portalEventAggregator.cleanUnclosedAggregations(start, end, interval);
                    }
                }
                cleanedIntervals++;
            }
            // Set the next interval to the end date from the last aggregation run
            nextIntervalDate = cleanUnclosedEnd;
            logger.debug("Closed {} aggregations across {} interval before {} with goal of {}", new Object[] { closedAggregations, cleanedIntervals, cleanUnclosedEnd, lastAggregatedDate });
        // Loop until either the batchSize of cleaned aggregations has been reached or no
        // aggregation work is done
        } while (closedAggregations <= cleanUnclosedAggregationsBatchSize && cleanedIntervals <= cleanUnclosedIntervalsBatchSize && cleanUnclosedEnd.isBefore(lastAggregatedDate));
    } finally {
        currentThread.setName(currentName);
    }
    // Update the status object and store it
    cleanUnclosedStatus.setLastEventDate(cleanUnclosedEnd);
    cleanUnclosedStatus.setLastEnd(new DateTime());
    eventAggregationManagementDao.updateEventAggregatorStatus(cleanUnclosedStatus);
    return new EventProcessingResult(closedAggregations, lastCleanUnclosedDate, lastAggregatedDate, !cleanUnclosedEnd.isBefore(lastAggregatedDate));
}
Also used : HashMap(java.util.HashMap) DateTime(org.joda.time.DateTime) EntityManager(javax.persistence.EntityManager) PortalEvent(org.apereo.portal.events.PortalEvent)

Example 8 with PortalEvent

use of org.apereo.portal.events.PortalEvent in project uPortal by Jasig.

the class JpaPortalEventStore method aggregatePortalEvents.

@Override
@RawEventsTransactional
public boolean aggregatePortalEvents(DateTime startTime, DateTime endTime, int maxEvents, Function<PortalEvent, Boolean> handler) {
    final Session session = this.getEntityManager().unwrap(Session.class);
    session.setFlushMode(FlushMode.COMMIT);
    final org.hibernate.Query query = session.createQuery(this.selectUnaggregatedQuery);
    query.setParameter(this.startTimeParameter.getName(), startTime);
    query.setParameter(this.endTimeParameter.getName(), endTime);
    if (maxEvents > 0) {
        query.setMaxResults(maxEvents);
    }
    int resultCount = 0;
    for (final ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY); results.next(); ) {
        final PersistentPortalEvent persistentPortalEvent = (PersistentPortalEvent) results.get(0);
        final PortalEvent portalEvent;
        try {
            portalEvent = this.toPortalEvent(persistentPortalEvent.getEventData(), persistentPortalEvent.getEventType());
        } catch (RuntimeException e) {
            this.logger.warn("Failed to convert PersistentPortalEvent to PortalEvent: " + persistentPortalEvent, e);
            // Mark the event as error and store the mark to prevent trying to reprocess the
            // broken event data
            persistentPortalEvent.setErrorAggregating(true);
            session.persist(persistentPortalEvent);
            continue;
        }
        try {
            final Boolean eventHandled = handler.apply(portalEvent);
            if (!eventHandled) {
                this.logger.debug("Aggregation stop requested before processing event {}", portalEvent);
                return false;
            }
            // Mark the event as aggregated and store the mark
            persistentPortalEvent.setAggregated(true);
            session.persist(persistentPortalEvent);
            // periodic flush and clear of session to manage memory demands
            if (++resultCount % this.flushPeriod == 0) {
                this.logger.debug("Aggregated {} events, flush and clear {} EntityManager.", resultCount, BaseRawEventsJpaDao.PERSISTENCE_UNIT_NAME);
                session.flush();
                session.clear();
            }
        } catch (Exception e) {
            this.logger.warn("Failed to aggregate portal event: " + persistentPortalEvent, e);
            // mark the event as erred and move on. This will not be picked up by processing
            // again
            persistentPortalEvent.setErrorAggregating(true);
            session.persist(persistentPortalEvent);
        }
    }
    return true;
}
Also used : PortalEvent(org.apereo.portal.events.PortalEvent) ScrollableResults(org.hibernate.ScrollableResults) IOException(java.io.IOException) JsonMappingException(com.fasterxml.jackson.databind.JsonMappingException) JsonParseException(com.fasterxml.jackson.core.JsonParseException) Session(org.hibernate.Session)

Aggregations

PortalEvent (org.apereo.portal.events.PortalEvent)8 DateTime (org.joda.time.DateTime)4 Test (org.junit.Test)3 InvocationOnMock (org.mockito.invocation.InvocationOnMock)3 TransactionStatus (org.springframework.transaction.TransactionStatus)3 TransactionCallback (org.springframework.transaction.support.TransactionCallback)3 JsonParseException (com.fasterxml.jackson.core.JsonParseException)2 JsonMappingException (com.fasterxml.jackson.databind.JsonMappingException)2 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2 ScrollableResults (org.hibernate.ScrollableResults)2 Session (org.hibernate.Session)2 Pattern (java.util.regex.Pattern)1 EntityManager (javax.persistence.EntityManager)1 PortletRenderExecutionEvent (org.apereo.portal.events.PortletRenderExecutionEvent)1 IPortletWindowId (org.apereo.portal.portlet.om.IPortletWindowId)1 IPerson (org.apereo.portal.security.IPerson)1