Cómo administrar los usuarios sin conexión en tus campañas de RBM

Un factor importante en el tiempo de entrega de los mensajes de tu agente es si el usuario al que intentas comunicarte tiene una conexión de datos en el momento en que el agente envía un mensaje. Si el usuario no tiene conexión, la plataforma de RBM almacena el mensaje y intenta entregarlo durante un máximo de 30 días. Si no se puede entregar el mensaje en ese momento, se quita del sistema.

Existen muchos motivos y situaciones por las que un usuario puede no tener conectividad cuando tu agente intente comunicarse con ellos. Podrían haber desactivado los datos para ahorrar dinero en su plan de telefonía móvil, podría estar en un avión sin Wi-Fi o si están en un túnel. Según la urgencia con la que deben llegar tus mensajes, el agente debe controlar de forma fluida a los usuarios sin conexión revocando los mensajes de RBM que no se entregaron y redirigiendo esos mensajes a través de un canal diferente.

En las siguientes secciones, se proporciona información detallada sobre cómo usar un Google Cloud Datastore para hacer un seguimiento los mensajes que envías y entregas, cómo usar cron para revocar mensajes no entregados y cómo redirigir esos mensajes a través de SMS.

Haz un seguimiento de los mensajes enviados

Cada mensaje que envía tu agente de RBM debe incluir un ID de mensaje único. Para hacer un seguimiento de los mensajes que envía tu agente, debes guardar el ID del mensaje, el número de teléfono y la marca de tiempo de cada mensaje.

Puedes usar diversas tecnologías para almacenar esta información, como las siguientes: en un almacén de datos de Google Cloud Datastore. Cloud Datastore es un servicio NoSQL altamente escalable que se encarga automáticamente de la fragmentación y la replicación. Este es un para almacenar datos no relacionales, como los mensajes que envía un agente. Cloud Datastore depende de tener una instancia activa de Google App Engine para que puedas usar App Engine para alojar tu agente de RBM y configurar una tarea de cron.

Hay bibliotecas cliente de Cloud Datastore disponibles en muchos lenguajes. Para En este ejemplo, puedes usar Node.js y basar el código del agente de RBM en el Muestra del primer agente de Node.js disponible en el sitio web para desarrolladores de RBM. En primer lugar, ejecuta el siguiente comando para instalar Cloud Datastore en mi proyecto de Node.js:

npm install --save @google-cloud/datastore

En el código fuente de tu agente, agrega una referencia global al cliente de Cloud Datastore biblioteca.

// Imports the Google Cloud client library
const Datastore = require('@google-cloud/datastore');

// Creates a client
const datastore = new Datastore({
    projectId: PROJECT_ID,
});

Con el objeto de almacén de datos creado, puedes introducir una función para almacenar los estados msisdn, message id, sent time y delivery de cada mensaje.

/**
 *   Records an entry in the Cloud Datastore to keep track of the
 *   messageIds sent to users and the delivery state.
 *
 *   @property {string} msisdn The user's phone number in E.164 format.
 *   @property {string} messageId The unique message identifier.
 *   @property {boolean} delivered True if message has been delivered.
 */
function saveMessage(msisdn, messageId, delivered) {
    const messageKey = datastore.key(['Message', messageId]);

    const dataForMessage = {
        key: messageKey,
        data: {
            id: messageId,
            msisdn: msisdn,
            lastUpdated: new Date().getTime(),
            delivered: delivered
        },
    };

    // Record that the message was sent.
    datastore
        .save(dataForMessage)
        .then(function() {
            console.log('saved message successfully');
        })
        .catch((err) => {
            console.error('ERROR:', err);
        });
}

Con esta función implementada, debes llamar a este método cada vez que tu agente envía un mensaje a un usuario. Cuando la biblioteca cliente de RBM para Node.js envía mensajes de RBM, la biblioteca proporciona un objeto de respuesta en el método de devolución de llamada que contiene el messageId del mensaje que se envió al usuario.

A continuación se incluye un ejemplo de cómo enviar un mensaje de texto sin formato a un usuario y grabarlo la información del mensaje después de comunicarte correctamente con la API de RBM.

let params = {
    messageText: 'Hello, World!',
    msisdn:'+12223334444',
};

// Send "Hello, World!" to the user.
rbmApiHelper.sendMessage(params,
function(response) {
    // Extract the message ID from the response
    let messageId = response.config.params.messageId;

    // Store the sent state in the Datastore
    saveMessage(phoneNumber, messageId, false);
});

Después de ejecutar el código, puedes inspeccionar Datastore desde la consola de Google Cloud en la vista Entidades de Datastore.

Datastore

Actualiza el estado de entrega de los mensajes

Ahora que tu agente almacena las solicitudes de mensajes enviados en Datastore, actualiza el estado de entrega una vez que el mensaje se entregue correctamente al dispositivo del usuario.

Los dispositivos de los usuarios envían eventos DELIVERED, READ y IS_TYPING a los agentes de RBM a través de Cloud Pub/Sub. En el controlador de Pub/Sub, verifica los eventos entregados y actualizarás la configuración de Datastore para la marca entregada a verdadero.

/**
 *   Uses the event received by the Pub/Sub subscription to send a
 *   response to the client's device.
 *   @param {object} userEvent The JSON object of a message
 *   received by the subscription.
 */
function handleMessage(userEvent) {
    if (userEvent.senderPhoneNumber != undefined) {
        let msisdn = userEvent.senderPhoneNumber;
        let messageId = userEvent.messageId;
        let eventType = userEvent.eventType;

        if(eventType === 'DELIVERED') {
            saveMessage(msisdn, messageId, true);
        }

        // TODO: Process message and create RBM response
    }
}

El agente guarda los mensajes salientes en Datastore y actualiza los datos cuando recibe una notificación de entrega. En la siguiente sección, verás cómo configurar un trabajo cron en App Engine de Google para que se ejecute cada 10 minutos y supervise los mensajes que no se entregaron.

Cron en App Engine de Google

Puedes usar trabajos cron para programar tareas en diferentes intervalos. En la app de Google Engine, un trabajo cron se configura con una descripción, una URL y un intervalo.

En las apps de Node.js, debes configurarlos en un archivo cron.yaml, que puedes implementar a App Engine con el SDK de Google Cloud. Obtén información sobre otros parámetros de configuración de idioma en Cómo programar trabajos con cron.yaml.

Debido a que la tarea cron necesita una URL, debes agregar un extremo de URL al archivo al router de la app al que llamará cron. Este webhook es responsable de consultar Datastore en busca de mensajes antiguos, borrarlos de la plataforma de RBM y enviarlos al usuario por SMS.

router.get('/expireMessages', function(req, res, next) {
    // TOOD: Query the Datastore for undelivered messages,
    // remove them from the RBM platform, and send them over SMS

    res.status(200).send();
});

A continuación, se encuentra la configuración del archivo cron.yaml para ejecutar este extremo cada 10 minutos.

cron:
-   description: "Processing expired RBM messages"
  url: /expireMessages
  schedule: every 10 mins

Para implementar las tareas de cron en App Engine, ejecuta el siguiente comando:

gcloud app deploy cron.yaml

Después de la implementación, App Engine configura automáticamente la tarea cron, y esta se puede ver en App Engine > Trabajos cron.

trabajos cron

Consulta Datastore en busca de mensajes no entregados.

En el webhook del trabajo cron que configuraste en la sección anterior, debes agregar lógica para buscar todos los mensajes enviados que tengan un estado delivered igual a falso y que tengan un tiempo de espera lastUpdated vez anterior al tiempo de espera predefinido para nuestro caso de uso. En este ejemplo, se vencen los mensajes que tienen más de una hora.

Para admitir una consulta compuesta como esta, Datastore debe tener índice compuesto que contiene las propiedades delivered y lastUpdated. Para puedes crear un archivo en tu proyecto llamado index.yaml la siguiente información:

indexes:
-   kind: Message
  properties:
  -   name: delivered
    direction: asc
  -   name: lastUpdated
    direction: desc

Al igual que para implementar el trabajo cron que definiste antes, usa el SDK de Google Cloud SDK para implementar el índice compuesto que definiste con el siguiente comando:

gcloud datastore create-indexes index.yaml

Después de la implementación, App Engine configura automáticamente el índice, y este último se muestra en Datastore > Índices.

Índices de Datastore

Con el índice definido, puedes volver al webhook que creaste para el archivo cron trabajo y completa la lógica de vencimiento del mensaje:

router.get('/expireMessages', function(req, res, next) {
    // Milliseconds in an hour
    const TIMEOUT = 3600000;

    // Threshold is current time minus one hour
    const OLD_MESSAGE_THRESHOLD = new Date().getTime() - TIMEOUT;

    // Create a query to find old undelivered messages
    const query = datastore
        .createQuery('Message')
        .filter('delivered', '=', false)
        .filter('lastUpdated', '<', OLD_MESSAGE_THRESHOLD);

    // Execute the query
    datastore.runQuery(query).then((results) => {
        for(var i = 0; i < results[0].length; i++) {
            let msisdn = results[0][i].msisdn;
            let messageId = results[0][i].id;

            // Stop the message from being sent
            rbmApiHelper.revokeMessage(msisdn, messageId);

            // Remove the message from the Datastore
            datastore.delete(results[0][i][datastore.KEY]);

            // TODO: Send the user the message as SMS
        }
    });

    res.status(200).send();
});

RBM no admite de forma nativa el resguardo de SMS, por lo que deberás implementar la lógica para enviar tus mensajes sin entregar a través de SMS.

Conclusión y resumen

Para administrar los usuarios sin conexión, puedes crear una lógica de revocación para RBM no entregados mensajes nuevos. La cantidad de tiempo que uses antes de que venza el mensaje depende de lo siguiente: qué tan urgente es la información que transmite. Con funciones urgentes del servidor, el tiempo de espera recomendado es inferior a dos horas.

En este ejemplo, se usa Cloud Datastore y Google App Engine para administrar el almacenamiento, consulta y revocación, sino también cualquier mecanismo de almacenamiento para hacer un seguimiento de tus mensajes enviados y entregados deberían funcionar.

¡Buena suerte y que disfrutes programando!