Functions Development Guidelines
Functions modules and API
For more information about the available Functions modules or the public REST API (for Functions v2) you can work with directly, check out the Functions Modules or REST 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 modules 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()
. The 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 called json()
, and the 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 called 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 for 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 Promise.all()
for parallel execution of multiple asynchronous Functions.
Take the following example where we fetch a username 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 be executed.
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 linesModules
You can use modules with your Functions to optimize their performance and provide specialized functionality for specific tasks. This allows each Function to be more efficient and tailored to the particular event it handles.
For the full list of modules supported by PubNub Functions, refer to Functions modules.
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.
-
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.
show all 18 linesexport 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'); -
Save the changes and, depending on the Functions version you use (v1 or v2), either restart the module
or confirm creating a new PackageModule
A collection of Functions (v1) used to manage and control a set of Functions.Revision and deploy it.Package
A collection of Functions (v2) used to manage and control a set of Functions.
We're done! You can now test the Function.
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 use pubnub.publish()
, but the same is applicable to the other two methods.
Modules/Packages for chained Functions
It's recommended that Functions that you would like to chain with each other are in the same Module/Package, 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 the hello-world
channel, and send it to your hello-logger
Function.
-
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
}; -
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
}; -
Save the changes and, depending on the Functions version you use (v1 or v2), either restart the Module or confirm creating a new Package Revision and deploy it.
-
Open a debug console tab on your browser to PubNub Debug Console.
-
Enter
hello_world
,hello-logger
for the channel in the debug console. -
Click Subscribe.
-
Back on the Functions screen, publish the test payload.
Fork Functions
Let's take an example where you want to capture a publish messages sent on hello-world
, edit the message to include "Hello": "World"
and send the newer message to the hello-universe
channel along with the original hello-world
channel.
-
Create a new Before Publish or Fire Function:
show all 31 linesexport 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(); -
Save the changes and, depending on the version of Functions you use (v1 or v2), either restart the Module or confirm creating a new Package Revision and deploy it.
-
Open a debug console tab on your browser to PubNub Debug Console.
-
Enter
hello-world
,hello-universe
for the channel in the debug console. -
Click Subscribe.
-
Back on the Functions screen, publish 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, check that your logic 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
Method | Arguments | Description |
---|---|---|
ok | message:String (Optional) | Returns a promise that resolves to the value of the request object. |
abort | message:String (Optional) | Returns a promise that resolves to the value of the request object, with an error code. |
request
Attributes
Attribute | Type | Definition |
---|---|---|
message | Object | The actual user message sent to the channel. |
verb | String | Method used by the publishing client when sending the message to PubNub. |
pubkey | String | The Publish Key used when sending the message. |
subkey | String | The Subscribe Key to retrieve the message. |
channels | Array<String> | The list of channels on which the message was sent on. |
version | String | API Version. |
meta.clientip | String | IP of the publishing client. |
meta.origin | String | Origin defined on the publishing client. |
meta.useragent | String | The Publishing client's useragent string. |
params | Object | URL Parameters made on the request. |
uri | String | The URI of the request. |
On Request Inputs/Outputs
request
Attributes
Attribute | Type | Definition |
---|---|---|
verb | String | Method used by the publishing client when sending the message to PubNub. Always set to rest . |
pubkey | String | The Publish Key used when sending the message. |
subkey | String | The Subscribe Key to retrieve the message. |
version | String | API Version. |
meta.clientip | String | IP of the publishing client. |
meta.origin | String | Origin defined on the publishing client. |
meta.useragent | String | The Publishing client's useragent string. |
params | Object | URL Parameters made on the request. |
uri | String | The full path of the URI of the request minus PubNub hostname information. |
path | String | The path minus PubNub and key specific information. This is the path configured, by you, for the Function itself. |
method | String | The HTTP method of the request, such as GET, PUT, POST, DELETE. |
body | Object | The body content if passed in the request. |
headers | Object | The header information passed in the request. |
response
Methods
Method | Arguments | Description |
---|---|---|
send | body:String (Optional) | Returns a promise that resolves to the value of the response object. |
response
Attributes
Attribute | Type | Definition |
---|---|---|
status | Object | The HTTP status code to use when returning the response to the calling application or user. |
body | Object | The body content returned to the calling application or user. |
headers | Object | Header information returned to the calling application or user. |
On Interval Inputs/Outputs
event
Methods
Method | Arguments | Description |
---|---|---|
ok | N/A | Returns a promise that resolves to the value of the response object. |
event
Attributes
Attribute | Type | Definition |
---|---|---|
verb | String | Method used by the publishing client when sending the message to PubNub. Always set to interval . |
pubkey | String | The Publish Key used when sending the message. |
subkey | String | The Subscribe Key to retrieve the message. |
execInterval | Number | Duration of the interval specified for the Function, in milliseconds. |
lastTimestamp | Number | Timestamp of last Function execution. |
timestamp | Number | Timestamp of current Function execution. |
Subscribe On Interval Inputs/Outputs
event
Methods
Method | Arguments | Description |
---|---|---|
ok | N/A | Returns a promise that resolves to the value of the response object. |
event
Attributes
Attribute | Type | Definition |
---|---|---|
verb | String | Method used by the publishing client when sending the message to PubNub. Always set to interval . |
pubkey | String | The Publish Key used when sending the message. |
subkey | String | The Subscribe Key to retrieve the message. |
execInterval | Number | Duration of the interval specified for the Function, in milliseconds. |
lastTimestamp | Number | Timestamp of last Function execution. |
timestamp | Number | Timestamp of current Function execution. |
Create a Function
This short instruction shows how to create a simple Function on the Admin Portal. This Function changes the content of the message before publishing it on the previously specified channel.
Admin Portal UI
This section shows how to use Admin Portal to create PubNub Functions. To familiarize yourself with the UI for Functions, go to the Functions v2 section of the Admin Portal documentation.
Set up configuration
You'll need to create a PackagePackage
A collection of Functions (v2) used to manage and control a set of Functions.
-
Log into the Admin Portal and go to the Functions v2 section.
-
Create a Package.
Click Create package. Choose to Configure your own Package and fill in the Package name and description. Confirm the changes by clicking Next.
-
Create a Function.
Add a Function name and select the Before Publish or Fire event type. Configure the Function to trigger on a channel by specifying a channel name as
hello-world
. Confirm the changes by clicking Create package. -
Open the new Package to see the initial Revision that was created for it. To edit the Function's code, either click the Edit code button or Edit Latest on the Package Revision list view.
-
As you can see in the editor, a sample Function is automatically added to the Function's toolbox to help you get started. You can replace the code to include some simple logging and 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
} -
Click Save at the top. As you can see, changing the Function's code generates a new Revision for it. Fill in the Revision name and description and save the changes.
-
To deploy the Package Revision with the Function, click Deploy.
-
Select Add keyset, to point to all the keyset(s) you want the Function to run on. Confirm the changes by clicking Create.
-
Since you're not assigning any secrets for the purpose of this example, just confirm by clicking Deploy again and creating the actual deployment of the Function.
Maximum number of deployments
The number of deployments is equal to the number of keysets you selected for the Package Revision to run on. The maximum number of keysets that a Package Revision can run on is 50.
Run and test
To test the new Function, follow these steps:
- Open the Function's editor either by clicking the Edit code button or Edit Latest on the Package Revision list view.
- Switch to the Debug tab.
- Click the Publish button in the Test payload section to see the Function in action.
Trigger Functions
A Function is triggered on one or more channels (through wildcards), except for the case of an On Request Function, in which triggering occurs through an 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 a Function only occurs when the parent Package Revision (version of a Package with Functions) is running.
Start a Module/Package
You can start a given Package Revision by clicking the start button next to a given Revision on the Package Revision list view.
When the Package Revision starts, each Function in a given Package Revision runs on all the data centers of the PubNub Network until the Package Revision is stopped. To achieve superior performance and the lowest latencies possible, all Functions run hot. This means that they are all ready to process incoming request rather than forcing Functions into a resource-saving mode if they do not receive traffic for some time.
When the Package Revision starts, each Function of the Package Revision runs on all the data centers of the PubNub Network.
Stop a Module/Package
A Package Revision is stopped by clicking the stop button next to a given Revision on the Package Revision list view.
When the Package Revision is stopped, all Functions in the Package Revision 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.