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

com.netflix.concurrency.limits.limiter.BlockingLimiter Maven / Gradle / Ivy

package com.netflix.concurrency.limits.limiter;

import com.netflix.concurrency.limits.Limiter;

import java.util.Optional;

/**
 * {@link Limiter} that blocks the caller when the limit has been reached.  The caller is
 * blocked until the limiter has been released.  This limiter is commonly used in batch
 * clients that use the limiter as a back-pressure mechanism.
 * 
 * @param 
 */
public final class BlockingLimiter implements Limiter {
    public static  BlockingLimiter wrap(Limiter delegate) {
        return new BlockingLimiter(delegate);
    }

    private final Limiter delegate;
    
    /**
     * Lock used to block and unblock callers as the limit is reached
     */
    private final Object lock = new Object();
    private boolean blocked = false;

    private BlockingLimiter(Limiter limiter) {
        this.delegate = limiter;
    }
    
    private Optional tryAcquire(ContextT context) {
        synchronized (lock) {
            while (true) {
                // Try to acquire a token and return immediately if successful
                Optional listener;
                listener = delegate.acquire(context);
                if (listener.isPresent()) {
                    return listener;
                }
                
                // We have reached the limit so block until a token is released
                blocked = true;
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return Optional.empty();
                }
            }
        }
    }
    
    private void unblock() {
        synchronized (lock) {
            if (blocked) {
                blocked = false;
                lock.notify();
            }
        }
    }
    
    @Override
    public Optional acquire(ContextT context) {
        return tryAcquire(context).map(delegate -> {
            return new Listener() {
                @Override
                public void onSuccess() {
                    delegate.onSuccess();
                    unblock();
                }

                @Override
                public void onIgnore() {
                    delegate.onIgnore();
                    unblock();
                }

                @Override
                public void onDropped() {
                    delegate.onDropped();
                    unblock();
                }
            };
        });
    }
    
    @Override
    public String toString() {
        return "BlockingLimiter [blocked=" + blocked + ", " + delegate + "]";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy