PollingHelper - sebamar88/bytekit GitHub Wiki
🔄 PollingHelper
EN: Intelligent polling utility with configurable backoff strategies, abort support, jitter, per-attempt timeouts, and performance metrics. Supports class-based usage, static convenience methods, and a factory function.
ES: Utilidad de polling inteligente con estrategias de backoff configurables, soporte de aborto, jitter, timeouts por intento y métricas de rendimiento. Soporta uso basado en clases, métodos estáticos de conveniencia y función factoría.
📦 Import
import { PollingHelper, createPoller } from "bytekit/polling-helper";
// or | o también:
import { PollingHelper, createPoller } from "bytekit";
⚙️ Constructor
const poller = new PollingHelper<T>(fn: () => Promise<T>, options?: PollingOptions<T>);
PollingOptions<T>
| Property / Propiedad | Type / Tipo | Default | Description (EN) | Descripción (ES) |
|---|---|---|---|---|
interval |
number |
1000 |
Base polling interval in milliseconds | Intervalo base de polling en milisegundos |
maxAttempts |
number |
Infinity |
Maximum number of polling attempts | Número máximo de intentos de polling |
maxDuration |
number |
Infinity |
Maximum total duration in milliseconds | Duración máxima total en milisegundos |
backoffMultiplier |
number |
1 |
Multiplier applied to interval after each attempt | Multiplicador aplicado al intervalo después de cada intento |
maxBackoffInterval |
number |
30000 |
Maximum interval after backoff scaling | Intervalo máximo después de escalar backoff |
stopCondition |
(result: T) => boolean |
() => true |
Predicate — polling stops when this returns true |
Predicado — el polling se detiene cuando retorna true |
onAttempt |
(attempt, result?, error?) => void |
no-op | Callback fired after each attempt | Callback ejecutado después de cada intento |
onSuccess |
(result, attempts) => void |
no-op | Callback fired on successful stop | Callback ejecutado al detenerse exitosamente |
onError |
(error, attempts) => void |
no-op | Callback fired on terminal error | Callback ejecutado en error terminal |
jitter |
boolean | number |
false |
Add random jitter to intervals (true = 10%, number = 0–100%) |
Agrega jitter aleatorio a los intervalos (true = 10%, number = 0–100%) |
attemptTimeout |
number |
undefined |
Timeout for each individual attempt (ms) | Timeout para cada intento individual (ms) |
retryOnError |
boolean |
true |
Whether to continue polling when an attempt throws | Si continuar el polling cuando un intento lanza error |
exponentialBase |
number |
2 |
Base for exponential backoff calculation | Base para el cálculo de backoff exponencial |
📋 Instance Methods / Métodos de Instancia
| Method / Método | Signature / Firma | Description (EN) | Descripción (ES) |
|---|---|---|---|
start |
start(): Promise<PollingResult<T>> |
Starts the polling loop | Inicia el ciclo de polling |
startWithAbort |
startWithAbort(): Promise<PollingResult<T>> |
Starts polling with an internal AbortController (enables abort()) |
Inicia polling con un AbortController interno (habilita abort()) |
abort |
abort(): void |
Aborts polling immediately | Aborta el polling inmediatamente |
📋 Static Methods / Métodos Estáticos
| Method / Método | Signature / Firma | Description (EN) | Descripción (ES) |
|---|---|---|---|
poll |
PollingHelper.poll<T>(fn, options?): Promise<PollingResult<T>> |
One-shot polling with default options | Polling de una sola vez con opciones por defecto |
pollWithBackoff |
PollingHelper.pollWithBackoff<T>(fn, options?): Promise<PollingResult<T>> |
Polling with exponential backoff (backoffMultiplier default: 2) |
Polling con backoff exponencial (backoffMultiplier default: 2) |
pollWithLinearBackoff |
PollingHelper.pollWithLinearBackoff<T>(fn, options?): Promise<PollingResult<T>> |
Polling with linear backoff (backoffMultiplier default: 1.5) |
Polling con backoff lineal (backoffMultiplier default: 1.5) |
🏭 Factory / Factoría
import { createPoller } from "bytekit/polling-helper";
const poller = createPoller<T>(fn: () => Promise<T>, options?: PollingOptions<T>);
// Returns a PollingHelper<T> instance / Retorna una instancia de PollingHelper<T>
📦 PollingResult<T>
EN: The result object returned when polling completes (either successfully or with an error).
ES: El objeto resultado retornado cuando el polling finaliza (ya sea exitosamente o con un error).
interface PollingResult<T> {
success: boolean; // Whether polling succeeded / Si el polling fue exitoso
result?: T; // The final result (if success) / El resultado final (si exitoso)
error?: Error; // The error (if failed) / El error (si falló)
attempts: number; // Total number of attempts / Número total de intentos
duration: number; // Total elapsed time in ms / Tiempo total transcurrido en ms
metrics?: { // Performance metrics (if any successful attempts)
minResponseTime: number; // Fastest attempt / Intento más rápido
maxResponseTime: number; // Slowest attempt / Intento más lento
avgResponseTime: number; // Average response time / Tiempo de respuesta promedio
};
}
🧠 How It Works / Cómo Funciona
EN:
PollingHelperexecutes the provided function repeatedly at the configured interval. After each attempt, it checksstopCondition(result)— iftrue, polling succeeds. The interval grows according tobackoffMultiplier(capped atmaxBackoffInterval). Jitter adds randomness to prevent thundering herd.startWithAbort()creates an internalAbortControllerthatabort()can trigger at any time.ES:
PollingHelperejecuta la función proporcionada repetidamente en el intervalo configurado. Después de cada intento, verificastopCondition(result)— si estrue, el polling tiene éxito. El intervalo crece segúnbackoffMultiplier(limitado amaxBackoffInterval). El jitter agrega aleatoriedad para prevenir efecto manada.startWithAbort()crea unAbortControllerinterno queabort()puede activar en cualquier momento.
start()
│
▼
┌─ attempt 1 ──────────────────────────────┐
│ fn() → result │
│ stopCondition(result)? │
│ ├── true → return { success: true } │
│ └── false → wait(interval + jitter) │
│ interval *= backoffMultiplier│
└───────────────────────────────────────────┘
│
▼
┌─ attempt 2 ... N ────────────────────────┐
│ (same loop until maxAttempts, │
│ maxDuration, or abort) │
└───────────────────────────────────────────┘
│
▼
return { success: false, error: "Max attempts exceeded" }
💡 Examples / Ejemplos
Basic polling / Polling básico
import { PollingHelper } from "bytekit/polling-helper";
const result = await PollingHelper.poll(
async () => {
const res = await fetch("/api/job/123");
return res.json();
},
{
interval: 2000,
maxAttempts: 10,
stopCondition: (job) => job.status === "completed",
}
);
if (result.success) {
console.log("Job done!", result.result);
console.log(`Completed in ${result.attempts} attempts (${result.duration}ms)`);
} else {
console.error("Polling failed:", result.error?.message);
}
Exponential backoff / Backoff exponencial
// Starts at 1s, doubles each time: 1s → 2s → 4s → 8s → ... (max 30s)
// Comienza en 1s, duplica cada vez: 1s → 2s → 4s → 8s → ... (máx 30s)
const result = await PollingHelper.pollWithBackoff(
() => checkDeploymentStatus(deployId),
{
interval: 1000,
maxDuration: 300_000, // 5 min max
stopCondition: (status) => status.phase === "ready",
jitter: 15, // 15% random jitter to avoid thundering herd
onAttempt: (n, res, err) => {
console.log(`Attempt ${n}:`, res?.phase ?? err?.message);
},
}
);
Linear backoff / Backoff lineal
// Grows at 1.5x: 1s → 1.5s → 2.25s → 3.375s → ...
// Crece a 1.5x: 1s → 1.5s → 2.25s → 3.375s → ...
const result = await PollingHelper.pollWithLinearBackoff(
() => fetchQueuePosition(),
{
interval: 1000,
maxAttempts: 20,
stopCondition: (pos) => pos === 0,
}
);
Instance with abort / Instancia con aborto
import { PollingHelper } from "bytekit/polling-helper";
const poller = new PollingHelper(
() => fetch("/api/status").then((r) => r.json()),
{
interval: 3000,
maxDuration: 60_000,
stopCondition: (data) => data.ready === true,
}
);
// Start with abort support / Iniciar con soporte de aborto
const resultPromise = poller.startWithAbort();
// Abort after user action / Abortar después de acción del usuario
cancelButton.addEventListener("click", () => poller.abort());
const result = await resultPromise;
if (!result.success) {
console.log(result.error?.message); // "Polling aborted"
}
Factory function / Función factoría
import { createPoller } from "bytekit/polling-helper";
const poller = createPoller(
async () => {
const res = await fetch("/api/payment/status");
return res.json();
},
{
interval: 2000,
maxAttempts: 30,
stopCondition: (payment) => payment.status !== "pending",
attemptTimeout: 5000, // 5s timeout per attempt / 5s timeout por intento
retryOnError: true,
onSuccess: (payment, attempts) => {
console.log(`Payment ${payment.status} after ${attempts} attempts`);
},
}
);
const result = await poller.start();
Using performance metrics / Usando métricas de rendimiento
const result = await PollingHelper.poll(
() => healthCheck(),
{
interval: 1000,
maxAttempts: 5,
stopCondition: (r) => r.healthy,
}
);
if (result.metrics) {
console.log(`Min response: ${result.metrics.minResponseTime}ms`);
console.log(`Max response: ${result.metrics.maxResponseTime}ms`);
console.log(`Avg response: ${result.metrics.avgResponseTime}ms`);
}
⚙️ Validation Rules / Reglas de Validación
EN: The constructor validates options and throws immediately if invalid:
ES: El constructor valida las opciones y lanza error inmediatamente si son inválidas:
| Rule / Regla | Error message |
|---|---|
interval <= 0 |
"interval must be greater than 0" |
maxAttempts <= 0 |
"maxAttempts must be greater than 0" |
maxDuration <= 0 |
"maxDuration must be greater than 0" |
backoffMultiplier < 1 |
"backoffMultiplier must be >= 1" |
maxBackoffInterval < interval |
"maxBackoffInterval must be >= interval" |
jitter < 0 || jitter > 100 |
"jitter percentage must be between 0 and 100" |
attemptTimeout <= 0 |
"attemptTimeout must be greater than 0" |
exponentialBase < 1 |
"exponentialBase must be >= 1" |
Véase También / See Also
- RetryPolicy — Retry strategies for single operations / Estrategias de reintento para operaciones individuales
- CircuitBreaker — Circuit breaker to avoid overwhelming failing services / Circuit breaker para evitar sobrecargar servicios fallidos
- RateLimiter — Rate limiting to control request frequency / Limitador de tasa para controlar frecuencia de solicitudes
- ApiClient — HTTP client with built-in retry / Cliente HTTP con reintento integrado