Как я могу синхронизировать некоторые ресурсы Flask-RESTful? - PullRequest
0 голосов
/ 22 мая 2019

У меня есть Flask-RESTful API, который действует как шлюз для TCP-устройств, которые не могут обрабатывать асинхронные вызовы к ним.

Поскольку для меня Resource объекты просто появляются, я не могу ставить их в очередь и управлять ими из одной точки источника.

Я попытался создать декоратор, который будет использовать Resources, который нуждается в синхронизации.В этом декораторе я попытался добавить идентификатор устройства TCP (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 выбирается неотредактированной.

Есть ли способ разрешить это асинхронное преобразование?

1 Ответ

0 голосов
/ 22 мая 2019

Расхождение было связано с тем, что в производстве используется uwsgi, а uwsgi использует несколько процессов, что приводит к фантомным различиям между общими объектами, потому что мы использовали разные объекты в разных процессах, но мы отлаживали с помощью процессов журналирования, которые все регистрируют в тот же файл.

...