From 709b4595ccd24084a73bc473475637911f4838c1 Mon Sep 17 00:00:00 2001 From: Soumyadas15 Date: Mon, 19 May 2025 01:44:45 +0530 Subject: [PATCH] chore(dev): fix redundant billing checks --- frontend/src/contexts/BillingContext.tsx | 80 +++++++++++++++++++ .../react-query/threads/use-billing-status.ts | 15 +++- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 frontend/src/contexts/BillingContext.tsx diff --git a/frontend/src/contexts/BillingContext.tsx b/frontend/src/contexts/BillingContext.tsx new file mode 100644 index 00000000..f54fc478 --- /dev/null +++ b/frontend/src/contexts/BillingContext.tsx @@ -0,0 +1,80 @@ +'use client'; + +import React, { createContext, useContext, useCallback, useEffect, useRef } from 'react'; +import { useBillingStatusQuery } from '@/hooks/react-query/threads/use-billing-status'; +import { BillingStatusResponse } from '@/lib/api'; +import { isLocalMode } from '@/lib/config'; + +interface BillingContextType { + billingStatus: BillingStatusResponse | null; + isLoading: boolean; + error: Error | null; + checkBillingStatus: () => Promise; + lastCheckTime: number | null; +} + +const BillingContext = createContext(null); + +export function BillingProvider({ children }: { children: React.ReactNode }) { + const billingStatusQuery = useBillingStatusQuery(); + const lastCheckRef = useRef(null); + const checkInProgressRef = useRef(false); + + const checkBillingStatus = useCallback(async (force = false): Promise => { + if (isLocalMode()) { + console.log('Running in local development mode - billing checks are disabled'); + return false; + } + + if (checkInProgressRef.current) { + return !billingStatusQuery.data?.can_run; + } + + const now = Date.now(); + if (!force && lastCheckRef.current && now - lastCheckRef.current < 60000) { + return !billingStatusQuery.data?.can_run; + } + + try { + checkInProgressRef.current = true; + if (force || billingStatusQuery.isStale) { + await billingStatusQuery.refetch(); + } + lastCheckRef.current = now; + return !billingStatusQuery.data?.can_run; + } catch (err) { + console.error('Error checking billing status:', err); + return false; + } finally { + checkInProgressRef.current = false; + } + }, [billingStatusQuery]); + + useEffect(() => { + if (!billingStatusQuery.data) { + checkBillingStatus(true); + } + }, [checkBillingStatus, billingStatusQuery.data]); + + const value = { + billingStatus: billingStatusQuery.data || null, + isLoading: billingStatusQuery.isLoading, + error: billingStatusQuery.error, + checkBillingStatus, + lastCheckTime: lastCheckRef.current, + }; + + return ( + + {children} + + ); +} + +export function useBilling() { + const context = useContext(BillingContext); + if (!context) { + throw new Error('useBilling must be used within a BillingProvider'); + } + return context; +} \ No newline at end of file diff --git a/frontend/src/hooks/react-query/threads/use-billing-status.ts b/frontend/src/hooks/react-query/threads/use-billing-status.ts index a310784b..de43b3ea 100644 --- a/frontend/src/hooks/react-query/threads/use-billing-status.ts +++ b/frontend/src/hooks/react-query/threads/use-billing-status.ts @@ -1,6 +1,7 @@ import { createQueryHook } from "@/hooks/use-query"; import { threadKeys } from "./keys"; -import { checkBillingStatus } from "@/lib/api"; +import { checkBillingStatus, BillingStatusResponse } from "@/lib/api"; +import { Query } from "@tanstack/react-query"; export const useBillingStatusQuery = (enabled = true) => createQueryHook( @@ -10,5 +11,17 @@ export const useBillingStatusQuery = (enabled = true) => enabled, retry: 1, staleTime: 1000 * 60 * 5, + gcTime: 1000 * 60 * 10, // 10 minutes (using gcTime instead of cacheTime) + refetchOnWindowFocus: false, // Disable refetch on window focus + refetchOnMount: false, // Disable refetch on component mount + refetchOnReconnect: false, // Disable refetch on reconnect + // Only refetch if the data is stale and the query is enabled + refetchInterval: (query: Query) => { + // If we have data and it indicates the user can't run, check more frequently + if (query.state.data && !query.state.data.can_run) { + return 1000 * 60; // Check every minute if user can't run + } + return false; // Don't refetch automatically otherwise + }, } )();