Просмотр исходного кода

1.针对不进背包的道具增加日志 2.处理邮件模块有时候会导致进程崩溃问题

gitxsm 3 недель назад
Родитель
Сommit
a792f4e504
2 измененных файлов с 138 добавлено и 42 удалено
  1. 3 0
      script/module/bag/BagLogic.lua
  2. 135 42
      script/module/mail/MailManager.lua

+ 3 - 0
script/module/bag/BagLogic.lua

@@ -285,6 +285,9 @@ function handlerSpObj(human, itemID, itemCnt, logType)
     	return
     end
 
+	Log.write(Log.LOGID_OSS_ITEM, human.db._id, human.db.account, human.db.name, human.db.lv,
+		LogDefine.DEFINE[logType] + LogDefine.TYPE["item"] , itemID, itemCnt, 0)
+
 	local cmdstr = itemConfig.cmd and itemConfig.cmd[1]
 	if cmdstr and ItemLogic.cmd[cmdstr] then
 		ItemLogic.onlyuse(human, itemID, itemCnt, logType, true)

+ 135 - 42
script/module/mail/MailManager.lua

@@ -9,6 +9,7 @@ local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
 local RoleSystemDefine = require("roleSystem.RoleSystemDefine") 
 local RoleDBLogic = require("role.RoleDBLogic")
 local MailExcel = require("excel.mail")
+local CommonDB = require("common.CommonDB")
 
 SYSTEM = 1 				-- 系统邮件
 GONGGAO = 2 				-- 公告
@@ -75,7 +76,8 @@ function add(type,receiverUuid,title,content,items,senderName,sender,time,fbTime
         mail.flag = 1
     end
 	LuaMongo.insert(DB.db_mail, mail)
-	RoleSystemLogic.onDotByUuid(receiverUuid, RoleSystemDefine.ROLE_SYS_ID_204)
+	-- 检测红点会调用getMails(), 短时间插入多封邮件加上玩家邮件数量过多,会发生段错误
+	-- RoleSystemLogic.onDotByUuid(receiverUuid, RoleSystemDefine.ROLE_SYS_ID_204)
 	return mail
 
 end
@@ -156,58 +158,149 @@ local function cmpMail(a, b)
 end
 
 local mails = {}
-function getMails(receiverUuid,mailType)
-	for key in ipairs(mails) do 
-		mails[key] = nil
-	end
+-- function getMails(receiverUuid,mailType)
+-- 	for key in ipairs(mails) do 
+-- 		mails[key] = nil
+-- 	end
+
+-- 	FIELD_RECEIVER.receiverUuid = receiverUuid
+-- 	FIELD_RECEIVER.type = mailType
+
+--     LuaMongo.find(DB.db_mail,{["$query"]=FIELD_RECEIVER})
+    
+-- 	local lastTime = os.time() - 7 * 86400
+--     local mailCnt = 0
+-- 	while true do
+-- 		local mail = {}
+-- 		-- if not LuaMongo.next(mail) then
+-- 		-- 	break
+-- 		-- end
 
-	FIELD_RECEIVER.receiverUuid = receiverUuid
-	FIELD_RECEIVER.type = mailType
+-- 		local res, err = pcall(function ()
+-- 			return LuaMongo.next(mail)
+-- 		end)
 
-    LuaMongo.find(DB.db_mail,{["$query"]=FIELD_RECEIVER})
+-- 		if not res then
+-- 			Log.write(Log.LOGID_DEBUG, "MailManager.getMails err = ".. err)
+-- 			break
+-- 		end
+
+-- 		if not err then
+-- 			break
+-- 		end
+
+--        if mail.expireTime then  -- 有指定过期时间
+--             if mail.time > os.time() - mail.expireTime then
+-- 			    mailCnt = mailCnt + 1
+-- 			    mails[mailCnt] = mail
+--             end
+--        elseif mail.time > lastTime then -- 没有就用默认过期时间
+--             mailCnt = mailCnt + 1
+-- 			mails[mailCnt] = mail
+--        end
+-- 	end
     
-	local lastTime = os.time() - 7 * 86400
+--     if mailCnt > MAIL_MAX_CNT then
+-- 		table.sort(mails, cmpMail)
+-- 		for i = MAIL_MAX_CNT + 1, mailCnt do
+-- 			mails[i] = nil
+-- 		end
+-- 	end    
+-- 	return mails
+-- end
+
+-- 替换原有的 getMails 函数
+function getMails(receiverUuid, mailType)
+    -- 1. 清空缓存表
+    for i = 1, #mails do mails[i] = nil end
+
+    local now = os.time()
     local mailCnt = 0
-	while true do
-		local mail = {}
-		-- if not LuaMongo.next(mail) then
-		-- 	break
-		-- end
-
-		local res, err = pcall(function ()
-			return LuaMongo.next(mail)
-		end)
-
-		if not res then
-			Log.write(Log.LOGID_DEBUG, "MailManager.getMails err = ".. err)
-			break
-		end
+    local tempMails = {}
+    local SCAN_LIMIT = 2000  -- 单次分段查询安全上限
+    local foundEnough = false
 
-		if not err then
-			break
-		end
+    -- 2.将时间划分为多个小窗口,避免单次 find 触发底层 OOM
+    -- 窗口设计:最近7天 -> 7~14天 -> 14~30天 -> 30~60天
+    local timeWindows = {
+        {now - 7*86400,   now},
+        {now - 14*86400,  now - 7*86400},
+        {now - 30*86400,  now - 14*86400},
+        {now - 60*86400,  now - 30*86400}
+    }
+	-- 60天 -> 开服
+	local serverOpenTime = CommonDB.getServerOpenTime()
+	timeWindows[#timeWindows+1] = { serverOpenTime, now - 60*86400 }
+
+    for _, window in ipairs(timeWindows) do
+        if foundEnough then break end
+
+        -- 使用最简平铺查询,彻底避开 C 扩展解析缺陷
+        local query = {
+            receiverUuid = receiverUuid,
+            type = mailType,
+            time = { ["$gte"] = window[1], ["$lte"] = window[2] }
+        }
 
-       if mail.expireTime then  -- 有指定过期时间
-            if mail.time > os.time() - mail.expireTime then
-			    mailCnt = mailCnt + 1
-			    mails[mailCnt] = mail
+        LuaMongo.find(DB.db_mail, query)
+
+        local mail = {}
+        local scanCnt = 0
+        while true do
+            local has_next = LuaMongo.next(mail)
+            if not has_next then break end
+            
+            scanCnt = scanCnt + 1
+            if scanCnt > SCAN_LIMIT then 
+                Log.write(Log.LOGID_DEBUG, string.format("Mail segment limit hit! uuid=%s window=%d~%d", 
+                    receiverUuid, window[1], window[2]))
+                break 
             end
-       elseif mail.time > lastTime then -- 没有就用默认过期时间
+
+            -- 浅拷贝隔离 C 驱动内部 Buffer
+            local m = {}
+            for k, v in pairs(mail) do m[k] = v end
+            tempMails[#tempMails + 1] = m
+
+            -- 清空复用表
+            for k in pairs(mail) do mail[k] = nil end
+        end
+
+        -- 如果已收集足够多数据(留足过滤冗余),提前终止后续窗口查询
+        if #tempMails >= 500 then 
+            foundEnough = true 
+            break 
+        end
+    end
+
+    -- 3.按时间倒序排序,确保后续取到的是“最新”的
+    table.sort(tempMails, cmpMail)
+
+    -- 4. 过滤过期邮件,精准截取最新 100 条
+    for _, m in ipairs(tempMails) do
+        if type(m.time) ~= "number" then m.time = 0 end
+
+        local isExpired = false
+        local expireTime = m.expireTime
+        if expireTime and type(expireTime) == "number" then
+            if m.time <= now - expireTime then isExpired = true end
+        elseif m.time <= now - 7 * 86400 then
+            isExpired = true
+        end
+
+        if not isExpired then
             mailCnt = mailCnt + 1
-			mails[mailCnt] = mail
-       end
-	end
-    
-    if mailCnt > MAIL_MAX_CNT then
-		table.sort(mails, cmpMail)
-		for i = MAIL_MAX_CNT + 1, mailCnt do
-			mails[i] = nil
-		end
-	end    
-	return mails
+            mails[mailCnt] = m
+            if mailCnt >= MAIL_MAX_CNT then break end -- 达到 100 条立即退出
+        end
+    end
+
+    return mails
 end
 
 
+
+
 function saveMail(mail)
     FIELD_ID._id = mail._id
     LuaMongo.update(DB.db_mail, FIELD_ID, mail)