Especialidad technical

Construir una cola de SMS resiliente con Redis (Laravel Horizon, Bull, BullMQ)

File espera resiliente sms redis: guía técnica con ejemplos de código para desarrolladores en Marruecos.

Construir una cola de SMS resiliente con Redis (Laravel Horizon, Bull, BullMQ)
En este artículo
  1. Si envía sus SMS de marketing o transacciones directamente en el mismo hilo que la respuesta HTTP al cliente (por ejemplo, el usuario hace clic en "Registrarse", el servidor hace una llamada sincronizada [API SMS](/fr/api-sms-maroc/) y luego devuelve la página web), su arquitectura es vulnerable.
  2. Por qué un simple loop "por" no es suficiente en la producción
  3. Laravel Horizon para envío masivo (PHP)
  4. Ejemplo de Node.js con BullMQ

Si envía sus SMS de marketing o transacciones directamente en el mismo hilo que la respuesta HTTP al cliente (por ejemplo, el usuario hace clic en "Registrarse", el servidor hace una llamada sincronizada [API SMS](/fr/api-sms-maroc/) y luego devuelve la página web), su arquitectura es vulnerable.

Si el pasillo SMS marroquí (IAM, naranja, inwi) tarda 3 segundos en responder debido a una sobrecarga de red, el usuario esperará 3 segundos frente a una pantalla blanca. Peor aún, si la API está temporalmente fuera de línea, su script se desplomará, el usuario verá una página de error 500, y el SMS se perderá definitivamente.

Para una producción robusta, el envío de SMS debe siempre ser asincrónico a través de un Archivo de espera (Queue) gestionado por Redis.

Por qué un simple loop "por" no es suficiente en la producción

Imaginemos que tengas que dirigir una campaña a 50.000 clientes marroquíes. Un simple loop foreach o for saturará la memoria de tu servidor (Memory Exhaustion) y, sobre todo, desencadenará el mecanismo de Rate Limiting (Throttling) de la API. Obtendrás decenas de miles de errores 429 Too Many Requests.

La arquitectura asíncrona resuelve este problema: 1. Delegación (El Productor): Su aplicación web coloca instantáneamente 50.000 tareas (Jobs) que contienen el número y el mensaje en una base de datos Redis (en memoria, ultra-rápida).La página web responde al cliente en menos de 50ms.2. Ejecución (El Consumidor / Trabajador): Un proceso en el fondo "despila" las consultas Redis a su propio ritmo (ej.: 50 solicitudes por minuto) para mantenerse por debajo del límite de su clave API.

Laravel Horizon para envío masivo (PHP)

En el ecosistema PHP/Laravel, Horizon (associado con Redis) es la herramienta perfecta. Permite configurar fácilmente filas de espera específicas, throttling y tener un dashboard visual.

1. Configuración del Throttling (App/Jobs/SendSmsJob.php): En lugar de inundar la API, vamos a forzar al trabajador de Laravel a no superar las 50 consultas por minuto, con una gestión automática de retiros.

php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\Middleware\RateLimited;

class SendSmsJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $contact;
    public $message;

    // Définir la limite de débit : "sms-api" (défini dans AppServiceProvider)
    public function middleware()
    {
        return [new RateLimited('sms-api')];
    }

    public function handle()
    {
        // Appel API réel vers EnvoiSMS.ma
        $response = EnvoiSms::send($this->contact->phone, $this->message);
        
        if ($response->failed()) {
            throw new \Exception("Erreur API, Horizon relancera le job selon l'exponential backoff.");
        }
    }
}

2. Aislamiento de flujos críticos: En config/horizon.php, configure dos procesos de "workers" distintos. Un worker dedicado a la fila otp_critical (que nunca debe ralentizarse) y otro dedicado a la fila marketing_bulk (que puede girar tranquilamente en tarea de fondo).

Ejemplo de Node.js con BullMQ

Si su backend es Express o NestJS, BullMQ (el sucesor de Bull) es el estándar de la industria de Redis para gestionar millones de puestos de trabajo.

Configuración del límite de tasa nativo en BullMQ:

javascript
import { Queue, Worker } from 'bullmq';

// Création de la file d'attente liée à Redis
const smsQueue = new Queue('sms_dispatch', {
  connection: { host: 'localhost', port: 6379 }
});

// Ajout d'un SMS dans la file (Hyper rapide, le client n'attend pas)
await smsQueue.add('send_otp', { phone: '+212600000000', message: 'Code: 1234' });

// Le Worker qui traite l'envoi en respectant les limites de l'opérateur
const smsWorker = new Worker('sms_dispatch', async job => {
  const { phone, message } = job.data;
  
  try {
    await sendSmsViaApi(phone, message); // Votre appel HTTP axios ou fetch
  } catch (error) {
    // Si l'erreur est temporaire (ex: 503), BullMQ relancera le job
    throw new Error('Erreur API, réessayer plus tard.');
  }
}, {
  connection: { host: 'localhost', port: 6379 },
  limiter: {
    max: 50, // Maximum 50 requêtes...
    duration: 60000 // ...par minute, sous la limite de votre clé API (60 à 1 200 req/min selon l'offre).
  }
});

Al usar estas herramientas, no solo se garantiza que la carga de la API sea perfectamente suave, sino que, sobre todo, si su servidor se rompe en medio del envío de la campaña, los SMS no enviados permanecen almacenados en Redis. Al reiniciar el servidor, los trabajadores volverán exactamente donde se detuvieron. Cero doble, cero pérdida.

¿Por qué elegir EnvoiSMS para su negocio?

Entrega a Operadores

Rutas locales hacia IAM, Orange e Inwi, con conmutación automática entre rutas y estado de entrega enviado por webhook.

Optimización de Costes

WhatsApp Business API desde 0,65 MAD por mensaje. El mejor retorno de inversión.

Conformidad CNDP

Alojamiento que cumple con las regulaciones de protección de datos personales locales.

¿Cómo seguir el enrutamiento en las redes IAM, Inwi y Orange?
Nuestras rutas locales hacia Maroc Telecom (IAM), Orange e inwi, con conmutación automática entre rutas, devuelven un estado de entrega del operador para cada mensaje, por webhook. El plazo de entrega depende del operador y de la red del destinatario.
¿Cómo gestiona la plataforma el formato de los números marroquíes?
EnvoiSMS normaliza automáticamente los números introducidos (06..., 07..., 00212...) al estándar E.164 (+212) para evitar cualquier fallo en la entrega.

Artículos sugeridos

Formateo de SMS en Marruecos: saltos de línea, codificación GSM-7 frente a UCS-2 y optimización de costes
technical

Formateo de SMS en Marruecos: saltos de línea, codificación GSM-7 frente a UCS-2 y optimización de costes

Formato empresarial de WhatsApp en Marruecos: texto enriquecido, emojis y botones interactivos
technical

Formato empresarial de WhatsApp en Marruecos: texto enriquecido, emojis y botones interactivos

Autenticación WhatsApp en 1-Clic y One-Tap Autofill OTP en Marruecos
technical

Autenticación WhatsApp en 1-Clic y One-Tap Autofill OTP en Marruecos