Скрученные и вложенные отложенные со встроенными обратными вызовами в crossbar.io

Я относительно новичок в Twisted и crossbar.io, и в настоящее время я работаю над некоторыми абстракциями базы данных, используя sqlalchemy и alchimia (слой для использования sqlalchemy с Twisted). Абстракции базы данных, которые я создал до сих пор, работают, как и ожидалось, но у меня возникают проблемы при выполнении асинхронных вызовов базы данных внутри моих процедур кроссбара. Я предполагаю, что это потому, что у меня есть вложенные асинхронные вызовы, при этом внешний вызов является некоторой удаленной процедурой перекрестной панели, а внутренний - доступом к базе данных.

Я хочу сделать следующее:

@inlineCallbacks
def onJoin(self, details):
  ...
  def login(user, password): # <-- outer call
    ...
    db_result = yield db.some_query(user, password) # <-- inner call
    for row in db_result: # <-- need to wait for db_result
      return 'authentication_ticket'
    return 'error'

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

Теперь, как мне дождаться внутри RPC для входа в систему внутреннего вызова базы данных, затем аутентифицировать пользователя и затем вернуться. Я знаю, что можно связать асинхронные вызовы в Twisted, но я не знаю, как это сделать в этом особом случае с перекладиной и когда моя внешняя функция использует ярлык @inlineCallbacks.

Обновление:

Поковырявшись, теперь я могу добавить обратный вызов к запросу БД. К сожалению, теперь я не знаю, как передать возвращаемое значение из внутренней функции во внешнюю функцию (внешняя функция должна вернуть билет, с которым пользователь проходит аутентификацию):

@inlineCallbacks
  def onJoin(self, details):
  ...
  def login(user, password): # <-- outer call
    db_result = db.some_query(user, password) # <-- inner call

    def my_callback(query_result):
      if not query_result.is_empty():
        return 'user_ticket' # <-- needs to be returned by outer method

    db_result.addCallback(my_callback)

    return my_callback_result # <-- need something like that

Я попробовал defer.returnValue('user_ticket') внутри моей функции обратного вызова, но это выдает ошибку.


person 7tupel    schedule 26.01.2016    source источник


Ответы (1)


Похоже, ваша проблема заключается в том, что, хотя login ожидает получить Deferred, он не украшен @inlineCallbacks.

person Glyph    schedule 26.01.2016