Reintentar con backoff creciente

Gana FxDart async

Requisito

El servicio de tarifas no está disponible exactamente dos veces, y luego sirve. Reintenta con backoff creciente — espera 40 ms tras el primer fallo, 80 ms tras el segundo — con un presupuesto de tres intentos. Imprime el payload, el conteo de intentos y la secuencia de backoff registrada (registrada cuando se elige cada espera, así que la salida es determinista). Las dos versiones deben imprimir las líneas que aparecen bajo Salida esperada.

Salida esperada
rates: EUR 0.85, GBP 0.74, JPY 148.20
attempts: 3
backoff: 40ms, 80ms

Lado a lado

RxDart

FxDart

Por qué difieren

El backoff es donde se rompe la simetría de una-sola-llamada del retry simple. El retryWhen de RxDart es un protocolo de meta-streams: por cada error, tu fábrica debe devolver un stream notificador — emite un valor para disparar el reintento, emite un error para rendirte. Así que «espera 40 ms, luego 80 ms» se convierte en mapear cada fallo a un stream Rx.timer, y como la fábrica solo ve un error a la vez, tanto el conteo de fallos como el presupuesto de intentos viven en variables mutables fuera del operador. Funciona, y es máximamente general — pero estás ensamblando a mano un bucle de reintentos a base de streams.

FxDart trata el backoff como lo que es: un número que depende de cuántas veces has fallado. El hook delay de retry recibe el conteo de fallos (1, 2, …) y devuelve un Duration — la política entera es una expresión, y el presupuesto es el mismo argumento attempts de antes. Nada en esperar entre intentos requiere un stream, y el lado pull nunca finge que sí.

Veredicto FxDart, por conteo de conceptos: un hook frente a una fábrica de streams notificadores, un contador externo y un stream de temporizador por fallo.

Benchmark

Apple M1 Max, 32 GB de RAM · Dart 3.12.2 (compilado AOT) · 2026-08-18

Caso async: la escala principal es N = 10,000, no 1,000,000. Cada elemento cuesta una vuelta del event loop en ambos lados, así que un millón de awaits reales mediría el event loop de Dart durante minutos — no el pipeline. Los retardos son de longitud cero y se conserva el límite de concurrencia del ejemplo; lo que comparan las barras es la maquinaria del pipeline.

N = 100

Tiempo Empate

RxDart 687 µs
FxDart 575 µs

Memoria pico Empate

RxDart 17.0 MB
FxDart 16.5 MB

N = 10,000

Tiempo Gana FxDart

RxDart 57.5 ms
FxDart 44.2 ms

Memoria pico Gana FxDart

RxDart 29.4 MB
FxDart 27.1 MB

Las barras son medianas de iteraciones cronometradas repetidas en procesos nuevos por lado (los N pequeños se agrupan por resolución del temporizador). Dos lados a menos del 5% entre sí — o a menos de 0.6 ms, una diferencia que nadie puede percibir — cuentan como empate; las carreras relativas ajustadas se vuelven a medir hasta 5 veces. En una app, cualquier cosa por debajo de unos pocos milisegundos es invisible para el usuario, gane la barra que gane. La memoria es el RSS pico del proceso. La VM de Dart y el dataset son idénticos en ambos lados, así que la diferencia entre las dos barras es lo que retiene el pipeline en sí.