lib/common/service/channelService.js
function(channelService, route, msg, groups, opts, cb) {
  let app = channelService.app;
  let namespace = 'sys';
  let service = 'channelRemote';
  let method = 'pushMessage';
  let count = utils.size(groups);
  let successFlag = false;
  let failIds = [];

  logger.debug('[%s] channelService sendMessageByGroup route: %s, msg: %j, groups: %j, opts: %j', app.serverId, route, msg, groups, opts);
  if(count === 0) {
    // group is empty
    utils.invokeCallback(cb);
    return;
  }

  let latch = countDownLatch.createCountDownLatch(count, function() {
    if(!successFlag) {
      utils.invokeCallback(cb, new Error('all uids push message fail'));
      return;
    }
    utils.invokeCallback(cb, null, failIds);
  });

  let rpcCB = function(serverId) {
    return function(err, fails) {
      if(err) {
        logger.error('[pushMessage] fail to dispatch msg to serverId: ' + serverId + ', err:' + err.stack);
        latch.done();
        return;
      }
      if(fails) {
        failIds = failIds.concat(fails);
      }
      successFlag = true;
      latch.done();
    };
  };

  opts = {type: 'push', userOptions: opts || {}};
  // for compatiblity
  opts.isPush = true;
  
  let sendMessage = function(sid) {
    return (function() {
      if(sid === app.serverId) {
        channelService.channelRemote[method](route, msg, groups[sid], opts, rpcCB(sid));
      } else {
        app.rpcInvoke(sid, {namespace: namespace, service: service,
          method: method, args: [route, msg, groups[sid], opts]}, rpcCB(sid));
      }
    })();
  };

  let group;
  for(let sid in groups) {
    group = groups[sid];
    if(group && group.length > 0) {
      sendMessage(sid);
    } else {
      // empty group
      process.nextTick(rpcCB(sid));
    }
  }
}
function(channelService, route, msg, groups, opts, cb) {
  let app = channelService.app;
  let namespace = 'sys';
  let service = 'channelRemote';
  let method = 'pushMessage';
  let count = utils.size(groups);
  let successFlag = false;
  let failIds = [];

  logger.debug('[%s] channelService sendMessageByGroup route: %s, msg: %j, groups: %j, opts: %j', app.serverId, route, msg, groups, opts);
  if(count === 0) {
    // group is empty
    utils.invokeCallback(cb);
    return;
  }

  let latch = countDownLatch.createCountDownLatch(count, function() {
    if(!successFlag) {
      utils.invokeCallback(cb, new Error('all uids push message fail'));
      return;
    }
    utils.invokeCallback(cb, null, failIds);
  });

  let rpcCB = function(serverId) {
    return function(err, fails) {
      if(err) {
        logger.error('[pushMessage] fail to dispatch msg to serverId: ' + serverId + ', err:' + err.stack);
        latch.done();
        return;
      }
      if(fails) {
        failIds = failIds.concat(fails);
      }
      successFlag = true;
      latch.done();
    };
  };

  opts = {type: 'push', userOptions: opts || {}};
  // for compatiblity
  opts.isPush = true;
  
  let sendMessage = function(sid) {
    return (function() {
      if(sid === app.serverId) {
        channelService.channelRemote[method](route, msg, groups[sid], opts, rpcCB(sid));
      } else {
        app.rpcInvoke(sid, {namespace: namespace, service: service,
          method: method, args: [route, msg, groups[sid], opts]}, rpcCB(sid));
      }
    })();
  };

  let group;
  for(let sid in groups) {
    group = groups[sid];
    if(group && group.length > 0) {
      sendMessage(sid);
    } else {
      // empty group
      process.nextTick(rpcCB(sid));
    }
  }
}
function ( channelService , route , msg , groups , opts , cb ) { let app = channelService . app ; let namespace = 'sys' ; let service = 'channelRemote' ; let method = 'pushMessage' ; let count = utils . size ( groups ) ; let successFlag = false ; let failIds = [ ] ; logger . debug ( '[%s] channelService sendMessageByGroup route: %s, msg: %j, groups: %j, opts: %j' , app . serverId , route , msg , groups , opts ) ; if ( count === 0 ) { // group is empty utils . invokeCallback ( cb ) ; return ; } let latch = countDownLatch . createCountDownLatch ( count , function ( ) { if ( ! successFlag ) { utils . invokeCallback ( cb , new Error ( 'all uids push message fail' ) ) ; return ; } utils . invokeCallback ( cb , null , failIds ) ; } ) ; let rpcCB = function ( serverId ) { return function ( err , fails ) { if ( err ) { logger . error ( '[pushMessage] fail to dispatch msg to serverId: ' + serverId + ', err:' + err . stack ) ; latch . done ( ) ; return ; } if ( fails ) { failIds = failIds . concat ( fails ) ; } successFlag = true ; latch . done ( ) ; } ; } ; opts = { type : 'push' , userOptions : opts || { } } ; // for compatiblity opts . isPush = true ; let sendMessage = function ( sid ) { return ( function ( ) { if ( sid === app . serverId ) { channelService . channelRemote [ method ] ( route , msg , groups [ sid ] , opts , rpcCB ( sid ) ) ; } else { app . rpcInvoke ( sid , { namespace : namespace , service : service , method : method , args : [ route , msg , groups [ sid ] , opts ] } , rpcCB ( sid ) ) ; } } ) ( ) ; } ; let group ; for ( let sid in groups ) { group = groups [ sid ] ; if ( group && group . length > 0 ) { sendMessage ( sid ) ; } else { // empty group process . nextTick ( rpcCB ( sid ) ) ; } } }
push message by group

@param route {String} route route message
@param msg {Object} message that would be sent to client
@param groups {Object} grouped uids, , key: sid, value: [uid]
@param opts {Object} push options
@param cb {Function} cb(err)

@api private
push message by group