Appengine的数据存储游标永远不会改变。

huangapple go评论86阅读模式
英文:

Appengine's datastore Cursor never changes

问题

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

有什么想法,为什么事情不像我想的那样工作?

http.HandleFunc("/fix", func(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    fixUser(c, w, r, "/fix", func() error { 
       // 在这里进行修复
       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)   // 总是相同的值
        u.Key = key
        fn(&u)
    }

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

I am trying to update a lot of records, to which cannot be done within the one minute max request time given, so I need to use a datastore.Cursor, but for some reason the returned cursor is always the same. So each redirect is done with the same cursor value, resulting in the the same 20 database updates being performed each time.

Any ideas to why things aren't working like I would like?

http.HandleFunc(&quot;/fix&quot;, func(w, http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
fixUser(c, w, r, &quot;/fix&quot;, 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(&quot;users&quot;)
c := r.URL.Query().Get(&quot;c&quot;)
if len(c) &gt; 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 &lt; 20; i++ {
var u User
key, err := iter.Next(&amp;u)
if err == datastore.Done {
return
}
if err != nil {
panic(err.Error())
}
cr, _ = iter.Cursor()
log.Debugf(ctx, &quot;Cursor: %v&quot;, cr)   // always the same value
u.Key = key
fn(&amp;u)
}
pathWithCursor := fmt.Sprintf(&quot;%s?c=%s&quot;, path, cr.String())
http.Redirect(w, r, pathWithCursor, 301)
}

答案1

得分: 1

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

英文:

I looked at some of my own cursor code and compared it against yours. The main difference I see is that I use q = q.Start(cursor) rather than q.start(cursor). This should fix your problem since your query will now be updated to reflect the position specified by the cursor. Without storing your query back into the q variable, your query will not update.

huangapple
  • 本文由 发表于 2017年3月12日 02:29:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/42738999.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定