diff --git a/.gitignore b/.gitignore index 57872d0..3a801af 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /vendor/ +composer.lock +test.php \ No newline at end of file diff --git a/composer.json b/composer.json index fccaf07..d93ce83 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "license": "MIT", "autoload": { "psr-4": { - "dino-ma\\php-speed-limit\\": "src/" + "SpeedLimit\\": "src/" }}, "require": { "php": "^7.1", diff --git a/src/Exceptions/RateException.php b/src/Exceptions/RateException.php new file mode 100644 index 0000000..a5454bf --- /dev/null +++ b/src/Exceptions/RateException.php @@ -0,0 +1,15 @@ + 0.000001, + self::MILLISECOND => 0.001, + self::SECOND => 1, + self::MINUTE => 60, + self::HOUR => 3600, + self::DAY => 86400, + self::WEEK => 604800, + self::MONTH => 2629743.83, + self::YEAR => 31556926, + ]; + + private $redis; + + private $redisKey; + + private $rate; + + private $timer; + + public function __construct(int $rate, string $timer, Client $redis) + { + if (!isset(self::$unitMap[$timer])) { + throw new \Exception('Failed is not timer'); + } + $this->rate = (int)$rate; + $this->timer = self::$unitMap[$timer]; + $this->redis = $redis; + } + + public function setRedisKey(string $id) : self + { + $this->redisKey = md5(sha1($id.'ACK'.$this->timer)); + + return $this; + } + + + public function getRedisKey() : string + { + return $this->redisKey; + } + + + public function rate() : bool + { + try { + $nowTime = microtime(true); + if (is_null($this->getRedisKey())) { + throw new RateException('You must be set redis key'); + } + $this->redis->watch($this->getRedisKey()); + $rateInfo = $this->redis->get($this->getRedisKey()); + $newVal = json_encode(['max_num' => $this->rate, 'timer' => $this->timer, 'last_time' => $nowTime]); + if (!is_null($rateInfo)) { + $rateObj = json_decode($rateInfo); + $remainTime = $nowTime - $rateObj->last_time; + if ($remainTime >= $this->timer) { + //超过时间则重新设置 + $this->redis->set($this->getRedisKey(), $newVal); + return true; + } + $rateObj->max_num--; + if ($rateObj->max_num > 0 && $remainTime > 0) { + //走本时间段内的次数减少 + $newVal = json_encode(['max_num' => $rateObj->max_num--, 'timer' => $remainTime, 'last_time' => $nowTime]); + $this->redis->set($this->getRedisKey(), $newVal); + return true; + } + } else { + $this->redis->set($this->getRedisKey(), $newVal); + return true; + } + return false; + } catch (RateException $exception) { + throw new RateException($exception->getMessage()); + } + } +} diff --git a/src/Services/SpeedLimitService.php b/src/Services/SpeedLimitService.php deleted file mode 100644 index b524754..0000000 --- a/src/Services/SpeedLimitService.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace DinoMa\PhpSpeedLimit\Services; - -interface SpeedLimitServiceInterface -{ - - public static function getInstance() : SpeedLimitService; - -} \ No newline at end of file diff --git a/src/SpeedLimit.php b/src/SpeedLimit.php deleted file mode 100644 index 9c33d64..0000000 --- a/src/SpeedLimit.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace DinoMa\PhpSpeedLimit; - - -use DinoMa\PhpSpeedLimit\Services\SpeedLimitService; - -class SpeedLimit extends SpeedLimitService -{ - public function test(): int - { - return parent::test(); - } - -} \ No newline at end of file