The Simple Notification Service (SNS) is a scalable, queryable, realtime notification micro service that is designed to provide the realtime infrastructure to allow you to integrate realtime notifications, events and sharing of data within your existing apps.
- Users have descriptive properties, allowing for targeted routing of notifications
- Send targeted notifications using our simple query model
- Use the same query model to detect other users, regardless of whether they are already connected, just connecting, or disconnecting
- Retrieve old notifications via the REST API
The SNS is built with Node.JS and RethinkDB in order to be highly scalable.
EventEmitter for the browser is also used to help handle events on the client side.
You can deploy this service directly to IBM Bluemix by clicking the button below.
Note: This will provision a RethinkDB instance within Bluemix which may incur costs, please see here for more information
You will need Node 4.4.x
or higher and a running instance of RethinkDB. You can download and run RethinkDB locally if you wish - or you can spin up a managed cluster at Compose for free, for 30 days.
Clone this repository and do the standard npm install
to get all of the depndencies.
By default, SNS will assume a local instance of RethinkDB is running, but you can use environment variables to define where a remote instance of RethinkDB is running if you wish.
export RETHINKDB_URL='rethinkdb://username:[email protected]:28015'
If your RethinkDB instance requires an SSL Certificate in order to get access (for instance, if you are using a Compose instance), then you will need to specify the location of your certificate via another environment variable like so:
export RETHINKDB_CERT='/path/to/my/cert'
To run the SNS app, simply do npm start
. On first run of the app, all necessary DB tables will be created.
You can install SNS and run it from your own Node.js application by installing the module:
npm install --save simple-notification-service
And then "require" it into your app:
const sns = require('simple-notification-service')()
It will pick up any environment variables for configuration as mentioned above, and you can provide some other options as shown below:
const path = require('path');
const router = require('express').Router();
router.get('/my/route', function(req, res) {
res.send({ foo: "bar" })
})
var opts = {
production: true,
static: path.join(__dirname, './public'),
authentication: [
{ hostname: 'localhost', key: 'my-api-key' }
],
router: router
}
const sns = require('simple-notification-service')(opts);
production
- when set to true, disables all of the SNS demo apps (defaultfalse
)static
- provide a static directory for Express (defaultnull
- this will put out the SNS admin)authentication
- an array ofhostname
/key
pairs to create API keys to allow SNS access (default is empty array)router
- custom Express routes for your application (default no custom routes)
Finally, once the service is running, you will need to include the client library into your HTML. You can do so very easily as so, making sure you change the hostname to match your particular instance of the SNS app:
<script src="http://sns-hostname.com/sns-client.js"></script>
And now your app is SNS enabled! Keep on reading to find out how to use the SNS in your app.
To connect to the SNS you will need an authentication key. For the JavaScript API these keys are tied to specific hostnames.
To enable the SNS demos to work you will need to create an authentication key for the hostname that is associated with your instance of the SNS. You can do this via the /admin
page.
Create a new key where hostname is the hostname of your SNS instance (e.g. localhost
) and the key is demokey
. To check whether this is working or not, visit the /status
endpoint - if there is at least 1 user connected, everything is working!
You can create and remove as many keys as you wish on this page.
When connecting to the SNS, you should supply serveral different pieces of information:
- An authentication key
- Some
userData
- A
userQuery
Your authentication key is tied to a particular hostname, and must be created as described above. You only need to provide the key when connecting.
userData
and userQuery
are provided as part of an options object.
userData
is a JSON object that describes this user (ie. the user that is connecting). This JSON object should only contain simple key/value pairs on one level (i.e. no nested objects, no arrays). This userData
is what other users of the SNS will query against to send notifications to this user.
userQuery
is also a JSON object (again, only simple key/value pairs), and is used to determine what other users we care about. We will then receive connection and disconnection events for any other user that matches this userQuery
.
Connect to SNS, and define your userData
and userQuery
like so:
var SNS = new SNSClient("your-authentication-key", {
userData: {
name: "Matt",
age: 32,
country: "USA",
user_type: "chat"
},
userQuery: {
country: "USA",
user_type: "chat"
}
});
Here we have defined this user with the following attributes:
- name = Matt
- age = 32
- country = USA
- user_type = chat
And we have asked to be informed about the connection/disconnections of any other users where:
- country = USA
- user_type = chat
note: a user must have ALL of the attributes defined in the
userQuery
in order to match, however it is not required that a user matches EXACTLY, and can have attributes defined that are not in theuserQuery
The userQuery
is used to identify recipients of the notification.
The below example will send a JSON object with a chat_msg
property to any connected user who has a user_type
of chat
.
SNS.send( { user_type: "chat" }, { chat_msg: "Hello, world!" } )
The userQuery
used to send a notification can be different to the userQuery
defined at connection time.
Once connected there are a number of events that can be triggered and acted upon.
The connected event is very simple, and just alerts the user to the fact they have successfully connected to the SNS.
SNS.on('connected', function() {
console.log("connected event")
})
On connection, the supplied userQuery
is used to find any other currently connected users that this user is interested in (i.e. Match the userQuery
). This will trigger the currentUsers
event.
SNS.on('currentUsers', function(users) {
console.log("currentUsers event", users)
})
An array of users is passed along with this event, where each element of the array is a JSON object containing the userData
of each matched user.
When a new user connects that matches the supplied userQuery
, it will trigger the connectedUser
event.
SNS.on('connectedUser', function(user) {
console.log("connectedUser event", user)
})
A JSON object containing the userData
of the connecting user is passed in the user
parameter.
When a new user disconnects that matches the supplied userQuery
, it will trigger the disconnectedUser
event.
SNS.on('disconnectedUser', function(user) {
console.log("disconnectedUser event", user)
})
A JSON object containing the userData
of the disconnecting user is passed in the user
parameter.
When a new notification is received, it will trigger the notification
event.
SNS.on('notification', function(notification) {
console.log("notification event", notification)
})
The notification
parameter will contain the notification information.
The SNS also provides a simple HTTP API for some operations.
Notifications can also be sent by using the POST /authentication-key/notification
HTTP endpoint, where authentication-key
is your authentication key. For making HTTP requests, this key is not tied to a hostname.
Requests to the POST /authentication-key/notification
require that a JSON body is sent as shown below:
curl -H "Content-Type: application/json" -X POST -d '{ "notification": { ... }, "userQuery": { ... } }' /authentication-key/notification
And the response would look something like:
{
"success": true
}
Historical notifications can be retrieved by using the GET /authentication-key/historical
HTTP endpoint, where authentication-key
is your authentication key. For making HTTP requests, this key is not tied to a hostname.
Requests to the GET /authentication-key/historical
endpoint will parse the query string to create a userQuery
. For example, the following request will return historical notifications where the userQuery
for this notification contains user_type: chat
.
curl /authentication-key/historical?user_type=chat
And the response would look something like:
{
"success": true,
"notifications": [
{
"msg": "Hello, Dave!",
"name": "Matt"
},
{
"msg": "Hello, world",
"name": "Dave"
}
]
}
The Simple Notification Service comes with two demos built in, accessible from the homepage.
The first demo is a chat room. This demo showcases all of the features of the SNS - send/receive messages, detect and handle connections/disconnections, and using historical data to preserve chat history.
There is also a copy & paste widget to add chat to any website.
The second demo showcases the ability of the SNS to direct notifications to specific users.
Here you can use an adin panel to update the scores of two soccer matches. End users will either see all updates, or match specific updates, depending on the page they are visiting.
The projected is released under the Apache-2.0 license so forks, issues and pull requests are very welcome.
Sample web applications that include this package may be configured to track deployments to IBM Bluemix and other Cloud Foundry platforms. The following information is sent to a Deployment Tracker service on each deployment:
- Node.js package version
- Node.js repository URL
- Application Name (application_name)
- Space ID (space_id)
- Application Version (application_version)
- Application URIs (application_uris)
- Labels of bound services
- Number of instances for each bound service and associated plan information
This data is collected from the package.json file in the sample application and the VCAP_APPLICATION and VCAP_SERVICES environment variables in IBM Bluemix and other Cloud Foundry platforms. This data is used by IBM to track metrics around deployments of sample applications to IBM Bluemix to measure the usefulness of our examples, so that we can continuously improve the content we offer to you. Only deployments of sample applications that include code to ping the Deployment Tracker service will be tracked.
To disable deployment tracking, please remove or comment out the following line from app.js
:
require("cf-deployment-tracker-client").track();