ConcurrencyLimiter.php 1.37 KB
<?php

namespace FootyRoom\Support;

use Illuminate\Cache\RateLimiter;
use Illuminate\Contracts\Cache\Repository;

class ConcurrencyLimiter
{
    /** @var \Illuminate\Contracts\Cache\Repository */
    protected $cache;

    /** @var \Illuminate\Cache\RateLimiter */
    protected $rateLimiter;

    public function __construct(Repository $cache, RateLimiter $rateLimiter)
    {
        $this->cache = $cache;
        $this->rateLimiter = $rateLimiter;
    }

    /**
     * Acquire lock if limit not reached.
     *
     * $resetMinutes Indicates in how many minutes concurrency counter will be
     * reset. This is needed to prevent possibility of being stuck at a limit if
     * locks were not released properly. Please not that setting this to a very
     * low value increases chances of having more concurrent requests than
     * specified by limit.
     */
    public function lock(string $key, int $limit, int $resetMinutes = 10): bool
    {
        if ($this->rateLimiter->tooManyAttempts($key, $limit, $resetMinutes)) {
            return false;
        }

        $this->rateLimiter->hit($key, $resetMinutes);

        return true;
    }

    /**
     * Release the lock.
     */
    public function release(string $key): void
    {        
        $sessions = (int) $this->cache->decrement($key);

        if ($sessions < 1) {
            $this->cache->forget($key);
        }
    }
}