obsidian/笔记文件/2.笔记/通用消息缓存器.md
2025-03-26 00:02:56 +08:00

18 KiB

#灵感/代码缓存

SessionCache

using System;
using System.Collections.Generic;
using HTFramework.Utility;
using Newtonsoft.Json;
using UnityEngine;

namespace DefaultNamespace
{
    
    [Serializable]
    public class SessionEventData
    {
        public string uuid;
        public string event_name;
        public long event_timestamp;
        public string public_properties;
        public Dictionary<string, object> event_properties;
    }
    
    [Serializable]
    public class EventData
    {
        public string uuid;
        public string event_name;
        public long event_timestamp;
        public string public_properties;
        public Dictionary<string, object> event_properties;
    }

    public enum Session_Name
    {
        start_end_session, //开始/结束会话
        default_session //普通会话
    }
    

    /// <summary>
    /// 消息事件 缓存器
    /// </summary>
    public class SessionCache : Singleton<SessionCache>
    {


        private Dictionary<string, Dictionary<string,object>> SessionDic;
        private string sessionCacheKey = "sessionCacheKey";
        private string _publicString = String.Empty;
        private int _deleteDay; //延迟几天删除

        public void OnInit(string publicString,int day)
        {
            // if (PlayerPrefs.HasKey(sessionCacheKey))
            // {
            //     PlayerPrefs.DeleteKey(sessionCacheKey);
            //     PlayerPrefs.Save();
            // }
            // return;

            _publicString = publicString;
            _deleteDay = day;

            InitData();

        }

        private void InitData()
        {

            if (PlayerPrefs.HasKey(sessionCacheKey))
            {
                SessionDic = JsonConvert.DeserializeObject<Dictionary<string,Dictionary<string,object>>>(PlayerPrefs.GetString(sessionCacheKey, ""));
            }
            else
            {
                SessionDic = new Dictionary<string, Dictionary<string,object>>();
            }
        }

        public void AddEvetData(Session_Name event_Name,object eventData)
        {
            switch (event_Name)
            {
                case Session_Name.start_end_session:
                    SessionEventData start_end_session  = eventData as SessionEventData;
                    start_end_session.public_properties = String.Empty;
                    if (!SessionDic.ContainsKey("start_end_session"))
                    {
                        Dictionary<string,object> start_sessionDic = new Dictionary<string, object>();
                        SessionDic.Add("start_end_session", start_sessionDic);
                    }
                    SessionDic["start_end_session"].Add(start_end_session.uuid,JsonConvert.SerializeObject(start_end_session));
                    break;
                case Session_Name.default_session:
                    EventData default_session = eventData as EventData;
                    default_session.public_properties = String.Empty;
                    if (!SessionDic.ContainsKey("default_session"))
                    {
                        Dictionary<string,object> default_sessionDic = new Dictionary<string, object>();
                        SessionDic.Add("default_session", default_sessionDic);
                    }
                    break;
            }
            PlayerPrefs.SetString(sessionCacheKey,JsonConvert.SerializeObject(SessionDic));
            PlayerPrefs.Save();
        }

        
        /// <summary>
        /// 移除特定缓存数据
        /// </summary>
        /// <param name="event_Name">对应缓存eventName名称</param>
        /// <param name="uuid"></param>
        public void RemoveEventData(string event_Name, string uuid)
        {
            if (SessionDic.ContainsKey(event_Name) && SessionDic[event_Name].ContainsKey(uuid))
            {
                SessionDic[event_Name].Remove(uuid);
            }
        }

        
        /// <summary>
        /// 清空缓存数据
        /// </summary>
        public void ClearEventData()
        {
            foreach (KeyValuePair<string,Dictionary<string,object>> keyValuePair in SessionDic)
            {
                keyValuePair.Value.Clear();
            }
            SessionDic.Clear();
            PlayerPrefs.DeleteKey(sessionCacheKey);
            PlayerPrefs.Save();
        }

        /// <summary>
        /// 发送缓存数据
        /// </summary>
        /// <returns></returns>
        public string CacheEvent()
        {
            List<object> SessionList = new List<object>();
            Dictionary<string, List<string>> _deleteDic = new Dictionary<string, List<string>>(); //过期需要清理的缓存数据
            
            foreach (KeyValuePair<string,Dictionary<string,object>> keyValuePair in SessionDic)
            {
                switch (keyValuePair.Key)
                {
                    case "start_end_session":
                        foreach (KeyValuePair<string,object> valuePair in keyValuePair.Value)
                        {
                            SessionEventData start_end_session_SessionEventData = JsonConvert.DeserializeObject<SessionEventData>(valuePair.Value.ToString());
                            start_end_session_SessionEventData.public_properties = _publicString;
                            if (GetDeleyTime(start_end_session_SessionEventData.event_timestamp))
                            {
                                if (!_deleteDic.ContainsKey(start_end_session_SessionEventData.event_name))
                                {
                                    List<string> uuidList = new List<string>();
                                    _deleteDic.Add(start_end_session_SessionEventData.event_name,uuidList);
                                }
            
                                _deleteDic[start_end_session_SessionEventData.event_name].Add(start_end_session_SessionEventData.uuid);
                            }
                            SessionList.Add(start_end_session_SessionEventData);
                        }
                        break;
                    case "default_session":
                        foreach (KeyValuePair<string,object> valuePair in keyValuePair.Value)
                        {
                            EventData default_session_SessionEventData = JsonConvert.DeserializeObject<EventData>(valuePair.Value.ToString());
                            default_session_SessionEventData.public_properties = _publicString;
                            if (GetDeleyTime(default_session_SessionEventData.event_timestamp))
                            {
                                if (!_deleteDic.ContainsKey(default_session_SessionEventData.event_name))
                                {
                                    List<string> uuidList = new List<string>();
                                    _deleteDic.Add(default_session_SessionEventData.event_name,uuidList);
                                }
            
                                _deleteDic[default_session_SessionEventData.event_name].Add(default_session_SessionEventData.uuid);
                            }
                            SessionList.Add(default_session_SessionEventData);
                        }
                        break;
                }
            }
            
            foreach (KeyValuePair<string,List<string>> keyValuePair in _deleteDic)
            {
                for (int i = 0; i < keyValuePair.Value.Count; i++)
                {
                    SessionDic[keyValuePair.Key].Remove(keyValuePair.Value[i]);
                }
            }
            
            
            if (SessionList.Count <= 0)
            {
                return  String.Empty;
            }
            return JsonConvert.SerializeObject(SessionList);
        }
        

        private bool GetDeleyTime(long t)
        {
            double time = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000 - t;
            if (Math.Floor(time / 86400) > _deleteDay)
            {
                return true;
            }

            return false;
        }

    }
}

SessionMgr

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using DefaultNamespace;
using HTFramework.Utility;
using UnityEngine;
using Newtonsoft.Json;
using UnityEngine.Networking;

namespace CGBU_SDK
{

    /// <summary>
    /// 会话时间管理类
    /// </summary>
    public class SessionMgr : MonoSingleton<SessionMgr>
    {
        // private const string appId = "3f99e16c541a";
        // private const string reportUrl = "https://global-receiver-ias.icongamesg.com/report/?appid=" + appId;
        
        private const string StartSession = "start_session";
        private const string EndSession = "end_session";
        // private const string sessionCachePrefsKey = "sessionCachePrefsKey";

        private const string ReSendUrl = "&batch=1";
        
        private string _sessionId;
        private string _publicString;
        private long  _startEventTimestamp;
        private long _endEventTimestamp;
        private Dictionary<string, object> _eventDic;
        private Dictionary<string, object> _userDataDic;

        private string _uid = String.Empty;
        private string _uuid = String.Empty;


        #region 生命周期
        
        private void Awake()
        {
            _uid = SystemInfo.deviceUniqueIdentifier;
        }
        

        private void OnDestroy()
        {
            StopNetworkRequest();
        }

        /// <summary>
        /// 切后台 暂停游戏
        /// </summary>
        /// <param name="pauseStatus"></param>
        private void OnApplicationPause(bool pauseStatus)
        {
            if (pauseStatus)
            {
                SendEndSessionEvent();
            }
            else
            {
                CacheEvent(0);
            }
        }
        

        /// <summary>
        /// 退出游戏
        /// </summary>
        private void OnApplicationQuit()
        {
            AddToList(CreateEndEvent());
        }

        private SessionEventData CreateEndEvent()
        {
            _endEventTimestamp = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
            SessionEventData _sessionEndEventData = new SessionEventData
            {
                uuid =  _uuid,
                event_name = EndSession,
                event_timestamp = _endEventTimestamp,
                public_properties = _publicString,
                event_properties = _eventDic
            };

            _sessionEndEventData.event_name = EndSession;
            _sessionEndEventData.event_timestamp = _endEventTimestamp;
            
            _sessionEndEventData.event_properties["session_dur"] = _endEventTimestamp - _startEventTimestamp;
            _sessionEndEventData.event_properties["user_properties"] = _userDataDic;
            return _sessionEndEventData;
        }
        

        #endregion

        #region 会话收发&业务逻辑

        /// <summary>
        /// 发送结束会话事件
        /// </summary>
        private void SendEndSessionEvent()
        {
            SessionEventData endData = CreateEndEvent();
            ReportEvent(JsonConvert.SerializeObject(endData),false,0,endData);
        }


        /// <summary>
        /// 初始化 发送开始会话事件
        /// </summary>
        /// <param name="wake"></param>
        /// <param name="publicString"></param>
        /// <param name="uid"></param>
        /// <param name="eventDataDic"></param>
        /// <param name="userDataDic"></param>
        public void OnInit(bool wake,string publicString,string uid = null,Dictionary<string,object> eventDataDic = null,Dictionary<string,object> userDataDic = null)
        {

            // if (PlayerPrefs.HasKey(sessionCachePrefsKey))
            // {
            //     PlayerPrefs.DeleteKey(sessionCachePrefsKey);
            //     PlayerPrefs.Save();
            // }
            // return;
            
            if (!wake)
            {
                Destroy(gameObject);
                return;
            }
            
            SessionCache.Instance.OnInit("",7);
            
            _uid = uid != null ? uid : _uid;
            _publicString = publicString;
            _startEventTimestamp = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
            // _sessionId = _uid + _startEventTimestamp + GenerateRandomString(10);
            _sessionId = DateTime.Now.ToUniversalTime().Ticks.ToString();

            _uuid = Guid.NewGuid() + "-" + DateTime.Now.ToUniversalTime().Ticks;

            _userDataDic = new Dictionary<string, object>();
            _eventDic = new Dictionary<string, object>
            {
                ["session_id"] = _sessionId,
                ["session_dur"] = 0,
                ["user_properties"] = _userDataDic
                
            };
            
            SessionEventData _sessionStartEventData = new SessionEventData
            {
                uuid =  _uuid,
                event_name = StartSession,
                event_timestamp = _startEventTimestamp,
                public_properties = _publicString,
                event_properties = _eventDic
            };
            
            ChangeEventDataDic(eventDataDic);
            ChangeUserDataDic(userDataDic);
            ReportEvent(JsonConvert.SerializeObject(_sessionStartEventData), false, 0, _sessionStartEventData);
        }

        
        /// <summary>
        /// 修改事件数据
        /// </summary>
        /// <param name="eventDataDic"></param>
        public void ChangeEventDataDic(Dictionary<string, object> eventDataDic)
        {
            if (eventDataDic != null)
            {
                Dictionary<string, object> mergedDict = _eventDic.Union(eventDataDic.Where(kvp => !_eventDic.ContainsKey(kvp.Key)))
                    .ToDictionary(pair => pair.Key, pair => pair.Value);
                _eventDic = mergedDict;
            }
        }

        /// <summary>
        /// 修改用户数据
        /// </summary>
        /// <param name="userDataDic"></param>
        public void ChangeUserDataDic(Dictionary<string,object> userDataDic)
        {
            _userDataDic = userDataDic == null ? _userDataDic : userDataDic;
        }
        
        private void ReportEvent(string eventDataStr,bool isReSend = false,int reSendCount = 0,SessionEventData eventData = null)
        {
            if (eventData != null)
            {
                AddToList(eventData);
            }
            StartNetworkRequest(Instance.SendSessionEvent(eventDataStr,isReSend,reSendCount,eventData));
        }
        
        private IEnumerator SendSessionEvent(string eventDataStr,bool isReSend = false,int reSendCount = 0,SessionEventData eventData = null)
        {
            string AnalyseAppId = isReSend == false ? "8d482dec8f6d" : "8d482dec8f6d" + ReSendUrl;
            // 发送POST请求
            using (UnityWebRequest www = new UnityWebRequest("https://7b6zvje56lpbtmjuzwulj36qoi0hikbc.lambda-url.us-east-1.on.aws?appid=" + AnalyseAppId, "POST"))
            {
                byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(eventDataStr);
                www.uploadHandler = new UploadHandlerRaw(bodyRaw);
                www.downloadHandler = new DownloadHandlerBuffer();
                www.SetRequestHeader("Content-Type", "application/json");
                yield return www.SendWebRequest();


                // 检查是否有错误发生
                if (www.result != UnityWebRequest.Result.Success)
                {
                    // Debug.Log("Error: " + www.error);
                }
                else
                {
                    // 获取服务器响应的文本内容
                    // string responseText = www.downloadHandler.text;
                
                    // 输出服务器响应内容
                    // Debug.Log("Server Response: " + responseText);
                    

                    if (isReSend) //如果是批量重发,就清空缓存器
                    {
                        SessionCache.Instance.ClearEventData();
                    }
                    else //如果不是重发,说明第一次就发送成功了,检测是否在缓存中,如果存在于缓存中,删除即可
                    {
                        if (eventData != null)
                        {
                            SessionCache.Instance.RemoveEventData(eventData.event_name,eventData.uuid);
                        }
                    }
                }

                if (www.isNetworkError || www.isHttpError)
                {
                    // Debug.LogError("Error: " + www.error);
                }
                CacheEvent(reSendCount);
            }
        }
        
        private void CacheEvent(int reSendCount = 0)
        {
            if (reSendCount >= 1) //只重发一次
            {
                return;
            }

            string ListStr = SessionCache.Instance.CacheEvent();
            
            if (ListStr != String.Empty)
            {
                reSendCount += 1;
                ReportEvent(ListStr,true,reSendCount);
            }
        }

        private void AddToList(SessionEventData sessionEventData)
        {
            SessionCache.Instance.AddEvetData(Session_Name.start_end_session,sessionEventData);
        }
        

        #endregion
        

        #region 协程处理

        private Coroutine networkCoroutine;

        private void StartNetworkRequest(IEnumerator coroutine)
        {
            if (networkCoroutine == null) //检查是否已有协程在运行
            {
                networkCoroutine = StartCoroutine(coroutine);
            }
            else
            {
                StopCoroutine(networkCoroutine);
                networkCoroutine = StartCoroutine(coroutine);
            }
        }
        
        private void StopNetworkRequest()
        {
            if (networkCoroutine != null)
            {
                StopCoroutine(networkCoroutine);
                networkCoroutine = null;
            }
        }

        #endregion

    }
}