News

Functions: Serverless Computation at Scale

Michael Carroll on Sep 12, 2016
Functions: Serverless Computation at Scale

We’re excited to announce Functions, a better way to do serverless computing at scale with real-time data. Now you can program the data network itself to do your bidding, compute real-time data, combine multiple webservices into a single workflow, and conjure a gelatinous cube with only spoony bard. Okay, we might have made that last part up.

But suppose you want to build a chat app for junior high students with a profanity filter? Conceptually this is simple to build. It’s just an if statement: if the message contains any of a list of words, send it back to the student. However, making this scale requires sending the message from the network back to your server, performing the simple computation, then sending it back. This adds latency and load to your server, for what should be a simple solution. Your server doesn’t even really want the messages, but it’s the only way to perform computation on data in motion. Until now.

Serverless Computation at Scale

PubNub has always had a Data Stream Network (DSN). It’s like a CDN, but for data in motion. Up until now the DSN could route that data in motion quickly and reliably, but not change the data in any way. That means you can’t edit contents or perform any computation. If you want to alter a message you’d have to take it out of the DSN to your owner server, perform the computation, then send back to the DSN and eventually out to the end user.

This roundabout method of real-time computing not only adds tremendous latency, but it also introduces a new single point of failure and completely destroys user locality. No matter where the data comes from, it has to go to a single server in a single location. If that server goes down, or is simply far away from the user, then the user experience massively suffers. No more. Now we have Functions.

Scaling computation is hard. Really hard. And annoying. The problem you want to solve is making a good looking voting app, not distributed synchronization and computation. Functions makes the problem simple again. With just a few lines of JavaScript running in the PubNub network, you can count the votes with our distributed datastore and give every user real-time feedback. Functions lets you stop worrying about infrastructure. Every second you spend on infrastructure is a second you can't spend on what your app really does.

How Functions Works

The way you use Functions is pretty simple. Create an event handler in plain JavaScript and put it inside of a block from the PubNub dashboard. Your handler code could log the message to a database, or update the message with missing values. You could calculate voting totals in real time, or track temperature data averages across thousands of temperature sensors. You can call external REST webservices or use the built in key-value store. The contents of the event handler are entirely up to you.

Next press the Save button then the Start block button. Now the event handler will be triggered whenever a message is sent to one of your data channels. Your block code will be run in every part of the network at once with no extra configuration required.

With Functions you don’t need your own servers. No rebooting and managing servers. No downtime. Just simple business logic running at scale. As we like to say: Functions just works.

Functions

Getting Started

Getting started is easy. Just log into your free PubNub account, create a new app with a keyset, go to the Keyset Configuration screen via the admin portal, then enable Functions from the Application add-ons feature section

Enable Functions

Now go to the Functions page by clicking on the Functions icon in the sidebar, and create a new block with a name and short description. The block's name and description can always be changed.

Create a New Block

Functions code is simple promise-based JavaScript. Below is a distributed real-time voting system using just a few lines of code with the built in key value datastore. It also filters votes to allow only one IP address per vote. See the full code in the Vote Counter template.

// extract poll id from message
var pollId = request.message.poll_id;
// channel on which to publish result
var resultChannel = pollId + '-result';
// get polls db from state
return store.get('polls_db').then(function (pollsDB) {
    pollsDB = pollsDB || {};
    // get poll data for specific poll,
    // assign new if does not exist
    var pollData = pollsDB[pollId] || {};
    // init ip data for poll
    var ipData = pollData.ip_data || [];
    // init voting data for this poll
    var votingData = pollData.voting_data || { a:0, b:0, c:0, d:0 };
    // extract client ip address from request
    var clientip = request.meta.clientip;
    // If client IP address is not in ip data, count the vote
    if (ipData.indexOf(clientip) < 0) {
        var voteOption = request.message.vote;
        // discard if voting option is invalid
        if (voteOption in votingData) {
            // update voting data and add ip address to list
            votingData[voteOption] += 1;
            ipData.push(clientip);
            pollData.voting_data = votingData;
            pollData.ip_data = ipData;
            pollsDB[pollId] = pollData;
            // save db to store
            store.set('polls_db', pollsDB);
        }
    }
    // lets publish current result on result channel for for tests
    // this is just to enable mocha tests to know current status
    pubnub.publish({
        channel: resultChannel,
        message: votingData
    });
    return request.ok();
});

Functions keeps your computations secure, reliable, and incredibly low latency. We designed Functions to ‘just work.’ The docs team has created a great set of tutorials to help you get started.

Functions is an amazing new way to build applications with the PubNub Data Stream Network. We are so excited to see what you make! Get started now.