uNetworking / uWebSockets.js

μWebSockets for Node.js back-ends :metal:
Apache License 2.0
7.76k stars 563 forks source link

PubSub.js example not working with 20.31.0 on node version v20.2.0 #948

Closed lockenj closed 1 year ago

lockenj commented 1 year ago

Using the example https://github.com/uNetworking/uWebSockets.js/blob/master/examples/PubSub.js with the only modification being requiring uWebSockets.js instead of '../dist/uws.js' I do not receive either of the published events when I send a message from the client.

I used https://websocketking.com/ as my client to rule out anything I was doing on the clientside.

Setting breakpoints on the server it appears the subscribe is working, the subscribe method returns true and in the message handler I added a ws.getTopics() and I see [ 'home/sensors/#' ].

I can easily add my own registration code but based on this discussion https://github.com/uNetworking/uWebSockets.js/discussions/140 that would not be the most performant approach. On a side note I'd love to know what is being done to achieve more performance.

Thanks for your help.

uNetworkingAB commented 1 year ago

That example is very old. Wildcards # does not work anymore

lockenj commented 1 year ago

I tried subscribing to home/sensors and then publishing using home/sensors and same results nothing is sent to the client.

const uWS = require('uWebSockets.js');
const port = 9001;

const app = uWS./*SSL*/App({
    key_file_name: 'misc/key.pem',
    cert_file_name: 'misc/cert.pem',
    passphrase: '1234'
}).ws('/*', {
    /* Options */
    compression: uWS.SHARED_COMPRESSOR,
    maxPayloadLength: 16 * 1024 * 1024,
    idleTimeout: 10,
    maxBackpressure: 1024,

    /* Todo, Setting 1: merge messages in one, or keep them as separate WebSocket frames - mergePublishedMessages */
    /* Todo, Setting 4: send to all including us, or not? That's not a setting really just use ws.publish or global uWS.publish */

    /* Handlers */
    open: (ws) => {
        /* Let this client listen to all sensor topics */
        ws.subscribe('home/sensors');
    },
    message: (ws, message, isBinary) => {
        /* Parse this message according to some application
         * protocol such as JSON [action, topic, message] */

        /* Let's pretend this was a temperature message
         * [pub, home/sensors/temperature, message] */
        ws.publish('home/sensors', message);

        /* Let's also pretend this was a light message
         * [pub, home/sensors/light, message] */
        ws.publish('home/sensors/light', message);

        /* If you have good imagination you can also
         * pretend some message was a subscription
         * like so: [sub, /home/sensors/humidity].
         * I hope you get how any application protocol
         * can be implemented with these helpers. */
    },
    drain: (ws) => {

    },
    close: (ws, code, message) => {
        /* The library guarantees proper unsubscription at close */
    }
}).any('/*', (res, req) => {
    res.end('Nothing to see here!');
}).listen(port, (token) => {
    if (token) {
        console.log('Listening to port ' + port);
    } else {
        console.log('Failed to listen to port ' + port);
    }
});
uNetworkingAB commented 1 year ago

You need 2 clients

e3dio commented 1 year ago

@lockenj app.publish publishes to all, ws.publish publishes to all except self, if you have 1 client you should prob test with app.publish

lockenj commented 1 year ago

@e3dio @uNetworkingAB thanks for the guidance!

If others come across this issue and you are testing with a single ws client you can use the below code:

const uWS = require('uWebSockets.js');
const port = 9001;

const app = uWS./*SSL*/App({
    key_file_name: 'misc/key.pem',
    cert_file_name: 'misc/cert.pem',
    passphrase: '1234'
}).ws('/*', {
    /* Options */
    compression: uWS.SHARED_COMPRESSOR,
    maxPayloadLength: 16 * 1024 * 1024,
    idleTimeout: 10,
    maxBackpressure: 1024,

    /* Todo, Setting 1: merge messages in one, or keep them as separate WebSocket frames - mergePublishedMessages */
    /* Todo, Setting 4: send to all including us, or not? That's not a setting really just use ws.publish or global uWS.publish */

    /* Handlers */
    open: (ws) => {
        /* Let this client listen to all sensor topics */
        ws.subscribe('home/sensors');
    },
    message: (ws, message, isBinary) => {
        /* Parse this message according to some application
         * protocol such as JSON [action, topic, message] */

        /* Will be received by all clients that have registered with this socket server for the topic 'home/sensors' */
        app.publish('home/sensors', message);

        /* This will not be received as it is not an exact match to 'home/sensors' */
        app.publish('home/sensors/light', message);
    },
    drain: (ws) => {

    },
    close: (ws, code, message) => {
        /* The library guarantees proper unsubscription at close */
    }
}).any('/*', (res, req) => {
    res.end('Nothing to see here!');
}).listen(port, (token) => {
    if (token) {
        console.log('Listening to port ' + port);
    } else {
        console.log('Failed to listen to port ' + port);
    }
});