Я работаю над простой системой обмена сообщениями, где два разных пользователя могут отправлять сообщения друг другу. Прямо сейчас каждый пользователь опрашивает сервер, запрашивая новейшие сообщения, используя graphQL.
Проблема в том, что когда один пользователь, пользователь A, отправляет тонну сообщений (запросы мутации graphQL), пока другой пользователь, пользователь B, опрашивает, иногда кажется, что сообщения были отправлены пользователем B.
Я посмотрел глубже и обнаружил, что в тех случаях, когда сообщения были неправильно распределены, запрос на мутацию был обработан с неверным запросом (как указано в контексте), и current_user
из flask_login
также является неправильным. current_user
, кажется, зависит от запроса. Запрос был одним из запросов пользователя B (которые не являются мутациями.)
Я немного проследил это и нашел точку, где заполняется контекст (https://github.com/graphql-python/flask-graphql/blob/master/flask_graphql/graphqlview.py#L42), но было трудно понять, почему он получал неправильный запрос от Flask.
Мое лучшее предположение - что-то происходит со стеком контекста запросов Flask, но его сложно отследить.
Я должен упомянуть, что аутентификация выполняется с использованием заголовка авторизации, и что я попытался найти случай, когда пользователь был неправильно аутентифицирован, но не смог.
Кажется, что это происходит только тогда, когда я запускаю колбу, используя FLASK_ENV=production flask run
, и, кажется, исчезает, когда я запускаю ее, используя gunicorn
. Тем не менее, это касается того, что аутентификация может быть настолько хрупкой.
Кто-нибудь видел эту проблему раньше? Есть ли в документации Flask что-то, объясняющее эту проблему, почему это происходит, и, что более важно, почему это не произойдет, когда я использую gunicorn
?
Соответствующие версии кода:
- Колба 1.0.2
- Flask-GraphQL 2.0.0
- Flask-Login 0.4.1
- Flask-SQLAlchemy 2.3.2
- графен 2.1.3
- графен-sqlalchemy 2.1.0
- graphql-core 2.1
- SQLAlchemy 1.2.12
Пример кода:
import graphene as gr
from graphql import GraphQLError
from flask_login import current_user
from ...models import Message
from .shared import MessageNode
class CreateMessage(gr.Mutation):
""" Send a message to a channel account """
message = gr.Field(MessageNode)
class Arguments:
body = gr.JSONString(required=True)
@login_required
def mutate(self, info, body):
# Make sure that the body is populated with something
if not (body.get("text") and not body.get("image")) and not (
not body.get("text") and body.get("image")
):
raise GraphQLError("Body must contain either text or an image")
new_message = Message(
body=body,
sender_account=current_user, # CURRENT USER IS INCORRECT HERE
)
db.session.add(new_message)
db.session.commit()
return CreateMessage(message=new_message)