丨Hong丨
丨Hong丨
  • 发布:2023-10-10 16:28
  • 更新:2023-10-16 11:19
  • 阅读:236

【报Bug】定时跑云函数,把数据库中的一个表导出到云存储中,导出成功后删除指定日期数据,导出失败,数据也被删除了

分类:uniCloud

产品分类: uniCloud/App

示例代码:
'use strict';  
const dayjs = require('dayjs')  
const timezone = require('dayjs/plugin/timezone');  
const utc = require('dayjs/plugin/utc');  
// 注册时区和 UTC 插件  
dayjs.extend(utc);  
dayjs.extend(timezone);  

const db = uniCloud.database()  

exports.main = async (event, context) => {  
    // 是否调试  
    const isDebug = false  
    // 往前查找时间,单位天  
    let day = 0  
    if (isDebug) {  
        day = 6  
    } else {  
        day = 30  
    }  

    const pageSize = 1000  
    const startDayObj = dayjs().utcOffset(8).subtract(day, 'day').startOf('day')  
    const startTime = startDayObj.valueOf()  
    const endTime = dayjs().utcOffset(8).subtract(day, 'day').endOf('day').valueOf()  
    const startDay = startDayObj.format("YYYY-MM-DD")  
    const dbCmd = db.command  

    // 1.查找自定义事件列表  
    const uniStatEventsCollection = db.collection('yyy')  
    const uniStatEventsData = await uniStatEventsCollection.where({  
        _id: dbCmd.exists(true)  
    }).get()  

    let eventKeyAry = []  
    if (isDebug) {  
        eventKeyAry = ["debug-123456"]  
    } else {  
        eventKeyAry = uniStatEventsData.data.map(item => item.event_key)  
    }  

    // 2.找出日志中符合事件和自定义事件的数据  
    const uniStatEventLogsCollection = await db.collection('xxx')  

    for (let i = 0; i < eventKeyAry.length; i++) {  
        const name = eventKeyAry[i]  
        const boxId = name.replace('', '')  

        // 查询条件  
        const where = {  
            event_key: name,  
            create_time: dbCmd.and(  
                dbCmd.gte(startTime),   
                dbCmd.lte(endTime)  
            )  
        }  

        // 总数  
        const { total } = await uniStatEventLogsCollection.where(where).count()  

        // 数据  
        let { data } = await uniStatEventLogsCollection.where(where).limit(pageSize).get()  

        // 没有box数据的停止处理  
        if (!data.length) {  
            continue;  
        }  

        // 当前查找长度  
        let findLength = data.length  

        // 当前搜索长度大于等于总数停止处理  
        // 总数要大于1000才行  
        if (data.length >= total && total > pageSize) {  
            continue;  
        }  

        // 获取页数  
        const page = Math.ceil(total / pageSize)  

        // 设置1就是之前已经拿过1000条(1页数据)  
        for (let ii = 1; ii < page; ii++) {  
            const { data: _data } =  await uniStatEventLogsCollection.where(where).skip(ii * pageSize).limit(pageSize).get()  
            data = [  
                ...data,  
                ..._data  
            ]  
        }  

        const saveText = data.map(item => item.param)  

        await uniCloud.uploadFile({  
            cloudPath: `testData/${boxId}/${startDay}.txt`,  
            fileContent: Buffer.from(encodeURIComponent(JSON.stringify(saveText))),  
            cloudPathAsRealPath: true,  
        });  

        await uniStatEventLogsCollection.where(where).remove()  
    }  

    //返回数据给客户端  
    return {  
        startTime: dayjs(startTime).format('YYYY-MM-DD HH:mm:ss'),  
        endTime: dayjs(endTime).format('YYYY-MM-DD HH:mm:ss'),  
    }  
};

操作步骤:
'use strict';  
const dayjs = require('dayjs')  
const timezone = require('dayjs/plugin/timezone');  
const utc = require('dayjs/plugin/utc');  
// 注册时区和 UTC 插件  
dayjs.extend(utc);  
dayjs.extend(timezone);  

const db = uniCloud.database()  

exports.main = async (event, context) => {  
    // 是否调试  
    const isDebug = false  
    // 往前查找时间,单位天  
    let day = 0  
    if (isDebug) {  
        day = 6  
    } else {  
        day = 30  
    }  

    const pageSize = 1000  
    const startDayObj = dayjs().utcOffset(8).subtract(day, 'day').startOf('day')  
    const startTime = startDayObj.valueOf()  
    const endTime = dayjs().utcOffset(8).subtract(day, 'day').endOf('day').valueOf()  
    const startDay = startDayObj.format("YYYY-MM-DD")  
    const dbCmd = db.command  

    // 1.查找自定义事件列表  
    const uniStatEventsCollection = db.collection('yyy')  
    const uniStatEventsData = await uniStatEventsCollection.where({  
        _id: dbCmd.exists(true)  
    }).get()  

    let eventKeyAry = []  
    if (isDebug) {  
        eventKeyAry = ["debug-123456"]  
    } else {  
        eventKeyAry = uniStatEventsData.data.map(item => item.event_key)  
    }  

    // 2.找出日志中符合事件和自定义事件的数据  
    const uniStatEventLogsCollection = await db.collection('xxx')  

    for (let i = 0; i < eventKeyAry.length; i++) {  
        const name = eventKeyAry[i]  
        const boxId = name.replace('', '')  

        // 查询条件  
        const where = {  
            event_key: name,  
            create_time: dbCmd.and(  
                dbCmd.gte(startTime),   
                dbCmd.lte(endTime)  
            )  
        }  

        // 总数  
        const { total } = await uniStatEventLogsCollection.where(where).count()  

        // 数据  
        let { data } = await uniStatEventLogsCollection.where(where).limit(pageSize).get()  

        // 没有box数据的停止处理  
        if (!data.length) {  
            continue;  
        }  

        // 当前查找长度  
        let findLength = data.length  

        // 当前搜索长度大于等于总数停止处理  
        // 总数要大于1000才行  
        if (data.length >= total && total > pageSize) {  
            continue;  
        }  

        // 获取页数  
        const page = Math.ceil(total / pageSize)  

        // 设置1就是之前已经拿过1000条(1页数据)  
        for (let ii = 1; ii < page; ii++) {  
            const { data: _data } =  await uniStatEventLogsCollection.where(where).skip(ii * pageSize).limit(pageSize).get()  
            data = [  
                ...data,  
                ..._data  
            ]  
        }  

        const saveText = data.map(item => item.param)  

        await uniCloud.uploadFile({  
            cloudPath: `testData/${boxId}/${startDay}.txt`,  
            fileContent: Buffer.from(encodeURIComponent(JSON.stringify(saveText))),  
            cloudPathAsRealPath: true,  
        });  

        await uniStatEventLogsCollection.where(where).remove()  
    }  

    //返回数据给客户端  
    return {  
        startTime: dayjs(startTime).format('YYYY-MM-DD HH:mm:ss'),  
        endTime: dayjs(endTime).format('YYYY-MM-DD HH:mm:ss'),  
    }  
};

预期结果:

云函数读取表的数据,存储到云存储有文件生成

实际结果:

云函数执行成功,但是云存储没有文件生成,数据库表的记录也被删除,超过7天没办法恢复

bug描述:

用定时任务跑云函数,把数据库一个表日志记录归档成文件存储到云存储中,国庆前放假测试是没问题的,放假回来之后,发现云存储没有新增文件,数据库的数据被删除了
发现数据被删除之后重新测试云函数生成云存储是没问题,有文件生成的,但是被删掉的数据无法恢复,超过7天,也没办法定位到问题为什么定时任务执行成功,云存储却没有文件生成

2023-10-10 16:28 负责人:无 分享
已邀请:
DCloud_uniCloud_WYQ

DCloud_uniCloud_WYQ

私聊发一下服务空间id和定时任务执行的requestId及日志内容

  • 丨Hong丨 (作者)

    已发

    2023-11-01 10:56

  • 丨Hong丨 (作者)

    可以留联系方式,例如qq之类的吗?

    2023-11-01 10:56

  • DCloud_uniCloud_WYQ

    回复 丨Hong丨: 你试试把remove注释掉,单独执行一下云存储里面会生成文件吗?这个问题是不是必现的?

    2023-11-01 11:16

要回复问题请先登录注册