Functions Development Guidelines

Functions API

For more information about the Funtions API, check out the Functions API documentation.

Introduction

  • PubNub provides integrations with popular services through the Integration Catalog.
  • Functions are implemented as a JavaScript module with a default export function. Go to guidelines to find out how to write code for each event type.
  • PubNub provides libraries to assist in your Functions development.
  • Asynchronous operations in Functions are handled through Promises. Refer to Promises.
  • You can chain up to 5 functions to execute consecutively. Refer to Chaining Functions.

Development Guidelines

Code Structure

All Event Types except the On Request should have the following structure:

export default (request) => {
// Your business logic here
return request.ok();
// request.abort(); to fail execution
};

For all Event Types except On Request and On Interval, the request object has two methods ok() and abort(). response object isn't available. For detailed attributes refer to On Request and On Interval.

On Request

The On Request function should have the following structure:

export default (request, response) => {
// Your code here
return response.send();
};

For the On Request event type, the request object has only one method json(), a response object only has send(). For detailed attributes refer to On Request.

On Interval

The On Interval function should have the following structure:

export default (event) => {
// Your code here
return event.ok();
};

For the On Interval event type, the event object has only one method ok(). For detailed attributes refer to On Interval Inputs/Outputs.

Promises

Asynchronous operations in Functions are handled via Promises based on ES6 Promise standards. promise is implicitly available to every Function.

const Promise = require('promise'); // No need to add this line
Learn more

Learn more about Promise and Promise.all()

Promise.all()

You can leverage the Promise.all() for parallel execution of multiple asynchronous functions.

Take the following example where we fetch a user name from the KV Store and fetch an IP address for that user from an external web service. When both are available (and not before), the logic to update the request object will execute.

export default (request) => {
const store = require('kvstore');
const xhr = require("xhr");

const fullName = store.get('fullName');
const ipAddress = xhr.fetch("https://httpbin.org/ip");

return Promise.all([fullName, ipAddress])
.then((values) => {

request.message.fullNameResult = values[0];
request.message.ip = JSON.parse(values[1].body).origin;

return request.ok();
})
show all 20 lines

Libraries

The Functions runtime provides custom built-in libraries to support functionality not found natively as part of the JavaScript language.

Functions API

For more information about the Funtions API, check out the Functions API documentation.

A library can be imported using the require() method.

const xhr = require(xhr); // Example of importing a library

The following libraries are available in Functions:

Library NameDescription
XHRThe XHR library is used to enable the developer to send HTTP or HTTPS requests to a remote web server and load the response data back into a Function. This library is perfect for third-party authentication or triggering webhooks from a Function.
KV StoreThis library allows access to the KV store. It's a persistent key value store that acts as a database for your Functions. The KV store database is globally distributed and eventually consistent. Data in the KV store is shared at a subscribe key level.
Advanced MathGlobal (lat-long) coordinate and geometry functions.
CryptoThe Crypto library provides encryption and decryption functionality in an Function.
UtilsSimple utility functions that didn't belong anywhere else.
Codec/authProvides an encoder for HTTP basic auth credentials.
Codec/base64Provides an encoder and decoder for Base64 strings.
Codec/query_stringProvides an encoder and decoder for URI query parameters.
PubNubThe PubNub library allows you to leverage many of the client SDK features supported by the PubNub Platform.
vaultRead-only database to retrieve secrets.
Features not yet available in Functions

Some JavaScript features that you may expect to see, but aren't yet available in Functions:

  • Native node modules
  • async/await
  • Access to process and some other global variables
  • Ability to install third-party modules via npm

Webhooks On Request

You can use an on Request event type to create webhooks.

Let's take an example to learn how On Request can be used to create webhooks. Let's say that you want to check whether the given username already exists in the database or not. For this, let's assume that a username is passed as a query parameter to the webhook.

  1. The following code shows how you can extract the passed username from the query parameter and checks whether it already exists in the database or not.

    export default (request, response) => {

    const db = require('kvstore');
    const username = request.params.username;

    return db.get(username).then((dataFromDb) => {
    if (!dataFromDb) {
    console.log('The username does not exist.');
    db.set(username, {});
    response.status = 200;
    return response.send('Username is available');
    } else {
    console.log('The username already exists.');
    response.status = 409;
    return response.send('Username already exists');
    show all 18 lines
  2. Click Save.

  3. Click Restart Module.

We're done! You can test the function from the HTTP client on the left side.

Chaining

Functions can be linked to execute in sequential way or depending on a specific condition. It's done using the pubnub.publish(), pubnub.signal() or the pubnub.triggerRequestFunction() methods. In the below examples, we have used pubnub.publish() but the same is applicable to the other two methods.

Modules for chained functions

It's recommended that functions that you would like to chain with each other are in the same Module, so it's easier to start/stop their execution.

Chain Functions

Let's take an example, you want to capture a publish messages sent on hello-world, and send it to your hello-logger function.

  1. Create an On Before Publish or Fire "hello-logger" function:

    export default (request) => {
    console.log(request) // show what we have inside
    return request.ok() // done
    };
  2. Create an On Before Publish or Fire hello-world function

    export default (request) => {
    const pubnub = require('pubnub');

    pubnub.publish({
    "channel": "hello-logger",
    "message":request.message
    }).then((publishResponse) => {
    console.log(`Publish Status: ${publishResponse[0]}:${publishResponse[1]} with TT ${publishResponse[2]}`);
    }).catch((err) => {
    console.error(err);
    });

    return request.ok(); // Return a promise when you're done
    };
  3. Click Save.

  4. Click Restart Module.

  5. Open a debug console tab on your browser to PubNub Debug Console.

  6. Enter hello_world, hello-logger for the channel in the debug console.

  7. Click Subscribe.

  8. Back on the Functions screen, click Publish on the test payload.

Fork Functions

Let's take an example, you want to capture a publish messages sent on hello-world, edit the message to include "Hello": "World" and would like to send the newer message to hello-universe channel along with the original hello-world channel.

  1. Create a new Before Publish or Fire Function with:

    export default (request) => {
    const db = require('kvstore');
       const pubnub = require('pubnub');

       console.log('The message ', request.message, ' was published on ', request.channels[0], ' via ', request.meta.clientip);

       request.message.hello = 'world!'; // augment hello = world

    // To fork return pubnub.publish and include request.ok in the .then()
    return pubnub.publish({
        "channel": "hello_universe",
           "message": request.message
       }).then((publishResponse) => {
    console.log(`Publish Status: ${publishResponse[0]}:${publishResponse[1]} with TT ${publishResponse[2]}`);
        return request.ok();
    show all 31 lines
  2. Click Save.

  3. Click Restart Module.

  4. Open a debug console tab on your browser to PubNub Debug Console.

  5. Enter hello-world, hello-universe for the channel in the debug console.

  6. Click Subscribe.

  7. Back on the Functions screen, click Publish on the test payload.

Avoid infinite loops: You can chain/fork publishes across as many channels as you wish, however it's important not to create a scenario where an infinite loop is possible (for example, publishing to A, which publishes to B, which Publishes back to A.) The system is designed to detect and not allow infinite loops to happen, however, it's important to take care that your logic also doesn't encourage or rely on this behavior.

Recursion limit

The maximum recursion limit you can do is 3 hops from one Function to another: using publish or fire, you can execute a maximum of three Functions.

The combined maximum number within a single Function execution of KV store operations, XHRs, publish and fire is 3.

Request/Response Objects

All Event Types except On Request

request Methods

MethodArgumentsDescription
okmessage:String (Optional)Returns a promise that resolves to the value of the request object.
abortmessage:String (Optional)Returns a promise that resolves to the value of the request object, with an error code.

request Attributes

AttributeTypeDefinition
messageObjectThe actual user message sent to the channel.
verbStringMethod used by the publishing client when sending the message to PubNub.
pubkeyStringThe Publish Key used when sending the message.
subkeyStringThe Subscribe Key to retrieve the message.
channelsArray<String>The list of channels on which the message was sent on.
versionStringAPI Version.
meta.clientipStringIP of the publishing client.
meta.originStringOrigin defined on the publishing client.
meta.useragentStringThe Publishing client's useragent string.
paramsObjectURL Parameters made on the request.
uriStringThe URI of the request.

On Request Inputs/Outputs

request Attributes

AttributeTypeDefinition
verbStringMethod used by the publishing client when sending the message to PubNub. Always set to rest.
pubkeyStringThe Publish Key used when sending the message.
subkeyStringThe Subscribe Key to retrieve the message.
versionStringAPI Version.
meta.clientipStringIP of the publishing client.
meta.originStringOrigin defined on the publishing client.
meta.useragentStringThe Publishing client's useragent string.
paramsObjectURL Parameters made on the request.
uriStringThe full path of the URI of the request minus PubNub hostname information.
pathStringThe path minus PubNub and key specific information. This is the path configured, by you, for the Function itself.
methodStringThe HTTP method of the request, such as GET, PUT, POST, DELETE.
bodyObjectThe body content if passed in the request.
headersObjectThe header information passed in the request.

response Methods

MethodArgumentsDescription
sendbody:String (Optional)Returns a promise that resolves to the value of the response object.
response Attributes
AttributeTypeDefinition
statusObjectThe HTTP status code to use when returning the response to the calling application or user.
bodyObjectThe body content returned to the calling application or user.
headersObjectHeader information returned to the calling application or user.

On Interval Inputs/Outputs

event Methods

MethodArgumentsDescription
okN/AReturns a promise that resolves to the value of the response object.

event Attributes

AttributeTypeDefinition
verbStringMethod used by the publishing client when sending the message to PubNub. Always set to interval.
pubkeyStringThe Publish Key used when sending the message.
subkeyStringThe Subscribe Key to retrieve the message.
execIntervalNumberDuration of the interval specified for the function, in milliseconds.
lastTimestampNumberTimestamp of last function execution.
timestampNumberTimestamp of current function execution.

Subscribe On Interval Inputs/Outputs

event Methods

MethodArgumentsDescription
okN/AReturns a promise that resolves to the value of the response object.

event Attributes

AttributeTypeDefinition
verbStringMethod used by the publishing client when sending the message to PubNub. Always set to interval.
pubkeyStringThe Publish Key used when sending the message.
subkeyStringThe Subscribe Key to retrieve the message.
execIntervalNumberDuration of the interval specified for the function, in milliseconds.
lastTimestampNumberTimestamp of last function execution.
timestampNumberTimestamp of current function execution.

Create a Function

Follow these instructions to create a function.

Hello World

You'll need to create a module before you can create a function. A module is a collection of Functions. Modules are useful to start and stop a set of functions together.

  1. Go to the Functions page -> Create Module -> Create Function -> select the Before Publish function event type. Different event types are listed in Event Types.

  2. Configure the function to trigger on a channel by specifying a channel name, 'hello-world'. Then Save.

  3. A sample function will be automatically added to get you started. You can update the code to include some simple logging to see how it works.

    export default (request) => {

    console.log('request', request);
    request.message.hello = 'world!'; // augment hello = world
    console.log('The message: ', request.message, ' was published on ', request.channels[0], ' via', request.meta.clientip);

    return request.ok(); // Return a promise when you're done
    }
  4. Click Save Function on the left panel.

Run & Test

  1. Start the Module.
  2. Click on the Publish button of the Test payload to see it in action.

Trigger Functions

A Function is triggered on one or more channels, except for the case of an OnRequest Function, in which triggering occurs through a HTTP API request. Clients that are publishing and subscribing to a channel have no awareness of which (if any) Functions are configured against the messages they send and receive. Execution of Function only occurs when the parent Module is running.

Starting a Module

You can start a Module by clicking on the Start Module button at the top right of the Functions screen.

When you click the Start Module button, the latest saved version of each Function in the Module is scheduled to start. This should occur within several seconds. To ensure you're running the latest version of your code, click the Save button before you start a Module.

When the Module starts, each Function of the Module runs on all the data centers of the PubNub Network until the Module is stopped. To achieve superior performance and the lowest latencies possible, all functions run hot.

When the Module starts, each Function of the Module runs on all the data centers of the PubNub Network.

Stopping a Module

A Module is stopped by clicking the Stop Module button displayed at the top right of the Functions screen.

When the Module is stopped, all Functions in the Module are stopped. Messages will pass through the PubNub network without triggering your saved Functions. Web API calls made to On Request Functions will result in a 404 Not Found error.

Module States

Below is the list of states that the Module can be in:

StateDefinition
StoppedNone of the Functions in the Module are running. Messages will pass through the PubNub network without triggering your saved Functions.
RunningAll Functions in the Module are running and operational.
PendingThe Functions in the Module are being started. This is a transient state, and the Module may remain in this state for up to 20 seconds.
StoppingThe Module is being stopped. Like the Pending state, this is a transient state, and the Module may remain in the Stopping state for few seconds.
FailedOne or more Functions in the Module failed to run because of an error, and all functions are stopped. Check the logs for more information.
Last updated on