ブログ/ニュースサイト用のコードを記述します。メインページには最新の記事が10件あります。また、すべての記事が変更時間の降順でソートされたアーカイブセクションがあります。アーカイブセクションでは、カーソルに基づくページネーションを使用し、新しい記事が公開されたときやページが何らかの理由でドラフトに移行したときにのみページが変更されるため、第2ページからの結果をキャッシュします。すべてのページには10個の記事があります。したがって、ユーザが(最初のものではなく)いくつかの番号を持つアーカイブページをヒットすると、memcacheはそのページ番号の結果が最初にチェックされます。ページがない場合は、memcacheのは、そのページのカーソルがチェックされ、その後、結果はそのカーソルを使用してデータストアからフェッチされる:put()後のApp Engine Datastoreでの読み込み遅延
class archivePage:
def GET(self, page):
if not page:
articles = memcache.get('archivePage')
if not articles:
articles = fetchArticles()
memcache.set('archivePage', articles)
else:
if int(page) == 0 or int(page) == 1:
raise web.seeother('/archive')
articles = memcache.get('archivePage'+page)
if not articles:
pageCursor = memcache.get('ArchivePageMapping'+page)
if not pageCursor:
pageMapping = ArchivePageMapping.query(ArchivePageMapping.page == int(page)).get()
pageCursor = pageMapping.cursor
memcache.set('ArchivePageMapping'+page, pageCursor)
articles = fetchArticles(cursor=Cursor(urlsafe=pageCursor))
memcache.set('archivePage'+page, articles)
新しい記事が作成されるか、または既存品のステータスが変更されるたびに(ドラフト/公開)アーカイブページの結果とカーソルのキャッシュを更新します。記事をデータストアに保存した後に行います:
class addArticlePage:
def POST(self):
formData = web.input()
if formData.title and formData.content:
article = Article(title=formData.title,
content=formData.content,
status=int(formData.status))
key = article.put()
if int(formData.status) == 1:
cacheArchivePages()
raise web.seeother('/article/%s' % key.id())
def cacheArchivePages():
articles, cursor, moreArticles = fetchArticlesPage()
memcache.set('archivePage', articles)
pageNumber=2
while moreArticles:
pageMapping = ArchivePageMapping.query(ArchivePageMapping.page == pageNumber).get()
if pageMapping:
pageMapping.cursor = cursor.urlsafe()
else:
pageMapping = ArchivePageMapping(page=pageNumber,
cursor=cursor.urlsafe())
pageMapping.put()
memcache.set('ArchivePageMapping'+str(pageNumber), cursor.urlsafe())
articles, cursor, moreArticles = fetchArticlesPage(cursor=cursor)
memcache.set('archivePage'+str(pageNumber), articles)
pageNumber+=1
ここに問題があります。キャッシュをリフレッシュした後で(時には法律がなくランダムに発生する)時々、リフレッシュ前と同じ結果とカーソルのアーカイブページが得られます。たとえば、私は新しい記事を追加します。これはデータストアに保存され、フロントページとアーカイブの最初のページに表示されます(アーカイブの最初のページはキャッシュされません)。しかし、他のアーカイブページは更新されません。私は私のcacheArchivePages()関数をテストし、期待どおりに動作します。 cacheArchivePages()関数内のfetchArticlesPage()の前にデータストアへの更新を挿入したあと、あまりにも時間がかかりすぎるのでしょうか?書き込みトランザクションがまだ完了していない可能性がありますので、古い結果が得られますか?私はtime.sleep()を使用してcacheArchivePages()を呼び出す前に数秒待っていましたが、その場合はその動作を再現できませんでしたが、time.sleep()は良い考えではないようです。とにかく、私はその行動の正確な原因とその対処方法を知る必要があります。
ありがとうございました!私はデータの一貫性にもっと注意を払い、HRデータストアの特性を覚えておく必要があります。この特定のケースでは、古い結果と新しい結果を比較するのは簡単ですし、それらが同じであればクエリを再開することも簡単です。 – wombatonfire
私は "祖先のクエリを使用する"正確に私のアプリで遅延の問題を解決したので、あなたがGuidoをありがとう、アップアップしました。 – Deleplace