如何添加事件处理程序仅在 sqlalchemy 中提交事务后触发一次

jay*_*ven 4 events transactions sqlalchemy

我正在使用 sqlalchemy 编写一些函数。这些函数被称为内部事务,例如:

def create_order(session, *arg, **kw):
    # create order object
    order = Order(xxxx=xxx)
    session.add(order)

    # order extra operations
    order_extra_data = OrderExtraData(yyyy=yyyy)
    session.add(order_extra_data)

    # more operations
    ....

    # email should be sent to the order's owner 
Run Code Online (Sandbox Code Playgroud)

成功创建订单后,应将电子邮件发送给用户。但在 create_order 结束时,事务尚未提交,可能会被后面的代码中止。所以这个函数不应该直接发送邮件。相反,它应该注册一个一次性事件处理程序,该处理程序仅在会话提交后触发(如果事务回滚或关闭,则不会触发和清除)。我怎样才能实现这个?

uni*_*rio 5

您可以使用以下命令监听会话after_commit事件once=True

def create_order(session, ...):
    ...
    @event.listens_for(session, "after_commit", once=True)
    def _send_email_after_commit(session):
        send_email()
Run Code Online (Sandbox Code Playgroud)

如果您预计回滚并重用会话(并且回滚后不触发侦听器),则还需要在回滚时删除该事件:

def create_order(session, ...):
    ...
    @event.listens_for(session, "after_commit", once=True)
    def _send_email_after_commit(session):
        send_email()

    @event.listens_for(session, "after_soft_rollback", once=True)
    def _remove_event_listener_on_rollback(session, prev_transaction):
        event.remove(session, "after_commit", _send_email_after_commit)
Run Code Online (Sandbox Code Playgroud)