将App Engine写入Google Datastore挂起

时间:2018-06-01 21:32:31

标签: google-app-engine go google-cloud-datastore

我正在使用Go编写一个简单的App Engine程序。我需要将一些数据写入Google DataStore。当我尝试将程序数据存入时,程序会一直挂起。这整整一周都困扰着我。

在某些时候,我设法将数据写入DataStore,只有在我发现如何在Cloud Console中查看上传的数据时才意识到这一点。从那以后我经常更改代码,现在我再也无法编写任何数据了。它每次都挂起。

日志显示没有任何帮助。只是注意到该过程已经超时。没有从程序写入的日志,仅来自系统。

  

由于超出了请求截止日期,流程终止。 (错误代码123)

我尝试使用this link更改import语句,但编译失败,所以我回到this link编译没有问题。

我认为我可能会以某种方式严重错误配置(可能是毁容?)我的开发环境,所以我去了一台干净的机器并仔细地进行了新的安装。它仍然挂起。

我的app.yaml文件:

runtime: go
    api_version: go1

handlers:
    - url: /.*
      script: _go_app

我添加了一个index.yaml文件:

indexes:

    - kind: Bacon
        properties:
    - name: YCode
        direction: asc
    - name: URL
    - name: Owner
    - name: Location

这是我的代码:

package main

    import (
        "fmt"
        "log"
        "net/http"
        "google.golang.org/appengine/datastore"
        "google.golang.org/appengine" 
    )

     type Bacon struct {
        YCode string
        URL string
        Owner string
        Location string
    } 

    func main() {
        http.HandleFunc("/", indexHandler)
        appengine.Main() 
    }

    func indexHandler(w http.ResponseWriter, r *http.Request) {

        ctx := appengine.NewContext(r)
        projectID := "fake-for-discussion-thread-787987"

        client, err := datastore.NewClient(ctx, projectID)
        if err != nil {
            log.Fatalf("Failed to create client: %v", err)
            return
        } 

        kind := "Bacon"
        name := "3"
        baconKey := datastore.NameKey(kind, name, nil)

        //Make bacon
        bacon := Bacon{
            YCode: "1",
            URL: "http://www.safeway.com",
            Owner: "Bob",
            Location: "Deli",
        }

        // I've confirmed that this is where it hangs every time.  
        // It doesn't even capture my silly fatal log entry. 
        // It just times out and finally sends a 500 Server Error.
        if _, err := client.Put(ctx, baconKey, &bacon); err != nil {
            log.Fatalf("Failed to save my Bacon: %v", err)
        }

        client.Close()

    }

非常感谢您提供的任何帮助!

1 个答案:

答案 0 :(得分:3)

好!所以这真的把我推到了墙上,但今天早上我设法破解了它。我在查找在线文档时遇到了很多困难,我想确保将其放入我的(现在正在工作的)代码中,以便其他人可以免除这些痛苦。

值得注意的是,如果您正在部署到App Engine,我已经开始怀疑Go文档/示例可能会让您走错路。 App Engine并不像某些核心Go库等。在部署到App Engine时,这可能会变得非常混乱。

另请注意,我从我最初的问题的评论中学到了很多我的经验教训。我正在制作此条目,以便我可以正确发布我的固定App Engine特定代码。

    //Modified to work on App Engine. May not work right locally, etc.

    package main

    import (
        "fmt"
        "log"
        "net/http"
        "google.golang.org/appengine/datastore"
        "google.golang.org/appengine" 
    )

     type Bacon struct {
        YCode string
        URL string
        Owner string
        Location string
    } 

    func main() {
        http.HandleFunc("/", indexHandler)
        appengine.Main() 
    }

    func indexHandler(w http.ResponseWriter, r *http.Request) {

        //This gives a context that makes App Engine happy      
        ctx := appengine.NewContext(r)

        //NOT NEEDED (Apparently, App Engine knows who you are. Creepy.)    
        //projectID := "fake-for-discussion-thread-787987" 

        //NOT NEEDED (And may actually cause you great woe!)
        //client, err := datastore.NewClient(ctx, projectID)
        //if err != nil {
        //  log.Fatalf("Failed to create client: %v", err)
        //  return
        //} 

        //Turns out that these aren't needed, either. 
        //kind := "Bacon"
        //name := "3"

        //Note the changes from my original code, including the
        //change from NameKey to NewIncompleteKey and the
        //hard-coding of Bacon in the arguments. Alternatively, you might
        //use a variable, depending on your needs. I just need bacon.
        //This causes the entity you create in Google DataStore 
        //to have a "Kind" of "Bacon"
        baconKey := datastore.NewIncompleteKey(ctx, "Bacon", nil)

        //Make bacon
        bacon := Bacon{
            YCode: "1",
            URL: "http://www.safeway.com",
            Owner: "Bob",
            Location: "Deli",
        }

        // Note changes here. No more client, just a call to datastore.Put.
        // Now it works!  One caveat: I'm still trying to figure out why it writes 
        // my data twice. But, hey!  At least it's writing!
        if _, err := datastore.Put(ctx, baconKey, &bacon); err != nil {
            log.Fatalf("Failed to save my Bacon: %v", err)
        }

        //No client, so no need to close.
        //client.Close()

    }

干杯!