我有一个Flask-RESTful API,它充当无法处理异步调用的TCP设备的网关。
由于对我来说Resource
对象只是生成的,所以我无法从一个源头对它们进行排队和管理。
我尝试创建需要同步的Resources
使用的装饰器。在这个装饰器中,我尝试将TCP设备的ID(load_id
)附加到全局范围中的列表中,并在处理请求后将其删除。
问题是,当发出异步请求时,第一个Resource
会得到一个空列表,并追加到该列表中,而当它仍在执行时,第二个Resource
会为第二个请求创建。第二个Resource
实例也得到一个空列表。因此,我实际上不能使Resource
实例共享一个列表。
我尝试在get
,put
方法中没有装饰器的情况下显式地进行了此操作,并在数据库模型对象上定义了锁,或者在一个公共处理程序对象中管理了用{{唯一标识的对象1}},但无济于事,我总是得到一个过时的列表。
以下是其中一个的精简版本:
load_id
在此代码上,在第一个请求中,用#APPEND注释的行更改了其范围内的loads_with_query_in_progress = [] # Global scope
def disallow_async_calls(func):
@wraps(func)
def decorator(*args, **kwargs):
global loads_with_query_in_progress
load_id = kwargs.get("load_id", None)
load = Load.query.get(load_id)
if load in loads_with_query_in_progress: # Load is in the list. Aborting.
raise Exception
else:
loads_with_query_in_progress.append(load) # APPEND
try:
decorated_function_output = func(*args, **kwargs)
except Exception as e:
loads_with_query_in_progress.remove(load) # Expt handling cleanup
raise e
loads_with_query_in_progress.remove(load) # Remove lock
return decorated_function_output
return decorator
class LoadStateAPI(Resource):
decorators = [auth.login_required,
disallow_async_calls]
...
def get(self, load_id):
load = Load.query.get(load_id)
try:
rqObj = RelayQueryObject(load)
rqObj.execute()
except:
raise
if(rqObj.fsmState == CommState.COMPLETED):
return {'state' : rqObj.response}, 200
。但是,当产生另一个请求时,变量loads_with_query_in_progress
会被未经编辑地获取。
有什么方法可以解决这种异步同步转换吗?
答案 0 :(得分:0)
差异是由于生产使用uwsgi,而uwsgi使用多个进程,导致共享对象之间存在幻像差异,导致我们在不同进程中使用了不同的对象,但是我们正在调试所有日志记录的日志记录进程到同一文件。