Tech Blog

Leveraging the public cloud: Sending notifications to patrons

Alma’s software-as-a-service offering allows institutions to reduce expenditures on internal IT infrastructure. Many institutions are looking to extend that savings to integrations and services which support the library system. The public cloud provides an opportunity to host those additional services in a cost-effective and robust infrastructure. This is the first in a series of blog posts which will demonstrate ways to leverage the public cloud to extend the functionality offered by Alma.

In this article, we will show how to use Alma Analytics, Amazon Web Services Lambda, and the Twilio messaging service to remind patrons that they have a book due tomorrow.

Alma Analytics

We’ve created a report called “Ex Libris – Loans due tomorrow with patron and item information” and stored it in the Shared folder of Alma Analytics. The report returns a row for each item which is due the following day, and includes the title and the patron’s contact information. We’ll want to send a notification to the patron the day before the item is due.

We can use the Analytics API to retrieve the report and get the same details in XML format:

<Row>
  <Column0>0</Column0>
  <Column1>Josh</Column1>
  <Column2>Weisman</Column2>
  <Column3>joshw</Column3>
  <Column4>2015-11-08</Column4>
  <Column5>20140710</Column5>
  <Column6>j************.com</Column6>
  <Column8>+972********</Column8>
  <Column9>History curatorship</Column9>
</Row>

AWS Lambda

We now need a way to call the report daily and process the results. We don’t want to set up a server in our local institution to run the job. The Amazon Web Services Lambda offering hosts micro-services without the need to worry about virtual machines or low-level infrastructure. Lambda supports several development environments including Node.js, Java, and Python.

Let’s take a look at the small application we built to process the daily report. The basic flow is as follows:

  1. Retrieve the report via the Analytics API
  2. Parse the XML and use XPath to retrieve the items which are due, then convert the result to JSON
  3. Send the notification to the patron

Our code is written in Node.js. The Lambda service requires a single entry point to execute when called, so we will create an index.js file with a single “exports” statement. We use the async library to handle the flow of the application.

Let’s take a look at each section in greater detail.

Retrieve the XML

We’ve created a small utility file to help call the Alma API. The utility makes the REST request with the appropriate headers. So our main function uses the utility method and passes in the callback:

alma.getXml('/analytics/reports?path=%2Fshared%2FCommunity%2FReports%2FShared%20Reports%2FReports%2FFulfillment%20-%20Misc.%20reports%2FEx%20Libris%20-%20Loans%20due%20tomorrow%20with%20patron%20and%20item%20information',
  next);

Parse the XML

Now we need to parse the response from the API. After we find the relevant rows, we want to transform them into JSON so we can use them in our JavaScript code:

var doc = new dom().parseFromString(data);
var select = xpath.useNamespaces(namespaces);
var nodes = select('/report/QueryResult/ResultXml/rowset:rowset/rowset:Row', doc);
parser.parseString("<items>" + nodes.join("") + "</items>", next);

Send the notification

Now that we have the items which are due tomorrow, we want to send the notification. If our students use a university mobile app, we can send a mobile notification. Alternatively, we can send an email or an SMS. Here we will use the Twilio service to send an SMS message.
We want to massage the items a bit so that we only send one message per patron, even if multiple items are due. To accomplish that we group by the patron, and then use the async “each” function to send the messages in parallel.
if (data.item.length) {
  data.item = data.item.groupBy(function(o) {return JSON.stringify({a: o.primaryId});});
  async.each(data.item, function(item, callback) {
    var msg = formatMsg(item.key.firstName, item.group);
    sendSms(item.key.sms, msg, callback); 
  }, next); 
} else {
  var msg = formatMsg(data.item.firstName, new Array(data.item));
  sendSms(data.item.sms, msg, next);
}

The Twilio API itself is very simple to use:

function sendSms(to, msg, callback) {
  console.log("Sending to " + to + ": " + msg);
  client.sms.messages.create({
    to: to,
    from: twilio_number,
    body: msg 
  }, callback);
}

After we call the API we see the SMS message has arrived:

Deploy and Schedule the Lambda Script

Now that we have the script running, we want to deploy it to Lambda and schedule it to run daily.

Deployment is very simple using the AWS Console. We create a zip file which includes the scripts and dependent node modules. Then we define the Lambda function, specify the language and entry point, and upload the zip file.

Once it’s deployed, we want to schedule it to run daily. Lambda supports cron scheduling of functions, so all we need to do is create an Event Source and specify the timing.

Wrap Up

Now our Lambda function will run every day and we’re providing better service to our patrons, without creating any new infrastructure in our institution. The code for the Lambda function is available in this Github repository. Good luck!

Github

Leave a Reply