HEX
Server: Apache
System: Linux server3230.server-vps.com 5.15.0-46-generic #49-Ubuntu SMP Thu Aug 4 18:03:25 UTC 2022 x86_64
User: lzgqnjwu (1002)
PHP: 7.4.33
Disabled: NONE
Upload Files
File: //proc/1122/cwd/common/components/TelegramRateLimiter.php
<?php

namespace common\components;

use yii\base\Component;
use yii\di\Instance;
use yii\redis\Connection;

/**
 * Global Telegram send rate per bot: max $maxPerSecond requests per rolling 1s window (Redis ZSET).
 */
class TelegramRateLimiter extends Component
{
    public $redis = 'redis';

    /** @var int max API calls per second (Telegram global ~30; we use 25) */
    public $maxPerSecond = 25;

    /** @var float window seconds */
    public $windowSeconds = 1.0;

    public function init(): void
    {
        parent::init();
        $this->redis = Instance::ensure($this->redis, Connection::class);
    }

    public function acquire(int $botId): void
    {
        while (!$this->tryAcquire($botId)) {
            sleep(1);
        }
    }

    public function tryAcquire(int $botId): bool
    {
        $key = 'tg:rl:' . $botId;
        $now = microtime(true);
        $windowStart = $now - $this->windowSeconds;
        $member = uniqid('m', true);

        /** @var Connection $redis */
        $redis = $this->redis;
        $redis->executeCommand('ZREMRANGEBYSCORE', [$key, (string) 0, (string) $windowStart]);
        $n = (int) $redis->executeCommand('ZCARD', [$key]);
        if ($n >= $this->maxPerSecond) {
            return false;
        }
        $redis->executeCommand('ZADD', [$key, (string) $now, $member]);
        $redis->executeCommand('EXPIRE', [$key, (string) 3]);

        return true;
    }
}