یک عامل اصلی در زمان تحویل پیامهای نماینده شما این است که آیا کاربری که میخواهید با آن ارتباط برقرار کنید، در زمانی که نماینده شما پیامی را ارسال میکند، اتصال داده دارد یا خیر. اگر کاربر آفلاین باشد، پلتفرم RBM پیام را ذخیره میکند و تا 30 روز تحویل میدهد. اگر پیام تا آن زمان قابل تحویل نباشد، از سیستم حذف می شود.
دلایل و موقعیتهای زیادی وجود دارد که در آن کاربر ممکن است زمانی که نماینده شما تلاش میکند با او تماس بگیرد، اتصال نداشته باشد. آنها میتوانستند دادهها را خاموش کنند تا در برنامه تلفن همراه خود صرفهجویی کنند، میتوانند در هواپیما بدون اتصال Wi-Fi باشند یا شاید در مترو در یک تونل باشند. بسته به فوریتهایی که پیامهای شما باید دریافت شوند، نماینده شما باید با ابطال پیامهای RBM تحویلنشده و مسیریابی مجدد آن پیامها از طریق کانالی دیگر، کاربران آفلاین را با ظرافت مدیریت کند.
در بخشهای زیر جزئیاتی در مورد نحوه استفاده از Google Cloud Datastore برای پیگیری پیامهایی که ارسال و تحویل میدهید، نحوه استفاده از cron برای لغو پیامهای تحویلنشده و نحوه مسیریابی مجدد آن پیامها از طریق پیامک ارائه میشود.
پیام های ارسالی را پیگیری کنید
هر پیامی که توسط نماینده RBM شما ارسال می شود باید دارای شناسه پیام منحصر به فرد باشد. برای پیگیری پیامهایی که نماینده شما ارسال میکند، باید شناسه پیام، شماره تلفن و مهر زمانی هر پیام را ذخیره کنید.
میتوانید از فناوریهای مختلفی برای ذخیره این اطلاعات استفاده کنید، از جمله Google Cloud Datastore. Cloud Datastore یک پایگاه داده NoSQL بسیار مقیاس پذیر است که به طور خودکار به اشتراک گذاری و تکرار رسیدگی می کند. این یک راه حل عالی برای ذخیره داده های غیر رابطه ای مانند پیام های ارسال شده توسط یک نماینده است. Cloud Datastore به داشتن یک نمونه فعال Google App Engine بستگی دارد، بنابراین میتوانید از App Engine برای میزبانی عامل RBM خود و پیکربندی یک کار cron استفاده کنید.
کتابخانه های سرویس گیرنده ای برای Cloud Datastore در بسیاری از زبان ها موجود است. برای این مثال، میتوانید از Node.js استفاده کنید و کد عامل RBM را بر اساس First Agent Node.js Sample موجود در وبسایت توسعهدهنده RBM قرار دهید. ابتدا با اجرای دستور زیر، Cloud Datastore را برای پروژه Node.js من نصب کنید:
npm install --save @google-cloud/datastore
در کد منبع عامل خود، یک مرجع جهانی به کتابخانه سرویس گیرنده Cloud Datastore اضافه کنید.
// Imports the Google Cloud client library
const Datastore = require('@google-cloud/datastore');
// Creates a client
const datastore = new Datastore({
projectId: PROJECT_ID,
});
با ایجاد شی datastore، می توانید تابعی را برای ذخیره msisdn ، message id ، sent time و وضعیت delivery برای هر پیام معرفی کنید.
/**
* 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);
});
}
با وجود این عملکرد، باید هر زمان که نماینده شما پیامی برای کاربر ارسال کرد، این روش را فراخوانی کنید. وقتی کتابخانه سرویس گیرنده RBM Node.js پیامهای RBM را ارسال میکند، کتابخانه یک شی پاسخ را در روش callback ارائه میکند که حاوی messageId برای پیامی است که برای کاربر ارسال شده است.
در زیر نمونه ای از ارسال یک پیام متنی ساده به کاربر و ثبت اطلاعات پیام پس از برقراری ارتباط موفقیت آمیز با 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);
});
پس از اجرای کد، می توانید Datastore را از Google Cloud Console در نمای Datastore Entities بررسی کنید.

وضعیت تحویل پیام ها را به روز کنید
اکنون که نماینده شما درخواستهای پیام ارسالی را در Datastore ذخیره میکند، پس از اینکه پیام با موفقیت به دستگاه کاربر تحویل داده شد، وضعیت تحویل را بهروزرسانی کنید.
دستگاههای کاربران رویدادهای DELIVERED ، READ و IS_TYPING را از طریق Cloud Pub/Sub به نمایندگان RBM ارسال میکنند. در کنترلر برای Pub/Sub، رویدادهای تحویلشده را بررسی کنید و تنظیمات Datastore را برای پرچم تحویلشده به درستی بهروزرسانی کنید.
/**
* 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
}
}
نماینده پیامهای خروجی را در Datastore ذخیره میکند و هنگام دریافت اعلان تحویل، دادهها را بهروزرسانی میکند. در بخش بعدی، نحوه راهاندازی cron job در موتور برنامه Google را ببینید تا هر 10 دقیقه یکبار اجرا شود تا پیامهای ارسالنشده را نظارت کند.
Cron در موتور برنامه گوگل
می توانید از cron jobs برای زمان بندی وظایف در فواصل زمانی مختلف استفاده کنید. در موتور برنامه گوگل، یک کار cron با یک توضیح، یک URL و یک فاصله پیکربندی شده است.
در برنامههای Node.js، اینها را در یک فایل cron.yaml پیکربندی میکنید که میتوانید با استفاده از Google Cloud SDK آن را در App Engine اجرا کنید. در مورد سایر تنظیمات پیکربندی زبان در زمانبندی کارهای با cron.yaml بخوانید.
از آنجایی که وظیفه cron به یک URL نیاز دارد، باید یک نقطه پایانی URL را به روتر app express اضافه کنید تا توسط cron فراخوانی شود. این وب هوک وظیفه پرس و جو از Datastore برای پیام های قدیمی، حذف آنها از پلتفرم RBM و ارسال آنها به کاربر از طریق 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();
});
در زیر پیکربندی فایل cron.yaml برای اجرای این نقطه پایانی هر 10 دقیقه است.
cron:
- description: "Processing expired RBM messages"
url: /expireMessages
schedule: every 10 mins
برای استقرار وظایف cron در App Engine، دستور زیر را اجرا کنید:
gcloud app deploy cron.yaml
پس از استقرار، App engine به طور خودکار وظیفه cron را پیکربندی می کند و این کار در قسمت App Engine > Cron jobs قابل مشاهده است.

از Datastore برای پیام های تحویل داده نشده پرس و جو کنید
در webhook برای کار cron که در بخش قبل تنظیم کردید، باید منطقی را اضافه کنید تا همه پیامهای ارسالی را که وضعیت delivered برابر با false دارند و دارای زمان lastUpdated قدیمیتر از زمان از پیش تعریفشده هستند، جستجو کنید. مورد استفاده در این مثال، پیامهای قدیمیتر از یک ساعت منقضی میشوند.
برای پشتیبانی از یک پرس و جو ترکیبی مانند این، Datastore باید یک فهرست ترکیبی داشته باشد که حاوی هر دو ویژگی delivered و lastUpdated باشد. برای این کار می توانید در پروژه خود فایلی به نام index.yaml با اطلاعات زیر ایجاد کنید:
indexes:
- kind: Message
properties:
- name: delivered
direction: asc
- name: lastUpdated
direction: desc
مشابه به کارگیری cron job که قبلاً تعریف کردهاید، از Google Cloud SDK برای استقرار فهرست ترکیبی که با دستور زیر تعریف کردهاید استفاده کنید:
gcloud datastore create-indexes index.yaml
پس از استقرار، موتور برنامه به طور خودکار ایندکس را پیکربندی می کند و ایندکس در زیر Datastore > Indexes نشان داده می شود.

با تعریف ایندکس، میتوانید به وب هوکی که برای کار cron ایجاد کردهاید برگردید و منطق انقضای پیام را تکمیل کنید:
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 به طور بومی از بازگشت اس ام اس پشتیبانی نمی کند، بنابراین باید منطقی را برای ارسال پیام های تحویل نشده خود از طریق SMS پیاده سازی کنید.
جمع بندی و خلاصه
برای رسیدگی به کاربران آفلاین، میتوانید منطق ابطال پیامهای RBM تحویلنشده ایجاد کنید. مدت زمانی که قبل از انقضای پیام استفاده می کنید بستگی به این دارد که اطلاعاتی که ارسال می کنید چقدر حساس به زمان است. با اطلاعات حساس به زمان، زمان توصیه شده کمتر از دو ساعت است.
این مثال از Cloud Datastore و Google App Engine برای مدیریت فضای ذخیرهسازی، پرس و جو و فرآیند لغو استفاده میکند، اما هر مکانیزم ذخیرهسازی برای پیگیری پیامهای ارسالی و ارسالی شما باید کار کند.
موفق باشید، و کد نویسی مبارک!