Umgang mit Offlinenutzern in RBM-Kampagnen

Ein wichtiger Faktor für die Zustellungszeit der Nachrichten Ihres Agents ist, ob der Nutzer, den Sie kontaktieren möchten, eine Datenverbindung hat, wenn der Agent eine Nachricht sendet. Wenn der Nutzer offline ist, speichert die RBM-Plattform die Nachricht und versucht, bis zu 30 Tage lang zuzustellen. Wenn die Nachricht bis dahin nicht zugestellt werden kann, wird sie aus dem System entfernt.

Es gibt viele Gründe und Situationen, in denen ein Nutzer möglicherweise keine Verbindung hat, wenn der Agent versucht, ihn zu kontaktieren. Sie hätten die mobile Datenverbindung deaktivieren können, um bei ihrem Mobilfunktarif Geld zu sparen, könnten in einem Flugzeug ohne WLAN-Verbindung oder vielleicht in der U-Bahn in einem Tunnel unterwegs sein. Abhängig von der Dringlichkeit, mit der Ihre Nachrichten eintreffen müssen, muss Ihr Agent Offline-Nutzer souverän handhaben, indem er nicht zugestellte RBM-Nachrichten widerruft und diese Nachrichten über einen anderen Kanal umleitet.

In diesem Artikel zeige ich Ihnen, wie Sie mit Google Cloud Datastore den Überblick über die gesendeten und zustellenden Nachrichten behalten, wie Sie mit Cron nicht zugestellte Nachrichten revoke und diese Nachrichten per SMS weiterleiten.

Nachverfolgen gesendeter Nachrichten

Jede Nachricht, die von deinem RBM-Agent gesendet wird, muss eine eindeutige Nachrichten-ID enthalten. Damit Sie den Überblick über die Nachrichten behalten, die Ihr Agent sendet, müssen Sie für jede Nachricht die Nachrichten-ID, die Telefonnummer und den Zeitstempel speichern.

Sie können zum Speichern dieser Informationen eine Vielzahl von Technologien verwenden. In diesem Artikel verwende ich jedoch einen Google Cloud Datastore. Cloud Datastore ist eine hoch skalierbare NoSQL-Datenbank, die Fragmentierung und Replikation automatisch durchführt. Es ist eine großartige Lösung zum Speichern nicht relationaler Daten wie der Nachrichten, die von einem Agent gesendet werden. Für Cloud Datastore ist eine aktive Google App Engine-Instanz erforderlich. Daher verwende ich App Engine, um meinen RBM-Agent zu hosten und einen Cronjob zu konfigurieren.

Es gibt Clientbibliotheken für Cloud Datastore in vielen Sprachen. In diesem Beispiel verwende ich Node.js und erstelle den RBM-Agent-Code auf dem First Agent Node.js-Beispiel, das auf der RBM-Entwicklerwebsite verfügbar ist. Als Erstes installiere ich Cloud Datastore für mein Node.js-Projekt. Dazu führe ich den folgenden Befehl aus:

npm install --save @google-cloud/datastore

Im Quellcode meines Agents füge ich einen globalen Verweis auf die Cloud Datastore-Clientbibliothek hinzu.

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

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

Mit dem erstellten Datenspeicherobjekt füge ich eine Funktion zum Speichern der Status msisdn, message id, sent time und delivery für jede Nachricht ein.

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

Nachdem Sie diese Funktion eingerichtet haben, müssen Sie diese Methode immer dann aufrufen, wenn Ihr Agent eine Nachricht an einen Nutzer sendet. Wenn die RBM-Node.js-Clientbibliothek RBM-Nachrichten sendet, stellt die Bibliothek in der Callback-Methode ein Antwortobjekt bereit, das die messageId für die an den Nutzer gesendete Nachricht enthält.

Im Folgenden finden Sie ein Beispiel für das Senden einer einfachen Textnachricht an einen Nutzer und das Aufzeichnen der Nachrichteninformationen nach erfolgreicher Kommunikation mit der RBM API.

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

Nachdem Sie den obigen Code ausgeführt haben, können Sie den Datenspeicher über die Google Cloud Console in der Ansicht Datastore-Entitäten prüfen.

Datastore

Zustellungsstatus von Nachrichten aktualisieren

Nachdem der Agent die gesendeten Nachrichtenanfragen im Datenspeicher gespeichert hat, müssen wir den Zustellungsstatus aktualisieren, sobald die Nachricht erfolgreich an das Gerät des Nutzers zugestellt wurde.

Nutzergeräte senden DELIVERED-, READ- und IS_TYPING-Ereignisse über Cloud Pub/Sub an RBM-Agents. Prüfen Sie im Handler für Pub/Sub, ob Ereignisse übermittelt wurden, und aktualisieren Sie die Datastore-Einstellung für das übermittelte Flag auf „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
    }
}

Der Agent speichert ausgehende Nachrichten im Datenspeicher und aktualisiert die Daten, wenn er eine Zustellbenachrichtigung erhält. Im nächsten Abschnitt richten wir in der Google App Engine einen Cronjob ein, der alle 10 Minuten ausgeführt wird, um nicht zugestellte Nachrichten zu überwachen.

Cron in der Google App Engine

Mit Cronjobs können Sie Aufgaben in verschiedenen Intervallen planen. In App Engine von Google wird ein Cronjob mit einer Beschreibung, einer URL und einem Intervall konfiguriert.

In Node.js-Anwendungen konfigurieren Sie diese in einer cron.yaml-Datei, die Sie mit dem Google Cloud SDK in App Engine bereitstellen können. Informationen zur Konfiguration anderer Sprachen finden Sie unter Jobs mit cron.yaml planen.

Da die Cron-Aufgabe eine URL benötigt, müssen Sie dem Express-App-Router einen URL-Endpunkt hinzufügen, der von Cron aufgerufen werden soll. Dieser Webhook ist dafür verantwortlich, alte Nachrichten im Datenspeicher abzufragen, sie von der RBM-Plattform zu löschen und sie per SMS an den Nutzer zu senden.

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();
});

Unten sehen Sie die Konfiguration der cron.yaml-Datei, mit der dieser Endpunkt alle 10 Minuten ausgeführt wird.

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

Führen Sie den folgenden Befehl aus, um die Cron-Aufgaben in App Engine bereitzustellen:

gcloud app deploy cron.yaml

Nach der Bereitstellung konfiguriert die App Engine die Cron-Aufgabe automatisch. Die Aufgabe wird unter App Engine > Cronjobs angezeigt.

Cronjobs

Datastore auf nicht zugestellte Nachrichten abfragen

Im Webhook für den Cronjob, den Sie im vorherigen Abschnitt eingerichtet haben, müssen Sie eine Logik hinzufügen, um alle gesendeten Nachrichten zu suchen, deren delivered-Status „false“ ist und deren lastUpdated-Zeit älter als ein vordefiniertes Zeitlimit ist, das in unserem Anwendungsfall sinnvoll ist. In diesem Beispiel laufen Nachrichten ab, die älter als eine Stunde sind.

Damit eine solche zusammengesetzte Abfrage unterstützt werden kann, muss der Datenspeicher einen zusammengesetzten Index haben, der die Attribute delivered und lastUpdated enthält. Erstellen Sie dazu in Ihrem Projekt eine Datei namens index.yaml mit den folgenden Informationen:

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

Verwenden Sie ähnlich wie beim zuvor definierten Cronjob das Google Cloud SDK, um den zusammengesetzten Index bereitzustellen, den Sie mit dem folgenden Befehl definiert haben:

gcloud datastore create-indexes index.yaml

Nach der Bereitstellung konfiguriert die App Engine automatisch den Index. Er kann unter Datastore > Indexe angezeigt werden.

Datenspeicherindexe

Wenn der Index definiert ist, können wir zu dem Webhook zurückkehren, den Sie für den Cronjob erstellt haben, und die Ablauflogik für die Nachrichten vervollständigen:

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 unterstützt nicht nativ SMS-Fallback, daher müssen Sie die Logik implementieren, um Ihre nicht zugestellten Nachrichten per SMS zu senden.

Zusammenfassung und Kurzfassung

Zur Verarbeitung von Offlinenutzern können Sie eine Widerrufslogik für nicht zugestellte RBM-Nachrichten erstellen. Wie lange es dauert, bis die Nachricht abläuft, hängt davon ab, wie zeitkritisch die von Ihnen übermittelten Informationen sind. Bei zeitkritischen Informationen empfehlen wir ein Zeitlimit von weniger als zwei Stunden.

In diesem Beispiel werden Cloud Datastore und Google App Engine zur Verwaltung des Speicher-, Abfrage- und Sperrprozesses verwendet. Es sollte jedoch jeder Speichermechanismus zum Verfolgen Ihrer gesendeten und zugestellten Nachrichten funktionieren.

Viel Erfolg und viel Spaß beim Programmieren!