New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.

Already on GitHub?
Sign in
to your account

Closed

mathiask88 opened this issue

Aug 9, 2014

· 21 comments


· Fixed by #160

Comments

@mathiask88

Hey,
I implemented a redis adapter in this way

var socketioPub = m_redis.createClient(null, null, { detect_buffers: true });
socketioPub.on('error', function (err) { ... });
var socketioSub = m_redis.createClient(null, null, { detect_buffers: true });
socketioSub.on('error', function (err) { ... });
io.adapter(m_socketio_redis({ pubClient: socketioPub, subClient: socketioSub }));

So if the redis server e.g. is not running I can handle that error, but I get an unhandled error event from https://github.com/Automattic/socket.io-redis/blob/master/index.js#L73

[...]
  function Redis(nsp){
    Adapter.call(this, nsp);

    var self = this;
    sub.psubscribe(prefix + '#*', function(err){
      if (err) self.emit('error', err); <--------------------------------
    });
    sub.on('pmessage', this.onmessage.bind(this));
  }
[...]

because there is no event listener attached and I see no way to attach one from the outside. Any ideas?

Best regards!

@rauchg

The adapter inherits from Emitter, so simply attach an error listener on the emitter instance.

@yaroshevych

@guille, could you please advise on valid syntax for ‘error’ event. I can’t find any working solution.

@rauchg

Attach it on the adapter instance? On the object you pass to io.adapter

@yaroshevych

Guillermo, thanks for your feedback, unfortunately it doesn’t work with v. 0.1.3. Here is my code:

var redis = require('socket.io-redis');
var redisAdapter = redis({ host: 'abc', port: 12345 });
redisAdapter.on('error', function(err) {});
io.adapter(redisAdapter);

There is no ‘on’ method in redisAdapter object. Here is error:

   redisAdapter.on('error', function(err) {});
                 ^
TypeError: Object function Redis(nsp){
    Adapter.call(this, nsp);

    var self = this;
    sub.psubscribe(prefix + '#*', function(err){
      if (err) self.emit('error', err);
    });
    sub.on('pmessage', this.onmessage.bind(this));
  } has no method 'on'

@mathiask88

Try redisAdapter.prototype.on('error', function(err) {}); that worked for me. But it feels a bit strange to edit the prototype…

@yaroshevych

It’s not working for me. When I kill Redis server, whole app crashes:

events.js:72
        throw er; // Unhandled 'error' event

@peteruithoven

I’m having the same issue, please reopen.
The emit in the psubscribe callback is throwing an error, which can’t be catched in a good way.
https://github.com/Automattic/socket.io-redis/blob/master/index.js#L73
I did add an error event handler:

var adapter = io.adapter(socketIORedis({  key: 'socket.io-redis-experiment',
                            pubClient: pub,
                            subClient: sub}));
adapter.on('error',function(err) {
  debug('adapter error: ',err);
});

@peteruithoven

Adding a error listener on self, just before sub.psubscribe solves the unhandled error…

self.on('error',function(err) {
  console.log("socket.io-redis inside error handler: ",err);
});

Maybe the right instance reference isn’t returned from the require?

@peteruithoven

Putting a listener on adapter.prototype actually works… That’s far from intuitive…
Example:

var adapter = socketIORedis();
adapter.prototype.on('error',function(err) {
  debug('adapter error: ',err);
});
io.adapter(adapter);

@peteruithoven

I think I understand the problem, require('socket.io-redis') returns a “class” and every namespace creates it’s own adapter instance from this.

@emidiocroci

I tried the solution suggested by @peteruithoven but no luck… The error is still thrown causing a crash of the application. Is there some news about this issue?

@peteruithoven

@emidiocroci, did you also try adding error listeners to the pub and sub clients?

@emidiocroci

@peteruithoven

Small example:

io.adapter(initRedisAdapter(config.REDIS_PORT,config.REDIS_HOST));
function initRedisAdapter(port,host) {
  var pub = redis.createClient(port,host,{detect_buffers: true});
  pub.on('error',onRedisError);
  var sub = redis.createClient(port,host,{detect_buffers: true});
  sub.on('error',onRedisError);
  var redisAdapter = RedisAdapter({pubClient: pub,
                            subClient: sub,
                            key: 'your key'});
  redisAdapter.prototype.on('error',onRedisError);
  function onRedisError(err){
    debug("Redis error: ",err);
  }
  return redisAdapter;
}

@nkzawa

You can access to an adapter instance like:

io.of('/').adapter.on('error', funtion(err) {});

@emidiocroci

Thanks @peteruithoven, worked like a charm!
Where did you find those info about redis adapter initialization?

@peteruithoven

Source code of socket.io 😉

@pkuhonker

@nkzawa 3x! You are right. Using radis adapter API also need to add of(namespace)!!!

@pherrymason

io.of('/').adapter.on('error', funtion(err) {}); this didn’t work for me,
only adding the handler to the prototype as @peteruithoven suggesed worked for me

@edevil

Same. Using version 5.2.0 and only catching errors on the pubClient and subClient still caused my app to crash.

Error: connect ECONNREFUSED 127.0.0.1:6379
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)

Adding:

  adapter.prototype.on("error", err => logger.error("PROTOTYPE", { err }));

will prevent the app from crashing:

2018-10-25T10:17:56.307Z error: PROTOTYPE [err: Error: connect ECONNREFUSED 127.0.0.1:6379] [severity: ERROR]
2018-10-25T10:17:56.308Z error: PROTOTYPE [err: Error: connect ECONNREFUSED 127.0.0.1:6379] [severity: ERROR]
2018-10-25T10:17:56.467Z error: PROTOTYPE [err: MaxRetriesPerRequestError: Reached the max retries per request limit (which is 3). Refer to "maxRetriesPerRequest" option for details.] [severity: ERROR]

However, it will not retry forever to establish the Redis connection and will stay zombie.

@salmanahmad94

Same. Using version 5.2.0 and only catching errors on the pubClient and subClient still caused my app to crash.

Error: connect ECONNREFUSED 127.0.0.1:6379
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)

Adding:

  adapter.prototype.on("error", err => logger.error("PROTOTYPE", { err }));

will prevent the app from crashing:

2018-10-25T10:17:56.307Z error: PROTOTYPE [err: Error: connect ECONNREFUSED 127.0.0.1:6379] [severity: ERROR]
2018-10-25T10:17:56.308Z error: PROTOTYPE [err: Error: connect ECONNREFUSED 127.0.0.1:6379] [severity: ERROR]
2018-10-25T10:17:56.467Z error: PROTOTYPE [err: MaxRetriesPerRequestError: Reached the max retries per request limit (which is 3). Refer to "maxRetriesPerRequest" option for details.] [severity: ERROR]

However, it will not retry forever to establish the Redis connection and will stay zombie.

To keep the reconnection protocol, instantiate the redis client separately from the adapter. Implement reconnection protocols on this redis client and let it reconnect. Let adapter.prototype.on catch the error handle even redundantly. That way, you’ll get the best of both worlds.

So i set up a small basic chat system:

Server code:

    var io = require('socket.io').listen(8000);

// open the socket connection
io.sockets.on('connection', function (socket) {

   // listen for the chat even. and will recieve
   // data from the sender.
   socket.on('chat', function (data) {

      // default value of the name of the sender.
      var sender = 'unregistered';

      // get the name of the sender
      var name = socket.nickname;
         console.log('Chat message by ', name);
         console.log('error ', err);
         sender = name;


      // broadcast data recieved from the sender
      // to others who are connected, but not 
      // from the original sender.
      socket.broadcast.emit('chat', {
         msg : data, 
         msgr : sender
      });
   });

   // listen for user registrations
   // then set the socket nickname to 
   socket.on('register', function (name) {

      // make a nickname paramater for this socket
      // and then set its value to the name recieved
      // from the register even above. and then run
      // the function that follows inside it.
      socket.nickname = name;

         // this kind of emit will send to all! :D
         io.sockets.emit('chat', {
            msg : "naay nag apil2! si " + name + '!', 
            msgr : "mr. server"
      });
   });

});

Client side:

<html>
   <head>
      <script src="http://localhost:8000/socket.io/socket.io.js"></script>
      <script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
      <script>
         var name = '';
         var socket = io.connect('http://localhost:8000');

         // at document read (runs only ones).
         $(document).ready(function(){
            // on click of the button (jquery thing)
            // the things inside this clause happen only when 
            // the button is clicked.
            $("button").click(function(){

               // just some simple logging
               $("p#log").html('sent message: ' + $("input#msg").val());

               // send message on inputbox to server
               socket.emit('chat', $("input#msg").val() );

               // the server will recieve the message, 
               // then maybe do some processing, then it will 
               // broadcast it again. however, it will not 
               // send it to the original sender. the sender
               // will be the browser that sends the msg. 
               // other browsers listening to the server will
               // recieve the emitted message. therefore we will
               // need to manually print this msg for the sender.
               $("p#data_recieved").append("<br />\r\n" + name + ': ' + $("input#msg").val());

               // then we empty the text on the input box.
               $("input#msg").val('');
            });

            // ask for the name of the user, ask again if no name.
            while (name == '') {
               name = prompt("What's your name?","");
            }

            // send the name to the server, and the server's 
            // register wait will recieve this.
            socket.emit('register', name );
         });

         // listen for chat event and recieve data
         socket.on('chat', function (data) {

            // print data (jquery thing)
            $("p#data_recieved").append("<br />\r\n" + data.msgr + ': ' + data.msg);

            // we log this event for fun :D
            $("p#log").html('got message: ' + data.msg);

         });
      </script>
   </head>
   <body>
      <input type="text" id="msg"></input><button>Click me</button>
      <p id="log"></p>
      <p id="data_recieved"></p>
   </body>
</html>

While it works pretty well, everytime i pass something to the server from the client i get an:
“throw er; // unhandled ‘error’ event.

ReferenceError: err is not defined.

Recommend Projects

  • React photo

    React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo

    Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo

    Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo

    TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo

    Django

    The Web framework for perfectionists with deadlines.

  • Laravel photo

    Laravel

    A PHP framework for web artisans

  • D3 photo

    D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Visualization

    Some thing interesting about visualization, use data art

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo

    Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo

    Microsoft

    Open source projects and samples from Microsoft.

  • Google photo

    Google

    Google ❤️ Open Source for everyone.

  • Alibaba photo

    Alibaba

    Alibaba Open Source for everyone

  • D3 photo

    D3

    Data-Driven Documents codes.

  • Tencent photo

    Tencent

    China tencent open source team.

Recommend Projects

  • React photo
    React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo
    Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo
    Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo
    TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo
    Django

    The Web framework for perfectionists with deadlines.

  • Laravel photo
    Laravel

    A PHP framework for web artisans

  • D3 photo
    D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Visualization

    Some thing interesting about visualization, use data art

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo
    Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo
    Microsoft

    Open source projects and samples from Microsoft.

  • Google photo
    Google

    Google ❤️ Open Source for everyone.

  • Alibaba photo
    Alibaba

    Alibaba Open Source for everyone

  • D3 photo
    D3

    Data-Driven Documents codes.

  • Tencent photo
    Tencent

    China tencent open source team.

I’m running express (via nginx proxy) with socket.io and after few moments (app for some time works fine) console throw this:

events.js:71
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: socket hang up
    at createHangUpError (http.js:1360:15)
    at ServerResponse.OutgoingMessage._writeRaw (http.js:507:26)
    at ServerResponse.OutgoingMessage._send (http.js:476:15)
    at ServerResponse.OutgoingMessage.write (http.js:749:16)
    at XHRPolling.doWrite (/home/xyz/chat/node_modules/socket.io/lib/transports/xhr-polling.js:67:17)
    at XHRPolling.HTTPPolling.write (/home/xyz/chat/node_modules/socket.io/lib/transports/http-polling.js:132:8)
    at XHRPolling.Transport.onDispatch (/home/xyz/chat/node_modules/socket.io/lib/transport.js:222:10)
    at Socket.dispatch (/home/xyz/chat/node_modules/socket.io/lib/socket.js:230:38)
    at Socket.packet (/home/xyz/chat/node_modules/socket.io/lib/socket.js:214:10)
    at Socket.emit (/home/xyz/chat/node_modules/socket.io/lib/socket.js:368:15)

Any ideas?

If you are using node.js version 0.8.20, then this bug was observed by many including myself.

https://github.com/LearnBoost/socket.io/issues/1160

Upgrading node.js to version 0.8.21 solves this problem.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *