npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

super-scaled-sockets

v0.2.1

Published

WebSockets, on a super scale

Downloads

2

Readme

Super Scaled Sockets

Table of contents

  1. Introduction
  2. Installation
  3. Scaler
  4. Adding to your app
  5. Subscriptions
  6. Ask and Tell
  7. Session Parsing
  8. Subscription Parsing
  9. Resources

What is Super Scaled Sockets?

Super Scaled Sockets allows developers to easily scale up using multiple websocket server instances to serve a high number of clients.

Even if you do not envision a high number of users using your app, it is still recommended that you use multiple instances to serve your clients. This is so that if one of your instances falls over the others can manage the load while the instance is restarted.

What do I need to scale my App?

The server instances are connected by the scalar. At the moment there is only one scaler developed which uses MongoDb and Redis. But this should be easily copied and changed to support different technologies.

How do the server and client communicate?

With Super Scaled sockets, the client has two methods of communication with the server:

  • The Ask & Tell Methods: The client can make ask and tell calls to the server. The server can only make tell calls to clients.
  • Channels: Subscribe and Publish the clients can subscribe to channels and the server can publish on these channels - This will publish to any clients subscribed to the channel on any server instance.

How about load balancing?

This library does not include a load balancer. There are many good solutions for load balancing WebSocket instances. No sticky sessions are required for use with this library. Look into NGINX etc.

What if the client disconnects? Does SSS have reconnection logic?

Yes! Super Scaled Sockets has built in reconnection logic, so if a user disconnects, they will attempt to reconnect and upon them successfully reconnecting the clients subscriptions are parsed and synced.

This library is built on top of the WebSockets node protocol implemented by node-ws.

Getting Started

Installation

Server

On nmp run the following command:

npm install super-scaled-sockets

And install the scaler: (more info below)

npm install sss-mongo-redis

Client

On nmp run the following command:

npm install super-scaled-sockets-client

Scaler

The scaler is a vital part of Super Scaled Sockets and is what connects your different web sockets to each other.

To use super scaled sockets you will require the dependant technologies of the scaler. At the moment the only scaler available is the mongoRedis scaler for which you will need an instance of redis and a a mongDB database instance. RedisLabs and MongoAtlas provide great cloud platforms that are free for development use and are very easy to set up.

MongoDB Atlas: https://www.mongodb.com

RedisLabs: https://redislabs.com/

Once you have set these up just take a note of the connection credentials which will be used to connect your scaler on the server.

And in your server code pass the credentials to the scaler.connect and that will return the scaler object. This should be passed to sss.client to create your client instance.

const sss = require('super-scaled-sockets');
const mongoRedis = require('sss-mongo-redis');

// mongo connection info all properties are required
const mongoConnection = {
  uri: 'mongodb+srv://smartUsername:[email protected]/test?retryWrites=true',
  dbName: 'redis',
  collectionName: 'redis'
};

// redis connection Info all properties are required
const redisConnection = {
  password: 'ABCDefGH1234567890ZYXWvu',
  host: 'redis-123456.z9.us-east-1-0.ec2.cloud.redislabs.com',
  port: 123456
};

mongoRedis.connect(mongoConnection, redisConnection, (err, scaler) => {
  if (err) {
    console.log('Error establishing scaler connection');
    return;
  }
  const client = sss.client(scaler, {})
  client.connect((error) => {
    // ......

Adding to your nodeJs server app

When adding the Super Scaled sockets, you must ensure you have all of the credentials to begin your scaler connection. There are no required options to start your server instance, but you will see in the below example we have passed the port number into the options object which we have got from the cml argument to start the node instance. Depending on your load balancer you may use a different method to define this. By default if undefined in the options the server instance will use port 443 to begin.

import sss from 'super-scaled-sockets';
import mongoRedis from 'sss-mongo-redis';

// We take the port to run our server instance on from the first argument in the node call in cl
const port = process.argv[2];

// mongo connection info all properties are required
const mongoConnection = {
  uri: 'mongodb+srv://smartUsername:[email protected]/test?retryWrites=true',
  dbName: 'redis',
  collectionName: 'redis'
};

// redis connection Info all properties are required
const redisConnection = {
  password: 'ABCDefGH1234567890ZYXWvu',
  host: 'redis-123456.z9.us-east-1-0.ec2.cloud.redislabs.com',
  port: 123456
};

const options = {
  port: port
};

mongoRedis.connect(mongoConnection, redisConnection, (err, scaler) => {
  if (err) {
    console.log('Error establishing scaler connection');
    return;
  }
  // Make a server instance
  const server = sss.server(scaler, options);
  // Open the sss connection
  server.connect((err) => {
    if (err) {
      console.log('Error opening super scaled sockets');
      return;
    }
    // .......

Adding to your client app

To connect your client to your server all you will require is the URL of your server. This will normally be the URL of you Load Balancer. You can provide additional options, please see the docs for more information.

import sssc from 'super-scaled-sockets-client';

const client = sssc.client('localhost:443', {});
client.connect((err) => {
  if (err) {
    console.log('Error opening super scaled sockets');
    return;
  }
  // .......

Subscriptions

Subscriptions are where the true power of super scaled sockets can be utilized. Any server instance can publish on a channel and any socket subscribed to that channel will receive that message. This allows apps to serve a very high number of clients allowing real time communication between them.

Client:

client.subscribe('sport', null, (err, sport) => {
  // The second argument is the query this can be used for passwords etc for secure subscriptions
  if(err) {
    alert('error - unable to connect to sport channel');
    return;
  }
  sport.on('article', (msg) => {
    displayArticle(msg);
  });
});

Server:

const publishSportArticle = (article) => {
  server.publish('sport', 'article', article);
}

Ask & Tell Protocols

These act similar to POST and UPDATE http requests. If the client requires information from the server it can call client.ask() and if it just needs to deliver information to the server it can call client.tell().

Ask

Client:

client.ask('serverTime', null, (err, response) => {
  if (!err) displayTime(response);
});

Server:

socket.onAsk('serverTime', (msg, response) => {
  response.send(Date.now());
});

Tell (Client)

Client:

const likeMessage = (messageId) => {
  client.tell('likedMsg', messageId, (err) => {
    if (!err) showThumbsUp(messageId);
  });
}

Server:

socket.onTell('likedMsg', (msg) => {
  handleLikedMessage(msg);
});

Session Parser

The session parser allows you to add a security layer to your server and is called when any new client tries to make a connection. You can check cookies and origins in this function etc. You can also use this function to add a user id and/or a session ID so that SSS can make session and user subscriptions. Your session parser should be passed to the server object as in the example below. If a Session Parser is not set then all sessions are accepted and no user or session subscriptions are created.

const sessionParser = (request, done) => {
    const token = request.cookies.token;
    mongoSessions.validateToken(token, (__err, result) => {
      done(result.isValid, result.user, token);
    });
  }
const options = {
  sessionParser
  port: port
};
const server = sss.server(scaler, options);
server.connect((err) => {
  // .....

Subscription Parser

The Subscription Parser is called when a client makes a subscription request allowing you to add security to subscriptions. You can pass a query in the client request if information is needed from the client to parse the request (ex: password). If a Subscription Parser is not set then all subscription requests are accepted.

// Array of roomKeys
const roomKeys = ['Sport', 'Politics', 'Fashion'];
// Password for the private room
const privateRoomPw = '21sdf24dgFD1fd2df2';
// The subscription Parser function
const subscriptionParser = (socket, channelName, request, done) => {
  if (channelName === 'private') {
    done(privateRoomPw === request);
    return;
  }
  // returns false if the room ket is unknown
  done(roomKeys.includes(channelName));
};
// Include Subscription Parser in your options
const options = {subscriptionParser, port};
const server = sss.server(scaler, options);
server.connect((err) => {
  // .....

Resources