SPB Git forge

spb/websensor

Public
33commits 1branches 0releases
3.4 MBsize
maindefault branch
10 days agolast push
TypeScript 55.4% Python 43.2% SQL 1.2%
1.9 KB · 54 lines typescript
Raw Blame History
1import { TIER_BASE_INTERVAL, TIER_MAX_INTERVAL, TIER_MIN_INTERVAL, type Tier } from "./taxonomy";23/**4 * Adaptive polling. The next interval depends on tier bounds, how recently the sensor5 * changed, how often it changes, error state and HTTP cache behaviour (304s are cheap6 * so we can afford to poll a bit faster).7 */8export interface ScheduleInput {9  tier: Tier;10  baseIntervalSeconds?: number | null;11  lastChangeAt?: Date | null;12  /** changes in the last 7 days */13  changes7d: number;14  /** meaningful events in the last 7 days */15  events7d: number;16  consecutiveErrors: number;17  /** last run served 304 Not Modified */18  lastWas304: boolean;19  now?: Date;20}2122export function nextIntervalSeconds(i: ScheduleInput): number {23  const now = i.now ?? new Date();24  const base = i.baseIntervalSeconds ?? TIER_BASE_INTERVAL[i.tier];25  const min = TIER_MIN_INTERVAL[i.tier];26  const max = TIER_MAX_INTERVAL[i.tier];27  let interval = base;2829  if (i.lastChangeAt) {30    const ageMin = (now.getTime() - i.lastChangeAt.getTime()) / 60000;31    if (ageMin < 15) interval = base / 6; // burst window32    else if (ageMin < 60) interval = base / 3;33    else if (ageMin < 24 * 60) interval = base / 1.5;34    else if (ageMin > 14 * 24 * 60) interval = base * 3;35    else if (ageMin > 7 * 24 * 60) interval = base * 2;36  } else {37    interval = base * 1.5;38  }3940  // Frequent changers get tighter polling; the weight is bounded so the tier still rules.41  const perDay = i.changes7d / 7;42  if (perDay >= 3) interval *= 0.6;43  else if (perDay >= 1) interval *= 0.8;44  if (i.events7d >= 3) interval *= 0.8;4546  if (i.lastWas304) interval *= 0.85;4748  if (i.consecutiveErrors > 0) interval = Math.max(interval, base) * Math.min(16, 2 ** i.consecutiveErrors);4950  // ±10 % jitter to avoid thundering herds51  const jitter = 1 + (Math.random() * 0.2 - 0.1);52  return Math.round(Math.max(min, Math.min(max * (i.consecutiveErrors ? 4 : 1), interval * jitter)));53}54