Appengine的数据存储区Cursor永远不会改变

时间:2017-03-11 18:29:25

标签: google-app-engine go

我正在尝试更新很多记录,在给定的一分钟最大请求时间内无法完成,因此我需要使用datastore.Cursor,但由于某种原因,返回的游标始终是相同的。因此,每个重定向都使用相同的游标值完成,从而导致每次执行相同的20个数据库更新。

为什么事情不像我想的那样有效?

http.HandleFunc("/fix", func(w, http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    fixUser(c, w, r, "/fix", func() error { 
       // do the fix here
       return nil
    })
})

func fixUser(ctx context.Context, w http.ResponseWriter, r *http.Request, path string, fn func(user *User) error) {
    q := datastore.NewQuery("users")
    c := r.URL.Query().Get("c")
    if len(c) > 0 {
        cursor, err := datastore.DecodeCursor(c)
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            w.Write([]byte(err.Error()))
            return
        }
        q.Start(cursor)
    }

    iter := q.Run(ctx)
    var cr datastore.Cursor
    for i := 0; i < 20; i++ {
        var u User
        key, err := iter.Next(&u)
        if err == datastore.Done {
            return
        }
        if err != nil {
            panic(err.Error())
        }
        cr, _ = iter.Cursor()
        log.Debugf(ctx, "Cursor: %v", cr)   // always the same value
        u.Key = key
        fn(&u)
    }

    pathWithCursor := fmt.Sprintf("%s?c=%s", path, cr.String())
    http.Redirect(w, r, pathWithCursor, 301)
}

1 个答案:

答案 0 :(得分:1)

我查看了一些自己的游标代码并将其与您的游标代码进行了比较。我看到的主要区别是我使用的是q = q.Start(cursor)而不是q.start(cursor)。这应该可以解决您的问题,因为您的查询现在将更新以反映光标指定的位置。如果不将查询存储回q变量,您的查询将不会更新。