The isUpdating system for zero-downtime data updates
TamborraData features an automatic annual update system that detects when new data is being processed and shows a real-time updating banner to users. This happens every January without requiring downtime or manual intervention.
sys_status TableSingle-row table that stores the update status:
CREATE TABLE sys_status ( id integer PRIMARY KEY DEFAULT 1, is_updating boolean DEFAULT FALSE NOT NULL, updated_at timestamptz DEFAULT now() NOT NULL, notes text);
This is a singleton table - it only ever contains one row with id = 1.
getSysStatus() FunctionChecks the sys_status table and returns the current state:
export async function getSysStatus(): Promise<boolean | null> { const isDev = process.env.NODE_ENV === 'development'; const now = new Date(); const month = now.getMonth(); // 0 = January const day = now.getDate(); // Only check during January or February ≤ 20 if (isDev || month === 0 || (month === 1 && day <= 20)) { const { data, error } = await supabaseClient .from('sys_status') .select('is_updating') .eq('id', 1) .single(); if (error || !data) return false; return data.is_updating as boolean; } // Outside January/February → always false return false;}
Date optimization: The function only queries the database during January and early February. The rest of the year, it returns false without a database call.
React Query PollingThe frontend uses conditional polling to detect changes:
export function useStatisticsQuery<T>(year: string) { return useQuery({ queryKey: queryKeys.statistics(year), queryFn: ({ signal }) => fetchStatistics<T>(year, signal), // Infinite cache for historical data staleTime: Infinity, gcTime: Infinity, // Conditional polling refetchInterval: (query) => { const isUpdating = query.state.data?.isUpdating; return isUpdating ? 3000 : false; // Poll every 3s if updating }, // Refetch on window focus if updating refetchOnWindowFocus: (query) => { return query.state.data?.isUpdating === true; } });}
Automated Pipeline (Private Repository)The private pipeline runs during January:
'use client';import { ExclamationIcon } from '@/app/(frontend)/icons/icons';export function UpdatingPage() { return ( <div className="w-full h-screen flex flex-col items-center justify-center gap-4"> <ExclamationIcon /> <h4 className="text-base md:text-xl font-bold text-center"> La página se está actualizando... </h4> <p className="text-sm text-center text-(--color-text-secondary)"> Visita la página dentro de un rato para ver las estadísticas actualizadas. </p> </div> );}
# 1. Connect to your Supabase databasepsql postgres://your-db-url# 2. Set isUpdating to trueUPDATE sys_status SET is_updating = true WHERE id = 1;# 3. Visit http://localhost:3000/statistics/2024# You should see the updating banner# 4. After testing, reset to falseUPDATE sys_status SET is_updating = false WHERE id = 1;