HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/app/Library/InMemoryCreditTracker.php
<?php

namespace App\Library;

use App\Library\Exception\OutOfCredits;
use App\Library\Contracts\CreditTrackerInterface;
use Illuminate\Support\Facades\Cache;
use Exception;

class InMemoryCreditTracker implements CreditTrackerInterface
{
    public const ZERO = 0;
    public const UNLIMITED = -1;

    protected $resourceKey;
    protected ?string $description;

    public function __construct(string $resourceKey, ?string $description = null)
    {
        $this->resourceKey = $resourceKey;
        $this->description = $description;
    }

    public function getRemainingCredits()
    {
        $credits = Cache::get($this->resourceKey);
        if (empty($credits)) {
            return self::ZERO;
        }

        return (int)$credits;
    }

    public function test(): void
    {
        if ($this->getRemainingCredits() == self::ZERO) {
            throw new OutOfCredits($this->description ? "Out of credits: {$this->description}" : 'Credits exceeded');
        }
    }

    public function count(): void
    {
        with_cache_lock($this->resourceKey, function () {
            $this->test();

            $remainingCredits = $this->getRemainingCredits();
            if ($remainingCredits != self::UNLIMITED) {
                $remainingCredits -= 1;
                Cache::put($this->resourceKey, $remainingCredits);
            }
        });
    }

    public function setCredits($amount)
    {
        if (!is_int($amount)) {
            throw new Exception('Invalid value for CreditTracker credits. Try using "(int)$credit": '.$amount);
        }

        if ($amount < self::UNLIMITED) {
            throw new Exception('Invalid value for CreditTracker credits (Integer >= -1): '.$amount);
        }

        Cache::put($this->resourceKey, $amount);

        return $this;
    }

    public function rollback(): void
    {
        with_cache_lock($this->resourceKey, function () {
            $remainingCredits = $this->getRemainingCredits();

            if ($remainingCredits != self::UNLIMITED) {
                $remainingCredits += 1;
                Cache::put($this->resourceKey, $remainingCredits);
            }
        });
    }

    public function isUnlimited(): bool
    {
        return $this->getRemainingCredits() == self::UNLIMITED;
    }

    public function isZero()
    {
        return $this->getRemainingCredits() == self::ZERO;
    }

    public function topup($amount)
    {
        with_cache_lock($this->resourceKey, function () use ($amount) {
            $remainingCredits = $this->getRemainingCredits();

            if ($remainingCredits != self::UNLIMITED) {
                $remainingCredits += $amount;
                Cache::put($this->resourceKey, $remainingCredits);
            } else {
                throw new Exception('Cannot topup credits, already UNLIMITED');
            }
        });
    }
}