Plugin de retry

Plugin de retry

O Plugin de retry fornece uma robust mecanismo de retry for Module Federation. Quando módulos remotos ou recursos fail para carregar, it retries automatically para keep your app stable.

Features

  • Automatic retries: Improve stability by retrying falhou recurso carrega
  • Domain rotation: Switch across multiple backup domains automatically
  • Cache-busting: Add query parameters para avoid cache interference on retries
  • Flexible configuração: Customize retry times, delay, e callbacks

Instale

npm install @module-federation/retry-plugin

Migration Guia

De v0.18.x para v0.19.x

O plugin configuração has been simplified. O old fetch e script configuração objetos são deprecated:

// ❌ Old way (deprecated)
RetryPlugin({
  fetch: {
    url: 'http://localhost:2008/not-exist-mf-manifest.json',
    fallback: () => 'http://localhost:2001/mf-manifest.json',
  },
  script: {
    url: 'http://localhost:2001/static/js/async/src_App_tsx.js',
    customCreateScript: (url, attrs) => { /* ... */ },
  }
})

// ✅ New way
RetryPlugin({
  retryTimes: 3,
  retryDelay: 1000,
  domains: ['http://localhost:2001'],
  manifestDomains: ['http://localhost:2001'],
  addQuery: ({ times, originalQuery }) => `${originalQuery}&retry=${times}`,
})

Uso

Method1: Usado no plugin de build

rspack.config.ts
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';
import { defineConfig } from '@rsbuild/core';

export default defineConfig({
  plugins: [
    pluginReact(),
    pluginModuleFederation({
      runtimePlugins: [
        path.join(__dirname, './src/runtime-plugin/retry.ts'),
      ],
    }),
  ],
});
// ./src/runtime-plugin/retry.ts
import { RetryPlugin } from '@module-federation/retry-plugin';
const retryPlugin = () => RetryPlugin({
  retryTimes: 3,
  retryDelay: 1000,
  manifestDomains: ['https://domain1.example.com', 'https://domain2.example.com'],
  domains: ['https://cdn1.example.com', 'https://cdn2.example.com'],
  addQuery: ({ times, originalQuery }) => `${originalQuery}&retry=${times}`,
  onRetry: ({ times, url }) => console.log('retry', times, url),
  onSuccess: ({ url }) => console.log('success', url),
  onError: ({ url }) => console.log('error', url),
})
export default retryPlugin;

Method2: Usado no runtime puro

import { createInstance, loadRemote } from '@module-federation/enhanced/runtime';
import { RetryPlugin } from '@module-federation/retry-plugin';

const mf = createInstance({
  name: 'federation_consumer',
  remotes: [],
  plugins: [
    RetryPlugin({
      retryTimes: 3,
      retryDelay: 1000,
      manifestDomains: ['https://domain1.example.com', 'https://domain2.example.com'],
      domains: ['https://cdn1.example.com', 'https://cdn2.example.com'],
      addQuery: ({ times, originalQuery }) => `${originalQuery}&retry=${times}`,
      onRetry: ({ times, url }) => console.log('retry', times, url),
      onSuccess: ({ url }) => console.log('success', url),
      onError: ({ url }) => console.log('error', url),
    }),
  ],
});

Configuração

Básico

retryTimes

  • Tipo: number
  • Opcional
  • Number de retries, padrão é 3

retryDelay

  • Tipo: number
  • Opcional
  • Delay entre retries em milliseconds, padrão é 1000

Avançado

domains

  • Tipo: string[]
  • Opcional
  • Backup domains for rotation. Padrão é um empty array

addQuery

  • Tipo: boolean | ((context: { times: number; originalQuery: string }) => string)
  • Opcional
  • Whether para append uma query parameter quando retrying, padrão é false
  • Se uma função é fornecido, it receives retry count e o original query string, e deve retornar o novo query string

fetchOptions

  • Tipo: RequestInit
  • Opcional
  • Custom buscar opções, padrão é um empty objeto

manifestDomains

  • Tipo: string[]
  • Opcional
  • Domain rotation list usado quando fetching o manifest (e.g. mf-manifest.json). Takes precedence over domains for manifest buscar retries. Other recursos still use domains.

Callbacks

onRetry

  • Tipo: ({ times, domains, url, tagName }: { times?: number; domains?: string[]; url?: string; tagName?: string }) => void
  • Opcional
  • Triggered on each retry
  • Params: times current retry number, domains domain list, url request URL, tagName recurso tipo

onSuccess

  • Tipo: ({ domains, url, tagName }: { domains?: string[]; url?: string; tagName?: string; }) => void
  • Opcional
  • Triggered quando uma retry finally succeeds
  • Params: domains domain list, url request URL, tagName recurso tipo

onError

  • Tipo: ({ domains, url, tagName }: { domains?: string[]; url?: string; tagName?: string; }) => void
  • Opcional
  • Triggered quando all retries fail
  • Params: domains domain list, url request URL, tagName recurso tipo

Details

Retry logic

O plugin retries automatically quando uma recurso fails para carregar. O number de retries é controlled by retryTimes. Por exemplo:

  • retryTimes: 3 means up para 3 retries (depois o primeiro attempt)
  • Uma delay de retryDelay ms é applied antes each retry

Domain rotation

Quando domains é configured, o plugin rotates o host on each retry:

const retryPlugin = RetryPlugin({
  domains: [
    'https://cdn1.example.com',
    'https://cdn2.example.com',
    'https://cdn3.example.com'
  ],
});

Order de attempts:

  1. Initial attempt: original URL
  2. 1st retry: switch para cdn2.example.com
  3. 2nd retry: switch para cdn3.example.com
  4. 3rd retry: switch para cdn1.example.com

Cache-busting

Use addQuery para adicionar query parameters during retries para avoid cache interference:

const retryPlugin = RetryPlugin({
  addQuery: true, // adds ?retryCount=1, ?retryCount=2, etc.
});

Você pode também forneça uma função:

const retryPlugin = RetryPlugin({
  addQuery: ({ times, originalQuery }) => {
    return `${originalQuery}&retry=${times}&timestamp=${Date.now()}`;
  },
});

Callbacks

Você pode monitor o retry lifecycle com callbacks:

const retryPlugin = RetryPlugin({
  onRetry: ({ times, domains, url, tagName }) => {
    console.log(`Retry #${times}, domains: ${domains}, url: ${url}`);
  },
  onSuccess: ({ domains, url, tagName }) => {
    console.log(`Retry success, domains: ${domains}, url: ${url}`);
  },
  onError: ({ domains, url, tagName }) => {
    console.log(`Retry failed, domains: ${domains}, url: ${url}`);
  },
});

Callback params:

  • times: current retry count (começa de 1)
  • domains: o current domain list
  • url: current request URL
  • tagName: recurso tipo ('buscar' ou 'script')

Use cases

1. CDN failover

const retryPlugin = RetryPlugin({
  retryTimes: 2,
  domains: [
    'https://cdn1.example.com',
    'https://cdn2.example.com',
    'https://cdn3.example.com'
  ],
  addQuery: true,
});

2. Unstable networks

const retryPlugin = RetryPlugin({
  retryTimes: 5,
  retryDelay: 2000,
  onRetry: ({ times }) => {
    console.log(`Unstable network, retry #${times}`);
  },
});

3. Monitoring e logging

const retryPlugin = RetryPlugin({
  onRetry: ({ times, url }) => {
    analytics.track('resource_retry', { times, url });
  },
  onError: ({ url }) => {
    logger.error('Resource load failed after all retries', { url });
  },
});

Notes

  1. Performance: High retry counts increase carregamento time; tune for your environment
  2. Domains: Ensure all domains em domains serve o mesmo recurso
  3. Caching: Se addQuery é habilitado, consider CDN caching estratégia
  4. Erro handling: Depois all retries fail, o original erro é thrown; handle it upstream

Erro codes

  • RUNTIME_008: Resource carregue falha esse triggers o mecanismo de retry