【问题标题】:Should a Firestore client be created per a request with Google App Engine?是否应根据 Google App Engine 的请求创建 Firestore 客户端?
【发布时间】:2019-03-16 01:29:57
【问题描述】:

我对如何处理这个问题感到困惑。

似乎 GAE 希望每个客户端库都使用范围为 http.Request 的 context.Context。

我以前有过这样的经验:

main.go

type server struct {
    db *firestore.Client
}

func main() {
    // Setup server
    s := &server{db: NewFirestoreClient()}

    // Setup Router
    http.HandleFunc("/people", s.peopleHandler())

    // Starts the server to receive requests
    appengine.Main()
}

func (s *server) peopleHandler() http.HandlerFunc {
    // pass context in this closure from main?
    return func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context() // appengine.NewContext(r) but should it inherit from background somehow?
        s.person(ctx, 1)
        // ...
    }
}

func (s *server) person(ctx context.Context, id int) {
    // what context should this be?
    _, err := s.db.Client.Collection("people").Doc(uid).Set(ctx, p)
    // handle client results
}

firebase.go

// Firestore returns a warapper for client
type Firestore struct {
    Client *firestore.Client
}

// NewFirestoreClient returns a firestore struct client to use for firestore db access
func NewFirestoreClient() *Firestore {
    ctx := context.Background()
    client, err := firestore.NewClient(ctx, os.Getenv("GOOGLE_PROJECT_ID"))
    if err != nil {
        log.Fatal(err)
    }

    return &Firestore{
        Client: client,
    }
}

这对如何确定项目范围的客户范围具有重大影响。例如,挂断 server{db: client} 并在该结构上附加处理程序,或者必须通过请求中的依赖注入传递它。

我确实注意到使用客户端的调用需要另一个上下文。所以也许应该是这样的:

  1. main.go 创建一个ctx := context.Background()
  2. main.go 将其传递给新客户端
  3. handler ctx := appengine.NewContext(r)

基本上初始设置与 context.Background() 无关,因为新请求的上下文与 App Engine 不同?

我可以将 ctx 从 main 传递到处理程序,然后从那个 + 请求中传递 NewContext?

这方面的惯用方法是什么?

注意:在之前的迭代中,我也有来自 Firestore 结构的 firestore 方法...

【问题讨论】:

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


    【解决方案1】:

    您应该重复使用firestore.Client 实例进行多次调用。但是,这在 GAE 标准的旧 Go 运行时中是不可能的。因此,在这种情况下,您必须为每个请求创建一个新的 firestore.Client

    但是,如果您将新的 Golang 1.11 运行时用于 GAE 标准,那么您可以随意使用任何您喜欢的上下文。在这种情况下,您可以使用后台上下文在 main() 函数或 init() 函数中初始化 firestore.Client。然后,您可以使用请求上下文在请求处理程序中进行 API 调用。

    package main
    
    var client *firestore.Client
    
    func init() {
      var err error
      client, err = firestore.NewClient(context.Background())
      // handle errors as needed
    }
    
    func handleRequest(w http.ResponseWriter, r *http.Request) {
      doc := client.Collection("cities").Doc("Mountain View")
      doc.Set(r.Context(), someData)
      // rest of the handler logic
    }
    

    这是我使用 Go 1.11 和 Firestore 实现的示例 GAE 应用程序,它演示了上述模式:https://github.com/hiranya911/firecloud/blob/master/crypto-fire-alert/cryptocron/web/main.go

    更多关于 GAE 中的 Go 1.11 支持:https://cloud.google.com/appengine/docs/standard/go111/go-differences

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-05
      • 1970-01-01
      • 2013-10-21
      • 1970-01-01
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多