I'm writing some functions using sqlalchemy. These functions are called inside transaction, like:
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
After order has been successful created, email should be sent to the user. But at the end of create_order, the transaction has not yet committed, and maybe abort by later code. So this function should not send mail directly. Instead it should register a one-time event handler that be triggered only after the session has been committed (And not fire and clear if the transaction is rollback or close). How can i implement this?
You can listen for the session after_commit event with once=True:
def create_order(session, ...):
...
@event.listens_for(session, "after_commit", once=True)
def _send_email_after_commit(session):
send_email()
If you anticipate rolling back and reusing the session down the road (and don't the listener to fire after the rollback), you'll also need to remove the event in the event of a rollback:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With