我有一个Flask-RESTful API,它充当无法处理对TCP设备的异步调用的TCP设备的网关。
因为对于我来说,Resource对象只是衍生出来的,所以我不能从单一的源点对它们进行排队和管理。
我尝试创建一个需要同步的Resources将使用的装饰器。在这个装饰器中,我尝试将TCP设备的id (load_id)附加到全局范围内的列表中,并在处理请求后将其删除。
问题是,当发出异步请求时,第一个Resource获取一个空列表,并将其追加到该列表中,当它仍在执行时,会为第二个请求创建第二个Resource。第二个Resource实例也得到一个空列表。因此,我实际上不能让Resource实例共享一个列表。
我试着在没有装饰器的情况下,在get、put方法中显式地使用在数据库模型对象上定义的锁,或者使用一个通用的处理程序对象来管理由load_id唯一标识的对象上的锁,但都没有用,我总是得到一个过时的列表。
以下是其中之一的精简版本:
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在这里的代码中,在第一个请求中,带有#APPEND注释的行更改了其作用域中的loads_with_query_in_progress。但是,当产生另一个请求时,将未经编辑地获取变量loads_with_query_in_progress。
有没有办法解决这种异步-同步转换?
发布于 2019-05-23 03:23:34
出现差异的原因是生产环境使用uwsgi,而uwsgi使用了多个进程,这导致了共享对象之间的幻影差异,因为我们在不同的进程中使用不同的对象,但我们调试的日志进程都记录到同一个文件中。
https://stackoverflow.com/questions/56257257
复制相似问题