Package org.apache.sling.replication.queue.impl

Source Code of org.apache.sling.replication.queue.impl.ErrorAwareQueueDistributionStrategy

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sling.replication.queue.impl;

import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyOption;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.replication.packaging.ReplicationPackage;
import org.apache.sling.replication.queue.ReplicationQueue;
import org.apache.sling.replication.queue.ReplicationQueueDistributionStrategy;
import org.apache.sling.replication.queue.ReplicationQueueException;
import org.apache.sling.replication.queue.ReplicationQueueItem;
import org.apache.sling.replication.queue.ReplicationQueueItemState;
import org.apache.sling.replication.queue.ReplicationQueueItemState.ItemState;
import org.apache.sling.replication.queue.ReplicationQueueProvider;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The error strategy for delivering packages to queues. Each agent manages a single queue for
* delivering packages with an error queue which can be used when an item is stuck in the default
* queue for too much time, then the stuck item is moved to the error queue or dropped.
*/
@Component(immediate = true, metatype = true, label = "Error Aware Queue Distribution Strategy")
@Service(value = ReplicationQueueDistributionStrategy.class)
@Property(name = "name", value = ErrorAwareQueueDistributionStrategy.NAME, propertyPrivate = true)
public class ErrorAwareQueueDistributionStrategy implements ReplicationQueueDistributionStrategy {

    protected static final String ERROR_QUEUE_NAME = "error";

    private static final String ERROR = "ERROR";

    public static final String NAME = "error";

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Property(intValue = 100, label = "no. of maximum queue item processing attempts")
    private static final String ATTEMPTS_THRESHOLD = "attempts.threshold";

    @Property(intValue = 600000, label = "no. of maximum amount of milliseconds in the queue")
    private static final String TIME_THRESHOLD = "time.threshold";

    @Property(label = "Stuck Queue Handling", options = {
            @PropertyOption(name = "ERROR", value = "Error"),
            @PropertyOption(name = "DROP", value = "Drop")}, value = ERROR)
    private static final String STUCK_HANDLING = "stuck.handling";

    private String stuckQueueHandling;

    private Integer attemptsThreshold;

    private Integer timeThreshold;

    @Activate
    protected void activate(final ComponentContext ctx) {
        stuckQueueHandling = PropertiesUtil
                .toString(ctx.getProperties().get(STUCK_HANDLING), ERROR);
        attemptsThreshold = PropertiesUtil.toInteger(ctx.getProperties().get(ATTEMPTS_THRESHOLD), 100);
        timeThreshold = PropertiesUtil.toInteger(ctx.getProperties().get(TIME_THRESHOLD), 600000);
    }

    public boolean add(String agentName, ReplicationPackage replicationPackage,
                         ReplicationQueueProvider queueProvider) throws ReplicationQueueException {
        boolean added;
        ReplicationQueueItem queueItem = getItem(replicationPackage);
        ReplicationQueue queue = queueProvider.getDefaultQueue(agentName);
        added = queue.add(queueItem);
        checkAndRemoveStuckItems(agentName, queueProvider);
        return added;
    }

    public List<String> getQueueNames() {
        return Arrays.asList(new String[] { ERROR_QUEUE_NAME, DEFAULT_QUEUE_NAME });
    }

    private void checkAndRemoveStuckItems(String agent,
                                          ReplicationQueueProvider queueProvider) throws ReplicationQueueException {
        ReplicationQueue defaultQueue = queueProvider.getDefaultQueue(agent);
        // get first item in the queue with its status
        ReplicationQueueItem firstItem = defaultQueue.getHead();
        if (firstItem != null) {
            ReplicationQueueItemState status = defaultQueue.getStatus(firstItem);
            // if item is still in the queue after a max no. of attempts, move it to the error queue
            int attempts = status.getAttempts();
            Calendar entered = status.getEntered();
            log.info("item {} entered {} was attempted {} times", new Object[]{firstItem, entered, attempts});
            if (attempts > attemptsThreshold || (entered != null && Calendar.getInstance().getTimeInMillis() - entered.getTimeInMillis() > timeThreshold)) {
                if (ERROR.equals(stuckQueueHandling)) {
                    log.warn("item {} moved to the error queue", firstItem);

                    ReplicationQueue errorQueue = queueProvider.getQueue(agent, ERROR_QUEUE_NAME);
                    if (!errorQueue.add(firstItem)) {
                        log.error("failed to move item {} the queue {}", firstItem, errorQueue);
                        throw new ReplicationQueueException("could not move an item to the error queue");
                    }
                }
                log.warn("item {} dropped from the default queue", firstItem);
                defaultQueue.remove(firstItem.getId());
            }
        }
    }

    private ReplicationQueueItem getItem(ReplicationPackage replicationPackage) {
        ReplicationQueueItem replicationQueueItem = new ReplicationQueueItem(replicationPackage.getId(),
                replicationPackage.getPaths(),
                replicationPackage.getAction(),
                replicationPackage.getType(),
                replicationPackage.getInfo());

        return replicationQueueItem;
    }

}
TOP

Related Classes of org.apache.sling.replication.queue.impl.ErrorAwareQueueDistributionStrategy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.