Skip to content
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

Error code EMFILE sending message to 19.000 devices #275

Closed
cmarrero01 opened this issue Nov 9, 2016 · 6 comments
Closed

Error code EMFILE sending message to 19.000 devices #275

cmarrero01 opened this issue Nov 9, 2016 · 6 comments

Comments

@cmarrero01
Copy link

HI,

I try to send a push notification to 19.000 devices each per each, and I receive the next error:

{ [Error: connect EMFILE 172.217.29.106:443 - Local (undefined:undefined)]
  code: 'EMFILE',
  errno: 'EMFILE',
  syscall: 'connect',
  address: '172.217.29.106',
  port: 443 } undefined

The code is:

for (var i = 0; i<doc.length;i++){
              sender.sendNoRetry(message, doc[i].token, function (err, result) {
                      console.log(err,result);
              });
}

None message was sent...

@eladnava
Copy link
Collaborator

eladnava commented Nov 9, 2016

@cmarrero01 Are you trying to send 19,000 messages with that code?

Doing it this way would que up 19,000 HTTP requests to the FCM API, which is definitely not something we want to do. The EMFILE error is thrown because the system is out of file descriptors (each socket takes up a file descriptor on Unix).

FCM allows sending to 1,000 registration IDs in the same request. You should implement a batch mechanism to split up the 19k devices and send only 19 requests via sender.sendNoRetry.

Sample implementation:
#42 (comment)

@eladnava eladnava closed this as completed Nov 9, 2016
@cmarrero01
Copy link
Author

cmarrero01 commented Nov 9, 2016

Of corse that my code above is an example only, my real code is more complex but with the same result.

The thing is the message is different for each device, so, I need send each message individualy.

For send batch messages I do something like this.


`var e;
                    var j;
                    var batchs;
                    var chunk = 999;
                    for (e=0,j=notifications.length; e<j; e+=chunk) {
                        batchs = notifications.slice(e,e+chunk);
                    }

                    pushRecursivityForAndroid(0,batchs,message,sender);
function pushRecursivityForAndroid(index,batchs,message,sender){
            if(index>=batchs.length){
                console.log("Finish Batchs");
                return;
            }
            sender.sendNoRetry(message, batchs[index], function (err, result) {
                console.log(err,result);
                index++;
                pushRecursivityForAndroid(index,batchs,message,sender);
            });
        }`

@eladnava
Copy link
Collaborator

eladnava commented Nov 9, 2016

If each message is different, you need to implement a queue mechanism so that you don't attempt to send 19,000 requests at the same time.

async.eachLimit makes this easy (using caolan/async):

// Add all 19k messages (store recipient registration ID in message.token)
var messages = [];

// Send up to 50 messages concurrently
async.eachLimit(messages, 50,
    function (message, complete) {
        sender.sendNoRetry(message, message.token, function (err, result) {
            // Invoke async's complete() callback when done sending the notification
            complete();
        });
    },
    function (err) {
        if (err) return console.error(err);
        console.log('Done processing all messages')
    }
);

@cmarrero01
Copy link
Author

The problem here is if take 500 ms to send 1 message, send 19.000 will take 15 minutes to send all messages, I need this on real time.

@eladnava
Copy link
Collaborator

eladnava commented Nov 10, 2016

@cmarrero01 Then FCM is not the right solution for your realtime requirements, especially when each message is highly individual. There's always the possibility of spinning up more servers to send more concurrent requests to FCM, but you'll need a crazy amount of servers to send 19,000 unique notifications in one second, not to mention a robust backend architecture.

There are alternative services to FCM that might be able to provide what you are looking for.

@hypesystem
Copy link
Collaborator

@cmarrero01 Could you consider doing the individualized lookup on the recipient devices? This would allow you to send identical messages to all devices.

The messages would then basically be "ping to fetch" messages, letting the device know that it needs to show a notification for something, but letting the device build the notification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants