mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 16:31:12 -05:00
Add database maintenance tooling
- Implement maintenance hooks (useMaintenanceTables, useVacuumTable, useAnalyzeTable, useReindexTable) - Add DatabaseMaintenance page and UI for vacuum/analyze/reindex - Wire new route / admin/database-maintenance and sidebar entry - Remove DatabaseMaintenance icon usage on page and align with AdminLayout props
This commit is contained in:
135
src/hooks/admin/useDatabaseMaintenance.ts
Normal file
135
src/hooks/admin/useDatabaseMaintenance.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { queryKeys } from '@/lib/queryKeys';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export interface MaintenanceTable {
|
||||
table_name: string;
|
||||
row_count: number;
|
||||
table_size: string;
|
||||
indexes_size: string;
|
||||
total_size: string;
|
||||
}
|
||||
|
||||
export interface MaintenanceResult {
|
||||
table_name: string;
|
||||
operation: string;
|
||||
started_at: string;
|
||||
completed_at: string;
|
||||
duration_ms: number;
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export function useMaintenanceTables() {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.admin.maintenanceTables(),
|
||||
queryFn: async () => {
|
||||
const { data, error } = await supabase.rpc('get_maintenance_tables');
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
return data as unknown as MaintenanceTable[];
|
||||
},
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
});
|
||||
}
|
||||
|
||||
export function useVacuumTable() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (tableName: string) => {
|
||||
const { data, error } = await supabase.rpc('run_vacuum_table', {
|
||||
table_name: tableName,
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
return data as unknown as MaintenanceResult;
|
||||
},
|
||||
onSuccess: (result) => {
|
||||
if (result.success) {
|
||||
toast.success(`Vacuum completed on ${result.table_name}`, {
|
||||
description: `Duration: ${Math.round(result.duration_ms)}ms`,
|
||||
});
|
||||
} else {
|
||||
toast.error(`Vacuum failed on ${result.table_name}`, {
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: queryKeys.admin.maintenanceTables() });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error('Vacuum operation failed', {
|
||||
description: error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useAnalyzeTable() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (tableName: string) => {
|
||||
const { data, error } = await supabase.rpc('run_analyze_table', {
|
||||
table_name: tableName,
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
return data as unknown as MaintenanceResult;
|
||||
},
|
||||
onSuccess: (result) => {
|
||||
if (result.success) {
|
||||
toast.success(`Analyze completed on ${result.table_name}`, {
|
||||
description: `Duration: ${Math.round(result.duration_ms)}ms`,
|
||||
});
|
||||
} else {
|
||||
toast.error(`Analyze failed on ${result.table_name}`, {
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: queryKeys.admin.maintenanceTables() });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error('Analyze operation failed', {
|
||||
description: error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useReindexTable() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (tableName: string) => {
|
||||
const { data, error } = await supabase.rpc('run_reindex_table', {
|
||||
table_name: tableName,
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
return data as unknown as MaintenanceResult;
|
||||
},
|
||||
onSuccess: (result) => {
|
||||
if (result.success) {
|
||||
toast.success(`Reindex completed on ${result.table_name}`, {
|
||||
description: `Duration: ${Math.round(result.duration_ms)}ms`,
|
||||
});
|
||||
} else {
|
||||
toast.error(`Reindex failed on ${result.table_name}`, {
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: queryKeys.admin.maintenanceTables() });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error('Reindex operation failed', {
|
||||
description: error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user