| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- import { keepPreviousData } from '@tanstack/react-query'
- import { useMemo } from 'react'
- import { CRON_JOBS_THRESHOLD } from './CronJobsTab.constants'
- import type { ConnectionVars } from '@/data/common.types'
- import { useCronJobsCountEstimateQuery } from '@/data/database-cron-jobs/database-cron-jobs-count-estimate-query'
- import { useCronJobsCountQuery } from '@/data/database-cron-jobs/database-cron-jobs-count-query'
- import {
- CronJob,
- useCronJobsInfiniteQuery,
- } from '@/data/database-cron-jobs/database-cron-jobs-infinite-query'
- import { useCronJobsMinimalInfiniteQuery } from '@/data/database-cron-jobs/database-cron-jobs-minimal-infinite-query'
- import { COST_THRESHOLD_ERROR } from '@/data/sql/execute-sql-query'
- import type { ResponseError } from '@/types'
- // =============================================================================
- // Input types
- // =============================================================================
- type UseCronJobsDataParams = ConnectionVars & {
- searchQuery: string | null
- }
- // =============================================================================
- // Shared state types (available in all states)
- // =============================================================================
- interface CronJobsGridState {
- rows: Array<CronJob>
- queryCost?: number
- isSuccess: boolean
- isLoading: boolean
- error: ResponseError | null
- isRefetching: boolean
- isFetchingNextPage: boolean
- hasNextPage: boolean
- isMinimal: boolean
- refetch: () => void
- fetchNextPage: () => void
- }
- interface CronJobsCountState {
- value: number | undefined
- isEstimate: boolean
- isLoading: boolean
- }
- // =============================================================================
- // Result type
- // =============================================================================
- interface UseCronJobsDataResult {
- /** State for the cron jobs grid */
- grid: CronJobsGridState
- /** State for the cron jobs count (exact or estimate) */
- count: CronJobsCountState
- }
- export function useCronJobsData({
- projectRef,
- connectionString,
- searchQuery,
- }: UseCronJobsDataParams): UseCronJobsDataResult {
- const isProjectReady = !!projectRef
- const {
- data: cronJobsData,
- error: cronJobsError,
- isSuccess: isCronJobsSuccess,
- isLoading: isCronJobsLoading,
- isRefetching: isCronJobsRefetching,
- isFetchingNextPage,
- hasNextPage = false,
- refetch: refetchCronJobs,
- fetchNextPage,
- } = useCronJobsInfiniteQuery(
- { projectRef, connectionString, searchTerm: searchQuery ?? undefined },
- {
- placeholderData: Boolean(searchQuery) ? keepPreviousData : undefined,
- staleTime: Infinity,
- }
- )
- const useMinimalQuery = cronJobsError?.message === COST_THRESHOLD_ERROR
- const {
- data: cronJobsMinimalData,
- error: cronJobsMinimalError,
- isSuccess: isCronJobsMinimalSuccess,
- isLoading: isCronJobsMinimalLoading,
- isRefetching: isCronJobsMinimalRefetching,
- isFetchingNextPage: isFetchingNextPageMinimal,
- hasNextPage: hasNextPageMinimal = false,
- refetch: refetchCronJobsMinimal,
- fetchNextPage: fetchNextPageMinimal,
- } = useCronJobsMinimalInfiniteQuery(
- { projectRef, connectionString, searchTerm: searchQuery ?? undefined },
- {
- placeholderData: Boolean(searchQuery) ? keepPreviousData : undefined,
- staleTime: Infinity,
- enabled: useMinimalQuery,
- }
- )
- const cronJobs = useMemo(() => {
- if (useMinimalQuery) {
- return cronJobsMinimalData?.pages.flatMap((page) => page) ?? []
- } else {
- return cronJobsData?.pages.flatMap((page) => page) ?? []
- }
- }, [useMinimalQuery, cronJobsData?.pages, cronJobsMinimalData?.pages])
- // Fetch count - gated on cron.job table size
- // Always fetch the estimate first (it's fast since it uses pg_stat)
- const {
- data: estimatedCount,
- isPending: isLoadingEstimatedCount,
- isError: isEstimatedCountError,
- } = useCronJobsCountEstimateQuery({ projectRef, connectionString }, { enabled: isProjectReady })
- const hasLargeCronJobsTable =
- typeof estimatedCount === 'number' && estimatedCount > CRON_JOBS_THRESHOLD
- // Exact count is enabled when the cron.job table is small enough
- const isCountQueryEnabled =
- isProjectReady && !isLoadingEstimatedCount && !isEstimatedCountError && !hasLargeCronJobsTable
- const { data: exactCount, isPending: isLoadingExactCount } = useCronJobsCountQuery(
- { projectRef, connectionString },
- { enabled: isCountQueryEnabled }
- )
- return {
- grid: {
- rows: cronJobs,
- queryCost: cronJobsError?.metadata?.cost,
- error: useMinimalQuery ? cronJobsMinimalError : cronJobsError,
- isSuccess: useMinimalQuery ? isCronJobsMinimalSuccess : isCronJobsSuccess,
- isLoading: useMinimalQuery ? isCronJobsMinimalLoading : isCronJobsLoading,
- isRefetching: useMinimalQuery ? isCronJobsMinimalRefetching : isCronJobsRefetching,
- isFetchingNextPage: useMinimalQuery ? isFetchingNextPageMinimal : isFetchingNextPage,
- hasNextPage: useMinimalQuery ? hasNextPageMinimal : hasNextPage,
- isMinimal: useMinimalQuery,
- refetch: useMinimalQuery ? refetchCronJobsMinimal : refetchCronJobs,
- fetchNextPage: useMinimalQuery ? fetchNextPageMinimal : fetchNextPage,
- },
- count: {
- value: isCountQueryEnabled ? exactCount : estimatedCount,
- isEstimate: !isCountQueryEnabled,
- isLoading: isCountQueryEnabled ? isLoadingExactCount : isLoadingEstimatedCount,
- },
- }
- }
|