这里是我的情况。
我正在构建一个 RESTful Web 服务,它从客户端接收数据,然后从该数据创建一个事件,然后我想将此新事件推送到 celery 以异步处理它。
我使用 pyramid 来构建 RESTful web 服务,并使用 pyramid_celery 使金字塔和 celery 一起工作。
这是我的观点的源代码:
# views.py
# This code recive data from client, then create a new record Event from this
posted_data = schema.deserialize(request.POST.mixed())
e = Event()
e.__dict__.update(posted_data)
DBSession.add(e)
transaction.commit()
print "Commited #%d" % e.id # code mark 01
fire_event.delay(e.id) # fire_event is a celery task
logging.getLogger(__name__).info('Add event #%d to tasks' % e.id)
这是我的任务的源代码:
# tasks.py
@celery.task()
def fire_event(event_id):
e = DBSession.query(Event).get(event_id)
if e is None:
return
print "Firing event %d#%s" % (event_id, e)
logger.info("Firing event %d#%s", event_id, e)
如果我使用金字塔炼金术脚手架中的默认代码,则会在代码标记 01行引发异常。像这样的例外:
DetachedInstanceError: Instance <Event at ...> is not bound to a Session; ...
从ZopeAlchemy 文档中,为了避免这个异常,我像这样配置 DBSession:
# models.py
DBSession = scoped_session(sessionmaker(
extension=ZopeTransactionExtension(keep_session=True)
))
现在我的问题是我的 RESTful 请求完成后与我的 MySQL 服务器的金字塔保持事务。当 RESTful 请求完成后,我转到 MySQL 服务器并运行命令:
SHOW engine innodb status;
从它的结果来看,我看到了这一点:
--TRANSACTION 180692, ACTIVE 84 sec
MySQL thread id 94, OS thread handle 0x14dc, query id 1219 [domain] [ip] [project name] cleaning up
Trx read view will not see trx with id >= 180693, sees < 180693
这意味着 Pyramid 仍然保持连接,没关系,但 Pyramid 也开始交易,这是一个问题。当我尝试使用其他工具访问我的 MySQL 服务器时,此事务可能会使我陷入困境。
我的问题是:
RESTful 请求完成后,如何让 Pyramid 关闭事务。如果我不能,是否有针对我的情况的另一种解决方案?
非常感谢。