Skip to content

Commit

Permalink
区分接口限流和用户限流,付费用户不限流
Browse files Browse the repository at this point in the history
  • Loading branch information
Yurunsoft committed Sep 18, 2023
1 parent ceb4b3a commit 4b676fa
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 15 deletions.
10 changes: 10 additions & 0 deletions server/Enum/ApiStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,14 @@ abstract class ApiStatus extends BaseEnum
* @EnumItem("网络错误")
*/
public const NETWORK_ERROR = 40004;

/**
* @EnumItem("接口限流")
*/
public const API_RATE_LIMIT = 40005;

/**
* @EnumItem("用户限流")
*/
public const MEMBER_RATE_LIMIT = 40006;
}
26 changes: 19 additions & 7 deletions server/Module/Chat/ApiController/ChatController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace app\Module\Chat\ApiController;

use app\Enum\ApiStatus;
use app\Exception\BaseException;
use app\Exception\ErrorException;
use app\Module\Card\Service\MemberCardService;
use app\Module\Chat\Enum\SessionType;
use app\Module\Chat\Model\ChatSession;
use app\Module\Chat\Model\Redis\ChatConfig;
Expand Down Expand Up @@ -33,6 +36,9 @@ class ChatController extends HttpController
#[Inject]
protected ChatService $chatService;

#[Inject()]
protected MemberCardService $memberCardService;

#[
Action,
Route(method: RequestMethod::POST),
Expand Down Expand Up @@ -60,8 +66,8 @@ public function stream(string $id, string $token = ''): void
{
MemberUtil::allowParamToken($token);
$memberSession = MemberUtil::getMemberSession();
$this->response->setResponseBodyEmitter(new class($id, $this->chatService, $memberSession->getIntMemberId()) extends SseEmitter {
public function __construct(private string $id, private chatService $chatService, private int $memberId)
$this->response->setResponseBodyEmitter(new class($id, $this->chatService, $memberSession->getIntMemberId(), $this->memberCardService) extends SseEmitter {
public function __construct(private string $id, private chatService $chatService, private int $memberId, private MemberCardService $memberCardService)
{
}

Expand All @@ -70,12 +76,18 @@ protected function task(): void
$handler = $this->getHandler();
try
{
// 限流检测
goWait(function () {
$config = ChatConfig::__getConfig();
if (goWait(fn () => $this->memberCardService->getBalance($this->memberId, true)) <= 0)
{
// 限流检测
if (!goWait(function () {
$config = ChatConfig::__getConfig();

return RateLimiter::limit('rateLimit:chat:' . $this->memberId, $config->getRateLimitAmount(), unit: $config->getRateLimitUnit());
}, 30, true);
return RateLimiter::limit('rateLimit:chat:' . $this->memberId, $config->getRateLimitAmount(), static fn () => false, unit: $config->getRateLimitUnit());
}, 30, true))
{
throw new ErrorException('资源有限,免费用户有使用频率限制,请购买卡密解除限制', ApiStatus::MEMBER_RATE_LIMIT);
}
}

foreach ($this->chatService->chatStream($this->id, $this->memberId, IPUtil::getIP()) as $data)
{
Expand Down
26 changes: 19 additions & 7 deletions server/Module/Embedding/ApiController/EmbeddingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace app\Module\Embedding\ApiController;

use app\Enum\ApiStatus;
use app\Exception\BaseException;
use app\Exception\ErrorException;
use app\Module\Card\Service\MemberCardService;
use app\Module\Embedding\Enum\PublicProjectStatus;
use app\Module\Embedding\Model\EmbeddingProject;
use app\Module\Embedding\Model\EmbeddingQa;
Expand Down Expand Up @@ -43,6 +46,9 @@ class EmbeddingController extends HttpController
#[Inject()]
protected ChatService $chatService;

#[Inject()]
protected MemberCardService $memberCardService;

#[
Action(),
Route(method: RequestMethod::POST),
Expand Down Expand Up @@ -222,8 +228,8 @@ public function stream(string $id, string $token = ''): void
{
MemberUtil::allowParamToken($token);
$memberSession = MemberUtil::getMemberSession();
$this->response->setResponseBodyEmitter(new class($id, $this->chatService, $memberSession->getIntMemberId()) extends SseEmitter {
public function __construct(private string $id, private ChatService $chatService, private int $memberId)
$this->response->setResponseBodyEmitter(new class($id, $this->chatService, $memberSession->getIntMemberId(), $this->memberCardService) extends SseEmitter {
public function __construct(private string $id, private ChatService $chatService, private int $memberId, private MemberCardService $memberCardService)
{
}

Expand All @@ -232,12 +238,18 @@ protected function task(): void
$handler = $this->getHandler();
try
{
// 限流检测
goWait(function () {
$config = EmbeddingConfig::__getConfig();
if (goWait(fn () => $this->memberCardService->getBalance($this->memberId, true)) <= 0)
{
// 限流检测
if (!goWait(function () {
$config = EmbeddingConfig::__getConfig();

return RateLimiter::limit('rateLimit:embedding:chat:' . $this->memberId, $config->getChatRateLimitAmount(), unit: $config->getChatRateLimitUnit());
}, 30, true);
return RateLimiter::limit('rateLimit:embedding:chat:' . $this->memberId, $config->getChatRateLimitAmount(), static fn () => false, unit: $config->getChatRateLimitUnit());
}, 30, true))
{
throw new ErrorException('资源有限,免费用户有使用频率限制,请购买卡密解除限制', ApiStatus::MEMBER_RATE_LIMIT);
}
}

foreach ($this->chatService->chatStream($this->id, $this->memberId) as $data)
{
Expand Down
4 changes: 3 additions & 1 deletion server/Module/OpenAI/Model/Redis/OpenAIConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace app\Module\OpenAI\Model\Redis;

use app\Enum\ApiStatus;
use app\Exception\ErrorException;
use app\Module\Config\Annotation\ConfigModel;
use app\Module\Config\Model\Redis\Traits\TConfigModel;
use Imi\Model\Annotation\Column;
Expand Down Expand Up @@ -74,7 +76,7 @@ public function getRandomApi(?string $model = null): Api
return $api;
}
}
throw new \RuntimeException('没有可用的 API');
throw new ErrorException('没有可用的 API', ApiStatus::API_RATE_LIMIT);
}

/**
Expand Down
5 changes: 5 additions & 0 deletions web/src/views/card/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const route = useRoute()
const tab = ref(route.params.tab ? route.params.tab.toString() : 'list')
const success = ref(false)
const buyCardText = import.meta.env.VITE_BUY_CARD_TEXT
watch(success, (val) => {
if (val)
tab.value = 'list'
Expand All @@ -34,6 +36,9 @@ watch(success, (val) => {
<NTabPane name="activation" tab="卡号激活">
<CardActivation v-model:success="success" />
</NTabPane>
<NTabPane name="buy" tab="卡号购买">
<pre class="font-sans mt-2 leading-6 whitespace-pre-wrap">{{ buyCardText }}</pre>
</NTabPane>
<NTabPane name="expiredList" tab="过期卡包">
<CardList :expired="true" />
</NTabPane>
Expand Down

0 comments on commit 4b676fa

Please sign in to comment.