Ważnym czynnikiem czasu dostarczania wiadomości agenta jest to, czy użytkownik, z którym próbujesz się skontaktować, ma połączenie do transmisji danych w momencie wysyłania wiadomości przez agenta. Jeśli użytkownik jest offline, platforma RBM przechowuje wiadomość i próbuje dostarczyć ją przez maksymalnie 30 dni. Jeśli nie uda się dostarczyć wiadomości w tym terminie, jest ona usuwana z systemu.
Istnieje wiele powodów, dla których użytkownik może nie mieć połączenia, gdy agent próbuje się z nim skontaktować. Mogli wyłączyć transmisję danych, aby zaoszczędzić pieniądze na abonamencie, być w samolocie bez połączenia z Wi-Fi lub być w metrze w tunelu. W zależności od tego, jak pilna jest potrzeba dostarczenia wiadomości, agent musi płynnie obsługiwać użytkowników offline, unieważniając niedostarczone wiadomości RBM i przekierowując je innymi kanałami.
W tym artykule pokażę, jak używać Google Cloud Datastore do śledzenia wysyłanych i dostarczanych wiadomości, jak używać narzędzia cron do revoke niedostarczonych wiadomości, a także jak przekierowywać te wiadomości przy użyciu SMS-ów.
Monitorowanie wysłanych wiadomości
Każda wiadomość wysyłana przez agenta RBM musi zawierać unikalny identyfikator wiadomości. Aby śledzić wiadomości wysyłane przez agenta, musisz zapisać identyfikator, numer telefonu i sygnaturę czasową każdej wiadomości.
Możesz przechowywać te informacje przy użyciu różnych technologii, ale w tym artykule używam Google Cloud Datastore. Cloud Datastore to wysoce skalowalna baza danych NoSQL, która automatycznie obsługuje fragmentację i replikację. To świetne rozwiązanie do przechowywania niepowiązanych danych, takich jak wiadomości wysłane przez agenta. Cloud Datastore wymaga aktywnej instancji Google App Engine, dlatego do hostowania agenta RBM i konfigurowania zadania cron używam App Engine.
Istnieją biblioteki klientów Cloud Datastore dostępne w wielu językach. W tym przykładzie używam Node.js i kodu agenta RBM na przykładzie pierwszego agenta Node.js dostępnego w witrynie dla programistów RBM. Najpierw zainstaluję Cloud Datastore dla mojego projektu Node.js. Aby to zrobić, uruchom to polecenie:
npm install --save @google-cloud/datastore
W kodzie źródłowym agenta dodaję globalne odwołanie do biblioteki klienta Cloud Datastore.
// Imports the Google Cloud client library
const Datastore = require('@google-cloud/datastore');
// Creates a client
const datastore = new Datastore({
projectId: PROJECT_ID,
});
Po utworzeniu obiektu datastore wprowadzam funkcję przechowywania stanu msisdn
, message id
, sent time
i delivery
dla każdej wiadomości.
/**
* 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);
});
}
Gdy to zrobisz, musisz wywoływać ją za każdym razem, gdy agent wysyła wiadomość do użytkownika. Gdy biblioteka klienta RBM Node.js wysyła komunikaty RBM, biblioteka dostarcza obiekt odpowiedzi w metodzie wywołania zwrotnego, który zawiera messageId
w przypadku wiadomości wysłanej do użytkownika.
Poniżej znajdziesz przykład wysyłania zwykłego tekstu do użytkownika i rejestrowania informacji o wiadomości po udanej komunikacji z interfejsem 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);
});
Po uruchomieniu powyższego kodu możesz sprawdzić Datastore w konsoli Google Cloud w widoku Encje w Datastore.
Aktualizowanie stanu dostarczenia wiadomości
Gdy agent przechowuje w Datastore żądania wiadomości, musimy zaktualizować stan dostarczenia po dostarczeniu wiadomości na urządzenie użytkownika.
Urządzenia użytkowników wysyłają zdarzenia DELIVERED
, READ
i IS_TYPING
do agentów RBM przez Cloud Pub/Sub. W module obsługi Pub/Sub sprawdź dostarczone zdarzenia i zmień ustawienie Datastore dla dostarczonej flagi na „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
}
}
Agent zapisuje wiadomości wychodzące w Datastore i aktualizuje dane po otrzymaniu powiadomienia o dostarczeniu. W następnej sekcji skonfigurujemy zadanie cron w Google App Engine, które będzie uruchamiać się co 10 minut i monitorować niedostarczone wiadomości.
Cron w Google App Engine
Za pomocą zadań cron możesz planować zadania w różnych odstępach czasu. W Google App Engine zadanie cron jest skonfigurowane z opisem, adresem URL i interwałem.
W aplikacjach Node.js konfigurujesz je w pliku cron.yaml
, który możesz wdrożyć w App Engine za pomocą pakietu SDK Google Cloud. Informacje o innych konfiguracjach konfiguracji językowych znajdziesz w artykule o planowaniu zadań z użyciem pliku cron.yaml.
Zadanie cron wymaga adresu URL, więc do routera Express aplikacji musisz dodać punkt końcowy URL, który będzie wywoływany przez program cron. Ten webhook odpowiada za wysyłanie zapytań do magazynu danych o starych wiadomościach, usuwanie ich z platformy RBM i wysyłanie ich do użytkownika SMS-em.
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();
});
Poniżej znajdziesz konfigurację pliku cron.yaml do wykonywania tego punktu końcowego co 10 minut.
cron:
- description: "Processing expired RBM messages"
url: /expireMessages
schedule: every 10 mins
Aby wdrożyć w App Engine zadania cron, uruchom to polecenie:
gcloud app deploy cron.yaml
Po wdrożeniu App Engine automatycznie konfiguruje zadanie cron. Możesz je wyświetlić w sekcji App Engine > Zadania cron.
Wysyłanie do Datastore zapytań o niedostarczone wiadomości
W webhooku zadania cron skonfigurowanego w poprzedniej sekcji musisz dodać funkcje logiczne umożliwiające wyszukiwanie wszystkich wysłanych wiadomości, w których stan delivered
ma wartość false (fałsz) i które są o lastUpdated
razy starsze niż wstępnie zdefiniowany limit czasu, który odpowiada naszym przypadku użycia. W tym przykładzie wygasają wiadomości starsze niż godzinę.
Aby móc obsługiwać takie zapytanie złożone, Datastore musi mieć indeks złożony zawierający zarówno właściwości delivered
, jak i lastUpdated
. Aby to zrobić, możesz utworzyć w projekcie plik o nazwie index.yaml z następującymi informacjami:
indexes:
- kind: Message
properties:
- name: delivered
direction: asc
- name: lastUpdated
direction: desc
Podobnie jak w przypadku wdrażania zdefiniowanego wcześniej zadania cron, użyj pakietu SDK Google Cloud do wdrożenia zdefiniowanego przez Ciebie indeksu złożonego za pomocą tego polecenia:
gcloud datastore create-indexes index.yaml
Po wdrożeniu App Engine automatycznie konfiguruje indeks, a indeks jest widoczny w sekcji Datastore > Indeksy.
Po zdefiniowaniu indeksu możemy wrócić do webhooka utworzonego dla zadania cron i dokończyć proces wygasania wiadomości:
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 nie obsługuje natywnie zastępczych SMS-ów, więc trzeba wdrożyć mechanizm wysyłania niedostarczonych wiadomości SMS-em.
Podsumowanie i TL;DR
Aby obsługiwać użytkowników offline, możesz utworzyć logikę unieważniania dla niedostarczonych wiadomości RBM. Czas potrzebny do wygaśnięcia wiadomości zależy od tego, jak bardzo pilne są przesyłane informacje. W przypadku informacji, które pilnie wymagają czasu, zalecany jest czas oczekiwania krótszy niż dwie godziny.
W tym przykładzie do zarządzania procesem przechowywania, zapytań i unieważniania używane są Cloud Datastore i Google App Engine, ale każdy mechanizm przechowywania danych do śledzenia wysyłanych i dostarczonych wiadomości powinien działać.
Powodzenia i życzę udanego programowania!