mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Live mode polled every 10 seconds for as long as the page stayed open, including in hidden tabs and tabs left unattended for hours. Move the polling loop into a useLivePolling hook that: - stops polling while the tab is hidden and polls immediately when it is visible again - pauses live mode after 15 minutes of visible time with no pointer, key, wheel, or scroll activity, with a notice to resume it - backs off from 10s to 20s, 40s, then 60s while polls find no new rows, resetting on new rows, activity, or the tab becoming visible Track clicks on the notice's "Resume live mode" button (unified_logs_live_mode_resume_button_clicked). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.4 KiB
TypeScript
35 lines
1.4 KiB
TypeScript
export const LIVE_POLL_BASE_INTERVAL_MS = 10_000
|
|
export const LIVE_POLL_MAX_INTERVAL_MS = 60_000
|
|
export const LIVE_MODE_IDLE_TIMEOUT_MS = 15 * 60_000
|
|
|
|
/**
|
|
* Delay before the next live-mode poll. Doubles after each poll that finds no new rows
|
|
* (10s, 20s, 40s), capped at 60s, so quiet projects are polled less often.
|
|
*/
|
|
export function getLivePollDelay(consecutiveEmptyPolls: number): number {
|
|
if (!Number.isFinite(consecutiveEmptyPolls) || consecutiveEmptyPolls <= 0) {
|
|
return LIVE_POLL_BASE_INTERVAL_MS
|
|
}
|
|
return Math.min(
|
|
LIVE_POLL_BASE_INTERVAL_MS * 2 ** Math.floor(consecutiveEmptyPolls),
|
|
LIVE_POLL_MAX_INTERVAL_MS
|
|
)
|
|
}
|
|
|
|
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
typeof value === 'object' && value !== null
|
|
|
|
/**
|
|
* Whether a live-mode poll found no new rows. A poll is `fetchPreviousPage`, which prepends
|
|
* the new page, so its result's first page holds the rows that poll returned. Anything
|
|
* unrecognized counts as not empty, so polling never slows down on unexpected data.
|
|
*/
|
|
export function isEmptyLivePoll(result: unknown): boolean {
|
|
if (!isRecord(result) || !isRecord(result.data)) return false
|
|
const pages = result.data.pages
|
|
if (!Array.isArray(pages) || pages.length === 0) return false
|
|
const newestPage = pages[0]
|
|
if (!isRecord(newestPage) || !Array.isArray(newestPage.data)) return false
|
|
return newestPage.data.length === 0
|
|
}
|