feat(throttling): add global rate limit lockout flow

This commit is contained in:
2026-04-30 15:25:45 +03:30
parent 2772b36447
commit e635fd9c2c
10 changed files with 901 additions and 279 deletions

View File

@@ -1,9 +1,10 @@
import { createContext, useContext, useState, useEffect, type ReactNode } from "react"
import { fetchWorkspaces, createWorkspace, type Workspace } from "../api/workspaces"
import { useTranslation } from "../hooks/useTranslation"
import { toast } from "sonner"
import { Button } from "../components/ui/button"
import { Input } from "../components/ui/input"
import { fetchWorkspaces, createWorkspace, type Workspace } from "../api/workspaces"
import { useTranslation } from "../hooks/useTranslation"
import { isRateLimitActive } from "../lib/rateLimit"
import { toast } from "sonner"
import { Button } from "../components/ui/button"
import { Input } from "../components/ui/input"
interface WorkspaceContextType {
workspaces: Workspace[]
@@ -31,9 +32,10 @@ export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
const [isCreatingFirst, setIsCreatingFirst] = useState(false)
const isAuthenticated = !!localStorage.getItem("accessToken")
const rateLimited = isRateLimitActive()
const refreshWorkspaces = async () => {
if (!isAuthenticated) {
if (!isAuthenticated || isRateLimitActive()) {
setIsLoading(false)
return
}
@@ -66,13 +68,13 @@ export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
}
useEffect(() => {
if (!isAuthenticated) {
if (!isAuthenticated || rateLimited) {
setIsLoading(false)
return
}
void refreshWorkspaces()
}, [isAuthenticated])
}, [isAuthenticated, rateLimited])
const setActiveWorkspace = (workspace: Workspace | null) => {
setActiveWorkspaceState(workspace)
@@ -100,7 +102,7 @@ export const WorkspaceProvider = ({ children }: { children: ReactNode }) => {
}
// Force workspace creation if authenticated but none exist
if (!isLoading && isAuthenticated && workspaces.length === 0) {
if (!rateLimited && !isLoading && isAuthenticated && workspaces.length === 0) {
return (
<div className="min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900 px-4">
<div className="w-full max-w-md bg-white dark:bg-slate-800 p-8 rounded-xl shadow-lg border border-slate-200 dark:border-slate-700">