Come gestire gli utenti offline nelle campagne RBM

Un fattore importante nel tempo di recapito dei messaggi dell'agente è se l'utente che stai tentando di raggiungere ha una connessione dati al momento in cui l'agente invia un messaggio. Se l'utente è offline, la piattaforma RBM archivia il messaggio e prova a effettuare l'invio per un massimo di 30 giorni. Se non è possibile consegnare il messaggio entro questa data, viene rimosso dal sistema.

Esistono molti motivi e situazioni in cui un utente potrebbe non disporre di connettività quando l'agente tenta di contattarlo. Potrebbe aver disattivato i dati per risparmiare sul piano tariffario, potrebbe essere in aereo senza Wi-Fi di collegamento o magari si trovano su una metropolitana in un tunnel. In base all'urgenza, a cui devono arrivare i messaggi, l'agente deve gestire utenti offline revocando i messaggi RBM non consegnati e reindirizzandoli nuovamente attraverso un altro canale.

Le sezioni seguenti forniscono dettagli su come utilizzare un Google Cloud Datastore per tenere traccia i messaggi che invii e recapita, come usare cron per revoca i messaggi non consegnati e le modalità di reindirizzamento tramite SMS.

Tieni traccia dei messaggi inviati

Ogni messaggio inviato dall'agente RBM deve includere un ID messaggio univoco. Per tenere traccia dei messaggi inviati dall'agente, devi salvare l'ID messaggio, il numero di telefono e il timestamp di ogni messaggio.

Puoi utilizzare varie tecnologie per memorizzare queste informazioni, tra cui: in un datastore Google Cloud. Cloud Datastore è un database NoSQL a scalabilità elevata che gestisce automaticamente il partizionamento orizzontale e la replica. È un'ottima soluzione per l'archiviazione di dati non relazionali, come i messaggi inviati da un agente. Cloud Datastore richiede un'istanza Google App Engine attiva, quindi puoi utilizzare App Engine per ospitare l'agente RBM e configurare un job cron.

Esistono librerie client per Cloud Datastore disponibili in molti linguaggi. Per questo esempio, puoi utilizzare Node.js e basare il codice dell'agente RBM sull'esempio di primo agente Node.js disponibile sul sito web per sviluppatori RBM. All'inizio, per installare Cloud Datastore per il mio progetto Node.js eseguendo seguente comando:

npm install --save @google-cloud/datastore

Nel codice sorgente dell'agente, aggiungi un riferimento globale alla libreria client Cloud Datastore.

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

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

Dopo aver creato l'oggetto datastore, puoi introdurre una funzione per l'archiviazione Stato msisdn, message id, sent time e delivery per ogni messaggio.

/**
 *   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);
        });
}

Una volta implementata questa funzione, devi chiamare questo metodo ogni volta che l'agente invia un messaggio a un utente. Quando la libreria client Node.js RBM invia messaggi RBM, fornisce un oggetto di risposta nel metodo di callback che contiene il messageId per il messaggio inviato all'utente.

Di seguito è riportato un esempio di invio di un messaggio in testo normale a un utente e di registrazione delle informazioni del messaggio dopo la comunicazione riuscita con l'API 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);
});

Dopo aver eseguito il codice, puoi ispezionare Datastore dalla console Google Cloud nella visualizzazione Entità Datastore.

Datastore

Aggiornare lo stato di recapito dei messaggi

Ora che l'agente archivia le richieste di messaggi inviate in Datastore, aggiorna stato di recapito quando il messaggio è stato recapitato al dispositivo dell'utente.

Utenti dispositivi inviano eventi DELIVERED, READ e IS_TYPING agli agenti RBM su Cloud Pub/Sub. Nel gestore di Pub/Sub, verifica gli eventi consegnati e aggiornare l'impostazione Datastore per il flag pubblicato su true.

/**
 *   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
    }
}

L'agente salva i messaggi in uscita nel Datastore e aggiorna i dati quando riceve una notifica di recapito. Nella sezione successiva, scopri come configurare un cron un job su App Engine di Google da eseguire ogni 10 minuti per monitorare le messaggi.

Cron su App Engine di Google

Puoi utilizzare i cron job per pianificare le attività a intervalli diversi. Nell'app di Google Engine, un cron job viene configurato con una descrizione, un URL e un intervallo.

Nelle app Node.js, le configuri in un file cron.yaml, di cui puoi eseguire il deployment in App Engine utilizzando Google Cloud SDK. Scopri di più su altre configurazioni di lingua in Pianificazione dei job con cron.yaml.

Poiché l'attività cron richiede un URL, devi aggiungere un endpoint URL al router dell'app Express da chiamare da cron. Questo webhook è responsabile dell'esecuzione di query Datastore per i messaggi precedenti, li elimina dalla piattaforma RBM e invia all'utente tramite 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();
});

Di seguito è riportata la configurazione del file cron.yaml per eseguire questo endpoint ogni 10 minuti.

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

Per eseguire il deployment delle attività cron in App Engine, esegui questo comando:

gcloud app deploy cron.yaml

Dopo il deployment, App Engine configura automaticamente l'attività cron e visibile in App Engine > Cron job.

cron job

Eseguire query in Datastore per i messaggi non consegnati

Nell'webhook per il job cron configurato nella sezione precedente, devi aggiungere la logica per cercare tutti i messaggi inviati con stato delivered uguale a false e con data e ora lastUpdated precedente a un timeout predefinito che abbia senso per il nostro caso d'uso. In questo esempio, i messaggi più vecchi di un'ora scadono.

Per supportare una query composta come questa, Datastore deve avere un indice composto contenente entrambe le proprietà delivered e lastUpdated. Per farlo, puoi creare nel progetto un file denominato index.yaml con le seguenti informazioni:

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

Come per il deployment del cron job definito in precedenza, utilizza l'SDK Google Cloud per eseguire il deployment dell'indice composito definito con il seguente comando:

gcloud datastore create-indexes index.yaml

Dopo il deployment, App Engine configura automaticamente l'indice, che viene visualizzato in Datastore > Indici.

Indici Datastore

Una volta definito l'indice, puoi tornare al webhook che hai creato per il cron e completa la logica di scadenza del messaggio:

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 non supporta a livello nativo il fallback SMS, pertanto dovrai implementare la logica per inviare i messaggi non recapitati tramite SMS.

Riepilogo e conclusione

Per gestire gli utenti offline, puoi creare una logica di revoca per i messaggi RBM non recapitati. La quantità di tempo da utilizzare prima della scadenza del messaggio dipende la sensibilità delle informazioni che trasmetti. Con i modelli informazioni, un timeout consigliato è inferiore a due ore.

Questo esempio utilizza Cloud Datastore e Google App Engine per gestire la procedura di archiviazione, query e revoca, ma qualsiasi meccanismo di archiviazione per tenere traccia dei messaggi inviati e recapitati dovrebbe funzionare.

Buona fortuna e buona programmazione.