Ctrl K
ComunidadGuías…

src/services/dashboardRefresh.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { useConsole } from '~/services/console'

export const CHART_REFRESH_STALE_MS = 5 * 60 * 1000
export const CHART_REFRESH_POLL_MS = 10 * 1000
export const CHART_REFRESH_TIMEOUT_MS = CHART_REFRESH_STALE_MS + CHART_REFRESH_POLL_MS

export interface ChartRefreshRequestResult {
  requested_at: string | null
  queued_app_ids: string[]
  queued_count: number
  skipped_count: number
}

export interface AppChartRefreshState {
  owner_org: string
  stats_refresh_requested_at: string | null
  stats_updated_at: string | null
}

export interface OrgChartRefreshState {
  stats_refresh_requested_at: string | null
  stats_updated_at: string | null
}

export function parseDashboardRefreshTimestamp(value: string | null | undefined): number | null {
  if (!value)
    return null

  const normalized = /(?:Z|[+-]\d{2}:\d{2})$/.test(value) ? value : `${value}Z`
  const parsed = Date.parse(normalized)
  return Number.isNaN(parsed) ? null : parsed
}

export function isChartRefreshInProgress(
  requestedAt: string | null | undefined,
  updatedAt: string | null | undefined,
  now: number = Date.now(),
): boolean {
  const requestedMs = parseDashboardRefreshTimestamp(requestedAt)
  if (requestedMs === null)
    return false
  if (now - requestedMs >= CHART_REFRESH_TIMEOUT_MS)
    return false

  const updatedMs = parseDashboardRefreshTimestamp(updatedAt)
  return updatedMs === null || requestedMs > updatedMs
}

export function isChartDataStale(
  updatedAt: string | null | undefined,
  now: number = Date.now(),
): boolean {
  const updatedMs = parseDashboardRefreshTimestamp(updatedAt)
  if (updatedMs === null)
    return true

  return now - updatedMs > CHART_REFRESH_STALE_MS
}

export function shouldAutoRequestChartRefresh(
  updatedAt: string | null | undefined,
  requestedAt: string | null | undefined,
  now: number = Date.now(),
): boolean {
  return isChartDataStale(updatedAt, now) && !isChartRefreshInProgress(requestedAt, updatedAt, now)
}

export function isOrgCacheReadyForRefresh(
  orgUpdatedAt: string | null | undefined,
  requestStartedAt: string | null | undefined,
): boolean {
  const requestStartedMs = parseDashboardRefreshTimestamp(requestStartedAt)
  if (requestStartedMs === null)
    return true

  const orgUpdatedMs = parseDashboardRefreshTimestamp(orgUpdatedAt)
  return orgUpdatedMs !== null && orgUpdatedMs >= requestStartedMs
}

export async function requestAppChartRefresh(appId: string): Promise<ChartRefreshRequestResult> {
  const { data, error } = await useConsole()
    .rpc('request_app_chart_refresh', { app_id: appId })
    .single()

  if (error)
    throw error

  return {
    queued_app_ids: data?.queued_app_ids ?? [],
    queued_count: data?.queued_count ?? 0,
    requested_at: data?.requested_at ?? null,
    skipped_count: data?.skipped_count ?? 0,
  }
}

export async function requestOrgChartRefresh(orgId: string): Promise<ChartRefreshRequestResult> {
  const { data, error } = await useConsole()
    .rpc('request_org_chart_refresh', { org_id: orgId })
    .single()

  if (error)
    throw error

  return {
    queued_app_ids: data?.queued_app_ids ?? [],
    queued_count: data?.queued_count ?? 0,
    requested_at: data?.requested_at ?? null,
    skipped_count: data?.skipped_count ?? 0,
  }
}

export async function fetchAppChartRefreshState(appId: string): Promise<AppChartRefreshState> {
  const { data, error } = await useConsole()
    .rpc('get_app_stats_refresh_state', { p_app_id: appId })
    .single()

  if (error || !data)
    throw error ?? new Error('App refresh state not found')

  return data
}

export async function fetchOrgChartRefreshState(orgId: string): Promise<OrgChartRefreshState> {
  const { data, error } = await useConsole()
    .rpc('get_org_stats_refresh_state', { p_org_id: orgId })
    .single()

  if (error || !data)
    throw error ?? new Error('Org refresh state not found')

  return data
}