def getTerminalProxyByUserId(cache, user_id): """根据终端用户id查找在连接到哪个tgs服务器 server_eps.conf 记录tqs对应的接收rpc消息的endpoint名称, 获取ep名称,通过RpcCommunicator.findEndpoints()得到ep ep.impl就是对应服务器接收消息的连接 """ global mgws_proxies prx = None try: key = CacheEntryConfig.getUserKey(user_id) instance.getLogger().debug('cache.get: {}'.format(key)) mgws = cache.get(key) # return mgws-server's name if not mgws: return None prx = mgws_proxies.get(mgws) if not prx: cf = SimpleConfig() eps_path = os.path.join(instance.getConfigPath(), 'server_eps.conf') cf.load(eps_path) ep_name = cf.getValue(mgws) conn = tce.RpcCommunicator.instance().getConnectionMQCollection( ).get(ep_name) if conn: prx = ITerminalPrx(conn) mgws_proxies[mgws] = prx except: traceback.print_exc() finally: if not prx: instance.getLogger().info('user: {} is offline.'.format(user_id)) return prx
def ping(self, ctx): ITerminalGatewayServer.ping(self, ctx) user_id = ctx.conn.getUserId() instance.getLogger().debug("user ping.. {} {}".format( user_id,ctx.conn.getAddress())) # print desert.misc.currentDateTimeStr(), 'ping() from: ',ctx.conn.getAddress() serverid = tce.RpcCommunicator.instance().currentServer().getName() # against to server_eps.conf 对应 server_id 与 mq 名称 self.redis.set( CacheEntryConfig.getUserKey( user_id ),serverid, instance.getConfig().get('access_heartbeat_timeout', HEARTBEAT_TIMEOUT_DEFAULT))
def connectReject(self, error, conn): """ 发送通知到前端设备 """ try: termPrx = ITerminalPrx(conn) msg = Message_t() # msg.props = dict( __error__ = ErrorDefs.UserAnotherPlaceLogin.value) msg.props = dict(__error__=error.value, __error_msg__='connectReject') termPrx.onMessage_oneway(msg) conn.close() except: instance.getLogger().error(traceback.print_exc())
def acknowledge(self, sids, ctx): """ seq_ids : list B 接收到消息之后发送 确认消息, 否则系统将定时重发当初的消息或者当B再次在线online时被推送到B """ user_id = USER_ID(ctx) db = self.server.getMongoDatabaseConnection().db name = nosql.KoalaCollection.getUserMessageCollection(user_id) coll = db[name] print sids for sid in sids: coll.update({'_id': ObjectId(sid)}, { '$set': { nosql.UserMessageStatus.FIELD: nosql.UserMessageStatus.Confirmed, 'confirm_time': int(time.time()) } }) instance.getLogger().debug('message sid acked :{}'.format(sid))
def _messageRecieving(self): """消息接收线程,保证一个线程接收""" self.isclosed = False for nr in range(self.execthread_nr): thread = Thread(target=self._executeThread) self.execthreads.append(thread) thread.start() while not self.isclosed: try: message = self.consumer.fetch() message = message.content # self.ssn.acknowledge(sync=False) if message is not None: func = self.func_list[self.entry] try: func(message) self.ssn.acknowledge(sync=False) except: instance.getLogger().error(u'amqp::qpid message process error. detail:{}'.format(traceback.format_exc())) # self.lock.acquire() # self.message_pool.append(message) # self.lock.release() # with self.cond_readable: # # self.cond_readable.notify() # self.cond_readable.notify_all() except: instance.getLogger().warn(u'amqp::qpid fetch message failed. detail:{}'.format(traceback.format_exc())) gevent.sleep(5) # for thread in self.execthreads: # thread.join() instance.getLogger().info( 'amqp::qpid recieve-thread is exiting...')
def sendMessage(self, targets, message, ctx): """ 向目标对象传递消息 消息进入缓存,用户在线则即刻传递 :param targets: list(string) :param message: Message_t :param ctx: :return: """ user_id = USER_ID(ctx) if not user_id: user_id = message.meta.sender db = self.server.getMongoDatabaseConnection().db for target_id in targets: name = nosql.KoalaCollection.getUserMessageCollection(target_id) coll = db[name] # r = user_msg_col.find_one( {'_id':ObjectId(sid) }) data = { 'realm': message.meta.realm, 'sender_id': user_id, 'send_time': int(time.time()) * 1000, 'title': message.title, 'content': message.content, 'props': message.props, nosql.UserMessageStatus.FIELD: nosql.UserMessageStatus.Sendable } _id = coll.insert(data) message.meta.seq = str(_id) prx = self.getTerminalProxyByUserId(target_id) # 搜寻一个匹配的接入服务器的代理对象 if not prx: instance.getLogger().warn( "user server(mgws) not found: {} ".format(target_id)) continue prx.onMessage_oneway(message, CALL_USER_ID(target_id)) instance.getLogger().debug( "message be delivered to destination: from:{} to:{} ".format( user_id, target_id))
def sendPendingMsgToUser(self, user_id): """ 发送未传送的消息到终端用户 """ instance.getLogger().debug('_sendPendingMsgToUser: {}'.format(user_id)) db = self.server.getMongoDatabaseConnection().db name = nosql.KoalaCollection.getUserMessageCollection(user_id) user_msg_col = db[name] # 检索用户可待发送的消息列表 # sort("UserName", pymongo.ASCENDING) rs = user_msg_col.find({ nosql.UserMessageStatus.FIELD: nosql.UserMessageStatus.Sendable }).sort("send_time", pymongo.DESCENDING) if rs.count() == 0: instance.getLogger().debug('message collection is null !') return prx = self.getTerminalProxyByUserId(user_id) # 搜寻一个匹配的接入服务器的代理对象 if not prx: instance.getLogger().warn( "user server(mgws) not found: {} ".format(user_id)) return instance.getLogger().debug( "user message: {} will be dispatched.".format(rs.count())) for row in rs: m = Message_t() m.meta.realm = row.get('realm', '') m.meta.seq = row.get('_id') m.meta.sender = row.get('sender_id') m.meta.stime = row.get('send_time') m.title = row.get('title', '') m.content = row.get('content', '') m.props = row.get('props', {}) prx.onMessage_oneway(m, CALL_USER_ID(user_id))
def onUserOffline(self, userid, gws_id, device, ctx): instance.getLogger().debug('onUserOffline: {},{}'.format( userid, gws_id))
def onUserOnline(self, userid, gws_id, device, ctx): instance.getLogger().debug('onUserOnline: {},{}'.format( userid, gws_id)) #传递未发送消息到前端用户 self.sendPendingMsgToUser(userid)
def run(self): instance.getLogger().info('MEXS Service Started.') # gevent.sleep(1000000) tce.RpcCommunicator.instance().waitForShutdown()