graphql-python / graphql-python/flask-graphql

Poor interaction with threads (python 2.7)

未關閉
#43 3 則留言 1 個 reaction 已指派 0 人 在 GitHub 檢視
主要語言
Python
星號
1.3k
分支
139
PR 合併指標
30 天內沒有已合併 PR

描述

the interaction between this library, graphql-core, and promise appears to allow execution to hop threads especially (only?) when using a middleware and nested resolvers. this is inconsistent with flasks threading model and the ability to access the request/g thread locals

with the attached (very contrived) example, when submitting the query with concurrent requests the requests frequently fail because the key created in get_context doesn't exist on the threadlocal flask.g object in the resolvers. This happens when a thread accesses the promise.async_instance which isn't thread local, and resolves a promise that was created on a different thread.
[query.txt](https://github.com/graphql-python/flask-graphql/files/2014433/query.txt)

```
from flask import Flask
from flask_graphql import GraphQLView

app = Flask(__name__)

import graphene
import threading
import time
from flask import g

def get_user(info):
return g.get(info.context['key'])

class User(graphene.ObjectType):
id = graphene.ID()
name = graphene.String()
friend = graphene.Field(lambda: User)
age = graphene.Int()
apple = graphene.String()

@classmethod
def resolve_friend(cls, root, info):
time.sleep(.1)
x = get_user(info)
return User(id=id(root), name=':'.join([x.name, threading.current_thread().name]))

@classmethod
def resolve_age(cls, root, info):
time.sleep(.1)
return 5

@classmethod
def resolve_apple(cls, root, info):
time.sleep(.1)
return "Apple"

class Query(graphene.ObjectType):
me = graphene.Field(User)

def resolve_me(self, info):
time.sleep(.1)
return get_user(info)

schema = graphene.Schema(query=Query)

ahh = {}
def dummy_middleware(next, root, info, **args):
return_value = next(root, info, **args)
return return_value

import random
random.seed()

class TestQLView(GraphQLView):
def get_context(self, request):
# set a random key in g to be used by resolvers
key = str(random.randint(0,50))
name = threading.current_thread().name
user = User(id=key, name=name)
setattr(g, key, user)
return {
'key': key
}

app.add_url_rule('/graphql', view_func=TestQLView.as_view('graphql', schema=schema, graphiql=True, middleware=[dummy_middleware]))
```

貢獻指南

這個儲存庫沒有索引到貢獻指南

研究方向

從附帶的 query.txt 和範例中顯示的 GraphQLView.get_context 進入點開始,接著跨並行請求追蹤 dummy_middleware、巢狀 resolver、promise.async_instance 和 Flask g。使用提供的 Python 2.7 範例重現故障,並判定執行在何處切換執行緒。完成的標準是了解這項互動,並就保留要求本地內容的修正方向達成共識。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
graphql, python
領域
api, backend
Issue 類型
缺陷
難度
4/5
預估耗時
3-5 天
活躍度
停滯
描述清晰度
需要釐清
新手友好度
28/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。