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

com.slack.api.rate_limits.queue.RateLimitQueue Maven / Gradle / Ivy

There is a newer version: 1.39.0
Show newest version
package com.slack.api.rate_limits.queue;

import com.slack.api.methods.Methods;
import com.slack.api.rate_limits.RateLimiter;
import com.slack.api.rate_limits.WaitTime;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;

@Slf4j
public abstract class RateLimitQueue {

    protected abstract RateLimiter getRateLimiter();

    protected final ConcurrentMap> methodNameToActiveQueue = new ConcurrentHashMap<>();

    protected LinkedBlockingQueue getOrCreateActiveQueue(String methodName) {
        return methodNameToActiveQueue.computeIfAbsent(methodName, key -> new LinkedBlockingQueue<>());
    }

    public synchronized SUPPLIER dequeueIfReady(
            String messageId,
            String teamId,
            String methodName,
            Map params) {
        LinkedBlockingQueue activeQueue = getOrCreateActiveQueue(methodName);
        MSG message = activeQueue.peek();
        if (message == null) {
            throw new IllegalStateException("No message is found in the queue");
        }
        if (message.getId().equals(messageId)
                && message.getMillisToRun() <= System.currentTimeMillis()) {
            // Make sure if the situation is still the same with the timing we determined the wait time
            WaitTime original = message.getWaitTime();
            WaitTime latest;
            if (methodName.equals(Methods.CHAT_POST_MESSAGE)) {
                latest = getRateLimiter().acquireWaitTimeForChatPostMessage(teamId, params.get("channel"));
            } else {
                latest = getRateLimiter().acquireWaitTime(teamId, methodName);
            }
            if (log.isDebugEnabled()) {
                log.debug("Latest: {} ({} millis), original: {} ({} millis)",
                        latest.getPace(), latest.getMillisToWait(), original.getPace(), original.getMillisToWait());
            }
            if (latest.getPace() != original.getPace() && latest.getMillisToWait() > original.getMillisToWait()) {
                // The latest situation is worse than that timing.
                long newMillisToRun = System.currentTimeMillis() + latest.getMillisToWait();
                message.setMillisToRun(newMillisToRun);
                message.setWaitTime(latest);
            } else {
                SUPPLIER supplier = (SUPPLIER) activeQueue.poll().getSupplier();
                return supplier;
            }
        }
        return null;
    }

    protected abstract MSG buildNewMessage(
            String messageId,
            long epochMillisToRun,
            WaitTime waitTime,
            SUPPLIER methodsSupplier
    );

    public void enqueue(
            String messageId,
            String teamId,
            String methodName,
            Map params,
            SUPPLIER methodsSupplier) throws InterruptedException {

        WaitTime waitTime = getRateLimiter().acquireWaitTime(teamId, methodName);
        if (methodName.equals(Methods.CHAT_POST_MESSAGE)) {
            waitTime = getRateLimiter().acquireWaitTimeForChatPostMessage(teamId, params.get("channel"));
        }
        LinkedBlockingQueue activeQueue = getOrCreateActiveQueue(methodName);
        long epochMillisToRun = System.currentTimeMillis() + waitTime.getMillisToWait();
        MSG message = buildNewMessage(messageId, epochMillisToRun, waitTime, methodsSupplier);
        activeQueue.put(message);

        if (log.isDebugEnabled()) {
            log.debug("A new message has been enqueued (id: {}, pace: {}, wait time: {})",
                    message.getId(),
                    message.getWaitTime().getPace(),
                    message.getWaitTime().getMillisToWait()
            );
        }
    }

    public synchronized void remove(String methodName, String messageId) {
        LinkedBlockingQueue activeQueue = getOrCreateActiveQueue(methodName);
        MSG toRemove = null;
        for (MSG message : activeQueue) {
            if (message.getId().equals(messageId)) {
                toRemove = message;
                break;
            }
        }
        activeQueue.remove(toRemove);
    }

    public Integer getCurrentActiveQueueSize(String methodNameWithSuffix) {
        LinkedBlockingQueue activeQueue = methodNameToActiveQueue.get(methodNameWithSuffix);
        return activeQueue != null ? activeQueue.size() : 0;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy