Beispiel #1
0
        public ActionResult UpdateReadState(string accesstoken, string msg_uids)
        {
            //先验证访问权限
            var userid = IMRedisDAL.GetUserIdByAccessToken(accesstoken);

            if (!String.IsNullOrEmpty(msg_uids))
            {
                var msg_uid_list  = msg_uids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var redis_msgpost = new FaceHand.Common.ResdisExecutor(RedisConfig.REDIS_MSGPOST_KEY);
                redis_msgpost.Exec(db => {
                    var chatMsgList = new List <Dictionary <string, string> >();

                    //更新整体的未读消息数量
                    var batch = db.CreateBatch();
                    foreach (string msg_uid in msg_uid_list)
                    {
                        var readtime = db.SortedSetScore($"readtime_{msg_uid}", userid);
                        if (!readtime.HasValue)
                        {
                            //从未读消息列表中移除
                            batch.SortedSetRemoveAsync($"notreadlist_{userid}", msg_uid, CommandFlags.FireAndForget);

                            //更新未读消息统计计数
                            var msg         = IMRedisDAL.GetMsg(msg_uid);
                            var msgtype_str = msg.GetStringValue(RedisFields.MSG_TYPE);
                            if (!String.IsNullOrEmpty(msgtype_str))
                            {
                                var count_rv = db.HashGet($"notreadcount_{userid}", msgtype_str);
                                if (count_rv.HasValue && !count_rv.IsNullOrEmpty)
                                {
                                    long count_lng = 0;
                                    if (count_rv.TryParse(out count_lng))
                                    {
                                        if (count_lng > 0)
                                        {
                                            batch.HashDecrementAsync($"notreadcount_{userid}", msgtype_str, 1, CommandFlags.FireAndForget);
                                        }
                                        else
                                        {
                                            batch.HashSetAsync($"notreadcount_{userid}", msgtype_str, 0);
                                        }
                                    }
                                }

                                //如果是聊天消息,更新聊天消息的阅读情况
                                var msgtype_int = Convert.ToInt32(msgtype_str);
                                if (msgtype_int < 60)
                                {
                                    chatMsgList.Add(msg);
                                }
                            }

                            //更新阅读时间
                            batch.SortedSetAddAsync($"readtime_{msg_uid}",
                                                    new SortedSetEntry[] { new SortedSetEntry(userid, DateTime.Now.AsUnixTimestamp()) }, CommandFlags.FireAndForget);
                        }
                    }

                    batch.Execute();

                    //更新聊天消息和接收者之间的的未读数量
                    if (chatMsgList.Count > 0)
                    {
                        var batch2 = db.CreateBatch();
                        foreach (var msg in chatMsgList)
                        {
                            var msg_senderid = msg.GetStringValue(RedisFields.MSG_SEND_USERID);
                            var receivers    = msg.GetStringValue(RedisFields.MSG_SUCCESS_RECEIVERS);
                            if (!String.IsNullOrEmpty(receivers))
                            {
                                var receivers_list = receivers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                foreach (var receiver_userid in receivers_list)
                                {
                                    var k        = $"chatnotreadcount_{msg_senderid}_{receiver_userid}";
                                    var count_rv = db.Execute("get", k);
                                    if (count_rv.HasValue() && !count_rv.IsNull && !count_rv.IsEmpty())
                                    {
                                        //这个key必须大于0才执行递减操作
                                        //否则不变
                                        if (count_rv.AsInt() > 0)
                                        {
                                            batch2.ExecuteAsync("DECRBY", k, 1);
                                        }
                                        else
                                        {
                                            batch2.ExecuteAsync("set", k, 0);
                                        }
                                    }
                                    else
                                    {
                                        //这个key还不存在
                                        batch2.ExecuteAsync("set", k, 0);
                                    }
                                }
                            }
                        }
                        batch2.Execute();
                    }
                });
            }

            return(JsonContent(true));
        }
Beispiel #2
0
        //投送消息
        private static void SendMsg(string msg_uid, bool isRemoveFromMQ)
        {
            //获取消息以验证消息的有效性
            var msg = IMRedisDAL.GetMsg(msg_uid);

            if (msg == null || msg.Count == 0)
            {
                throw new BusinessException($"message {msg_uid} not found");
            }

            var state = msg.GetStringValue(RedisFields.MSG_STATE).AsEnum <MsgSendState>();

            if (state != MsgSendState.Sending)
            {
                //消息ID被取到,但是又不是正在发送的状态
                //说明消息已被其它进程处理,这时应该从消息队列中删除这个ID
                var redis_msmq = new FaceHand.Common.ResdisExecutor(RedisConfig.REDIS_MSGMQ_KEY);
                redis_msmq.Exec(db => db.ListRemove(MessageSendStateQueue.SENDING, msg_uid, 0, CommandFlags.FireAndForget));
            }
            else
            {
                //验证接收人,把有效的人和无效的人分离出来
                var receiver_valid   = new List <string>();
                var receiver_invalid = new List <string>();
                ValidateReceiver(msg[RedisFields.MSG_RECEIVERS], ref receiver_valid, ref receiver_invalid);

                //没有有效接收人,消息发送失败
                if (receiver_valid.Count == 0)
                {
                    //更新消息发送状态为失败
                    FaceHand.Common.ResdisExecutor.ExecCommand(db => db.HashSet($"msg_{msg_uid}", new HashEntry[] {
                        //更新发送失败的人
                        new HashEntry(RedisFields.MSG_FAILED_RECEIVERS, String.Join(",", receiver_invalid)),
                        //更新消息发送状态
                        new HashEntry(RedisFields.MSG_STATE, (int)MsgSendState.Failed),
                        //更新消息发送状态
                        new HashEntry(RedisFields.MSG_ERROR_MSG, "available receivers count is zero")
                    }, CommandFlags.FireAndForget), RedisConfig.REDIS_MSGCACHE_KEY);

                    //从队列中删除消息
                    if (isRemoveFromMQ)
                    {
                        var redis_msmq = new FaceHand.Common.ResdisExecutor(RedisConfig.REDIS_MSGMQ_KEY);
                        redis_msmq.Exec(db => db.ListRemove(MessageSendStateQueue.SENDING, msg_uid, 0, CommandFlags.FireAndForget));
                    }

                    //抛出错误,以便控制台能看到发送失败
                    throw new BusinessException($"available receivers count is zero");
                }
                else
                {
                    //投送消息
                    var redis_msgpost = new FaceHand.Common.ResdisExecutor(RedisConfig.REDIS_MSGPOST_KEY);
                    redis_msgpost.Exec(db => {
                        var batch           = db.CreateBatch();
                        var msg_sendtime    = msg.GetStringValue(RedisFields.MSG_SEND_TIME).AsLong();
                        var msg_senderid    = msg.GetStringValue(RedisFields.MSG_SEND_USERID);
                        var msg_type        = (int)msg.GetStringValue(RedisFields.MSG_TYPE).AsEnum <MsgType>();
                        var isChatMsg       = msg_type < 60;
                        var now             = DateTime.Now;
                        var nowUnixTimestmp = now.AsUnixTimestamp();
                        foreach (var receiver_userid in receiver_valid)
                        {
                            //更新未读消息数,未读消息数按消息类型分别存
                            batch.HashIncrementAsync($"notreadcount_{receiver_userid}", msg[RedisFields.MSG_TYPE], 1D, CommandFlags.FireAndForget);

                            //将消息ID放入对应人的未读消息清单
                            batch.SortedSetAddAsync($"notreadlist_{receiver_userid}", msg_uid, nowUnixTimestmp, When.Always, CommandFlags.FireAndForget);

                            //单独统计聊天消息的数量
                            if (isChatMsg)
                            {
                                var chatnotreadcount_k = $"chatnotreadcount_{msg_senderid}_{receiver_userid}";
                                var chatnotreadcount   = db.Execute("GET", chatnotreadcount_k).AsInt();

                                if (chatnotreadcount < 0)
                                {
                                    batch.ExecuteAsync("SET", 1);
                                }
                                else
                                {
                                    batch.ExecuteAsync("INCRBY", chatnotreadcount_k, 1D);
                                }
                            }
                        }

                        batch.Execute();
                    });

                    //更新消息发送状态
                    FaceHand.Common.ResdisExecutor.ExecCommand(db => db.HashSet($"msg_{msg_uid}", new HashEntry[] {
                        //更新发送成功的人
                        new HashEntry(RedisFields.MSG_SUCCESS_RECEIVERS, String.Join(",", receiver_valid)),

                        //更新发送失败的人
                        new HashEntry(RedisFields.MSG_FAILED_RECEIVERS, String.Join(",", receiver_invalid)),

                        //更新消息发送状态
                        new HashEntry(RedisFields.MSG_STATE, (int)MsgSendState.Success)
                    }, CommandFlags.FireAndForget), RedisConfig.REDIS_MSGCACHE_KEY);

                    var redis_msmq = new FaceHand.Common.ResdisExecutor(RedisConfig.REDIS_MSGMQ_KEY);

                    //从队列中删除消息
                    if (isRemoveFromMQ)
                    {
                        redis_msmq.Exec(db => db.ListRemove(MessageSendStateQueue.SENDING, msg_uid, 0, CommandFlags.FireAndForget));
                    }

                    //通过订阅器通知客户端有新消息
                    if (receiver_valid.Count > 0)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            try
                            {
                                redis_msmq.Exec(db => db.Publish(
                                                    RedisChannelName.NEW_MESSAGE_CHANNEL_TOCLIENT,
                                                    $"{msg_uid},{String.Join(",", receiver_valid)}", //通知client manager
                                                    CommandFlags.FireAndForget));
                            }
                            catch (Exception ex)
                            {
                                WriteErrorLog($"notify {msg_uid} to client failed. {ex.Message}");
                            }
                        });
                    }

                    //将消息持久化到数据库
                    Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            using (var context = new DataContext(MysqlDbConfig.IMCONN))
                            {
                                IMMySqlDAL.Instance.InsertMsg(msg, receiver_valid);
                            }
                        }
                        catch (Exception ex)
                        {
                            WriteErrorLog($"save message {msg_uid} to database failed. {ex.Message}");
                        }
                    });

                    //如果是应用消息,还要考虑是否通知到企业微信端
                    if (msg[RedisFields.MSG_TYPE].AsEnum <MsgType>() == MsgType.system_app)
                    {
                    }

                    WriteLog($"post message success。msg_uid:{msg_uid}");
                }
            }
        }