【问题标题】:ndb put() work but not update result at the same time just after 15-30 secondsndb put() 工作但不会在 15-30 秒后同时更新结果
【发布时间】:2019-01-20 02:57:28
【问题描述】:

我有一个非常有趣的问题(对我来说完全是),我有查询,在这个查询中我有列表行:

class TestList(ndb.Model):
    testing_list = ndb.StringProperty(repeated=True)
    list_id = ndb.IntegerProperty()

我还有通过 PATCH 请求更改 testing_list 的 API 方法。 代码:

@app.route('/list/change', methods=['PATCH'])
def list_change():
    list_id = request.form['id']
    list_elements = request.form['elements']
    query = TestList.query(TestList.list_id == int(list_id))
    try:
        query.fetch()[0].list_id
    except IndexError:
        return 'Error', 400
    new_elements = str(list_elements).replace(' ', '').split(',')
    query.fetch()[0].testing_list = [element for element in new_elements if element in query.fetch()[0].testing_list]
    query.fetch()[0].put()

    testing_list_extend(query.get(), new_elements)
    return 'Success', 200

@ndb.transactional
def testing_list_extend(list_key, new_elements):
    for element in new_elements:
        query = TestList.query(ancestor=list_key.key)
        if element not in query.fetch()[0].testing_list:
            query.fetch()[0].testing_list.append(element)
            query.fetch()[0].put()
    return '200'

在输入时,我得到类似'Element1,Element2'的字符串,这是正文请求中的elementsid,如'1'。所以在我解析字符串并制作列表之后。在我想在 testing_list 中添加新的独特元素之后。在这部分我有错误:有时,当我添加新元素并通过 GET 请求获取 testing_list 时,我得到空列表,但在 15-30 秒内我得到列表前段时间就想看 例如在正文 PATCH 请求中:

id = '1'
elements = 'Element1, Element2'

我通过获得 testing_list 等待什么响应:

[Element1, Element2]

我经常得到的:

[Element1, Element2]

我得到的东西非常罕见(我认为是错误):

[]

【问题讨论】:

标签: python-2.7 google-app-engine google-cloud-datastore app-engine-ndb


【解决方案1】:

问题出在 ndb 缓存中。

为此问题编写功能测试并发现 google.cloud 中 Datastore 上的行已更新,但同时执行 GET 请求并获取旧日期,因此在 GET 方法中放置了 ndb.get_context()。 clear_cache() 这工作得很好。

【讨论】:

    【解决方案2】:

    这里有一些问题,但我认为您的问题的原因是您执行的多次 put 和 fetches。如果您可以使用TestLists 键而不是TestList.list_id,这会更好。这样你的函数看起来像这样:

    @app.route('/list/change', methods=['PATCH'])
    def list_change():
        list_id = request.form['id']
        list_elements = request.form['elements']
        new_elements = str(list_elements).replace(' ', '').split(',')
        try:
            testing_list_extend(ndb.Key(TestList, long(list_id)), new_elements)
            return 'Success', 200
        except Exception as e:
            return e.message, 400
    
    @ndb.transactional
    def testing_list_extend(list_key, new_elements):
        test_list = list_key.get()
        if test_list is None:
            raise Exception('Test List ID does not exist')
        l = []
        l.extend(entity.testing_list)  # the existing list
        l.extend(new_elements)  # the append the new_elements
        entity.testing_list = list(set(l))  # remove duplicates
        entity.put()
    

    否则,请尝试这样做:

    @app.route('/list/change', methods=['PATCH'])
    def list_change():
        list_id = request.form['id']
        list_elements = request.form['elements']
        new_elements = str(list_elements).replace(' ', '').split(',')
        try:
            # Only return the Key, to be used in the transaction below
            query = TestList.query(TestList.list_id == int(list_id)).fetch(2, keys_only=True)
            if len(query) == 0:
                raise Exception("Found no 'TestList' with list_id == %s" % list_id)
            # Double check for duplicates
            elif len(query) == 2:
                raise Exception("Found more than one 'TestList' with list_id == %s" % list_id)
            testing_list_extend(query[0], new_elements)
            return 'Success', 200
        except Exception as e:
            return e.message, 400
    
    @ndb.transactional
    def testing_list_extend(list_key, new_elements):  # same
        test_list = list_key.get()
        if test_list is None:
            raise Exception('Test List ID does not exist')
        l = []
        l.extend(entity.testing_list)  # the existing list
        l.extend(new_elements)  # the append the new_elements
        entity.testing_list = list(set(l))  # remove duplicates
        entity.put()
    

    【讨论】:

    • 谢谢,我修改了我的代码!但问题出在 ndb 缓存中。我为此问题编写了功能测试,发现 google.cloud 中 Datastore 上的那一行已更新,但同时我做了 GET 请求并获取旧日期,所以在我的 GET 方法我把ndb.get_context().clear_cache() 和它工作正常。
    • @Ruslan 您能否将其发布为造福社区的答案?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    • 1970-01-01
    相关资源
    最近更新 更多