当事务中的任务失败时,如何使用pg-promise回滚事务?

问题描述 投票:0回答:1

比方说,我有两个函数,我想把它们一起运行,如果一个失败,另一个就回滚。

export const setThingAlertsInactive = (userID, thingIDs) => {
    return db.any(' UPDATE thing_alerts SET is_active = false WHERE IN (Select * from thing_alerts where user_id = $1 and thing_id IN ($2:csv))', [userID.toString(), thingIDs])
}

export const archiveOrRestoreThings = (thingIDs, archive) => {
    let archivedStatement =''
    if(archive === true){
        archivedStatement = 'archived = current_timestamp'
    } else if(archive === false){
        archivedStatement = 'archived = NULL'
    }
    return db.none(`UPDATE things SET ${archivedStatement} WHERE id IN ($1:csv)`, [thingIDs])
}

我想把它们放在一起运行,如果一个失败了,另一个就会回滚。事实上,我故意在第一个SQL Query中留下了一个错误。

这是我的tx函数。

export const archiveOrRestoreThingsAndSetAlert = (userID, thingsIDs, archive) => {
    return db.tx((transaction) => {
        const queries = [archiveOrRestoreThings(thingIDs, archive), setThingAlertsInactive(userID, projectIDs)]
        return transaction.batch(queries)
    })
}

第一个查询运行并成功 第二个查询失败了。在这种情况下,我需要能够将它们回滚。谢谢!我需要在这种情况下能够将它们回滚。

javascript postgresql pg-promise
1个回答
2
投票

来自作者 pg-promise.


之所以对你不起作用,是因为这两个查询函数使用的是根数据库连接上下文,而不是事务上下文,也就是说,你是在事务连接之外执行查询。

你可以把它们改成支持可选的tasktransaction上下文。

export const setThingAlertsInactive = (userID, thingIDs, t) => {
    return (t || db).none(`UPDATE thing_alerts SET is_active = false WHERE
           IN (Select * from thing_alerts where user_id = $1 and thing_id IN ($2:csv))`,
           [userID.toString(), thingIDs]);
}

export const archiveOrRestoreThings = (thingIDs, archive, t) => {
    let archivedStatement =''
    if(archive === true){
        archivedStatement = 'archived = current_timestamp'
    } else if(archive === false) {
        archivedStatement = 'archived = NULL'
    }
    return (t || db).none(`UPDATE things SET ${archivedStatement} WHERE id IN ($1:csv)`, 
                          [thingIDs]);
}

而且没有必要使用 batch,这是一个传统方法,只在特殊情况下需要。

export const archiveOrRestoreThingsAndSetAlert = (userID, thingsIDs, archive) => {
    return db.tx(async t => {
        await archiveOrRestoreThings(thingIDs, archive, t);
        await setThingAlertsInactive(userID, projectIDs, t);
    })
}

1
投票

你需要将事务传递给archiveOrRestoreThings和setThingAlertsInactive 并在事务上调用.none和.any而不是db. 请看 示例代码 以供参考。

© www.soinside.com 2019 - 2024. All rights reserved.