SocketCluster / SocketCluster/socketcluster

How to organize large numbers of event handlers

Open
#470 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
6.2k
Forks
318
PR merge metrics
No merged PRs in 30d

Description

When you start handling many different types of events, the code in worker.js can get a little unwieldy:

scServer.on('connection', socket => {
    socket.on('foo1', (data, res) => { ... });
    socket.on('foo2', (data, res) => { ... });
    socket.on('foo3', (data, res) => { ... });
    socket.on('bar1', (data, res) => { ... });
    socket.on('bar2', (data, res) => { ... });
    ...
});

Is there a recommended/built-in way to split these handlers into their own modules?

If not, it would be nice to add a module that does something like express.Router does for Express routes. For example:

// foo-handlers.js
const eventManager = require('socketcluster/event-manager');

eventManager.on('foo1', (data, res) => { ... });
eventManager.on('foo2', (data, res) => { ... });
eventManager.on('foo3', (data, res) => { ... });

module.exports = eventManager;

// bar-handlers.js
const eventManager = require('socketcluster/event-manager');

eventManager.on('bar1', (data, res) => { ... });
eventManager.on('bar2', (data, res) => { ... });

module.exports = eventManager;

// worker.js
const foo = require('./foo-handlers'),
    bar = require('./bar-handlers');

scServer.on('connection', socket => {
    socket.register(foo);
    socket.register(bar);
});

I hacked together a rough attempt at this:

class SCEventManager {
    constructor() {
        this.handlers = {};
    }

    on(eventName, callback) {
        this.handlers[eventName] = callback;
    }

    register(socket) {
        Object.keys(this.handlers).forEach(eventName => {
            socket.on(eventName, this.handlers[eventName]);
        });
    }
}

module.exports = () => new SCEventManager();

But you have to call foo.register(socket) instead of socket.register(foo):

// foo-handlers.js
const eventManager = require('sc-event-manager')();

eventManager.on('foo1', (data, res) => { ... });
eventManager.on('foo2', (data, res) => { ... });
eventManager.on('foo3', (data, res) => { ... });

module.exports = eventManager;

// worker.js

const foo = require('./foo-handlers');

scServer.on('connection', socket => {
    foo.register(socket);
});

There are probably other issues with this design; it would be nice if there were something integrated with Socketcluster that did this. Also, express.Router provides other neat features like per-module routing prefixes and middleware that might be useful in such a feature.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the event registration flow in worker.js, including scServer.on('connection') and socket.on handlers. Compare the proposed event-manager and socket.register designs, then determine the required API, prefixes, and middleware behavior. Done would require an agreed design and implementation scope; the issue does not define tests or acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.