sqlalchemy的update手動commit之前通過yield執行遠程異步調用時session對象被替換

SQLAlchemy==1.2.18

result = db.session.query(ObjectModel).get(ids.get("id"))
result.status = 2   #此時 session._is_clean()  =  False

#中間執行一次yield遠程調用
#外部請求函數
def onAyncFetch():
    req = ...省略其它代碼
    response = yield async_http.fetch(req)
    ...省略其它代碼
    return Return(json_decode(response.body))
print id(result.query.session) 
data = yield onAyncFetch(...)
print id(result.query.session) #兩次打印內存地址不相同
...省略其它代碼
#執行yield調用結束之後 session._is_clean()  =  True

db.session.commit() #再進行commit的會進行如下代碼段,上面修改的status字段無法被commit

上面是一段僞代碼.流程大概就這樣,下面貼sqlalchemy時commiit的源碼

sqlalchemy/orm/session.py


    def _prepare_impl(self):
        self._assert_active()
        if self._parent is None or self.nested:
            self.session.dispatch.before_commit(self.session)

        stx = self.session.transaction
        if stx is not self:
            for subtransaction in stx._iterate_self_and_parents(upto=self):
                subtransaction.commit()

        if not self.session._flushing:
            for _flush_guard in range(100):
                if self.session._is_clean():  # 判斷對象信息是否變更,如果變更則執行flush()
                    break
                self.session.flush()
            else:
                raise exc.FlushError(
                    "Over 100 subsequent flushes have occurred within "
                    "session.commit() - is an after_flush() hook "
                    "creating new objects?"
                )

        if self._parent is None and self.session.twophase:
            try:
                for t in set(self._connections.values()):
                    t[1].prepare()
            except:
                with util.safe_reraise():
                    self.rollback()

        self._state = PREPARED
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章