google-app-engine - 是否应根据 Google App Engine 的请求创建 Firestore 客户端?
问题描述
我对如何处理这个问题感到困惑。
似乎 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,
}
}
这对如何确定项目范围的客户有很大的影响。例如,挂断 aserver{db: client}
并在该结构上附加处理程序,或者必须通过请求中的依赖注入传递它。
我确实注意到使用客户端的调用需要另一个上下文。所以也许它应该是这样的:
main.go
创建一个ctx := context.Background()
main.go
将其传递给新客户handler ctx := appengine.NewContext(r)
基本上初始设置并不重要,context.Background()
因为新请求与 App Engine 具有不同的上下文?
我可以将 ctx 从 main 传递到处理程序,然后从那个 + 请求中传递 NewContext 吗?
什么是惯用的方法?
Firestore
注意:在以前的迭代中,我也有结构体之外的 firestore 方法......
解决方案
您应该重复使用该firestore.Client
实例进行多次调用。但是,这在 GAE 标准的旧 Go 运行时中是不可能的。因此,在这种情况下,您必须为firestore.Client
每个请求创建一个新的。
但是如果你使用新的 Golang 1.11 运行时的 GAE 标准,那么你可以自由地使用你喜欢的任何上下文。firestore.Client
在这种情况下,您可以在main()
函数中或init()
使用后台上下文的函数中进行初始化。然后,您可以使用请求上下文在请求处理程序中进行 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
推荐阅读
- python - 谁在他们的公司中使用 pyenv?
- python - 如何在 Python 中绘制 Google QuickDraw 数据集?
- c# - 如何在仅数字排序的字母数字中使用顺序
- powershell - 使用 powershell 在 powerpoint 中编辑形状
- android - 为什么在 Android 中为 NumberPicker 设置 textcolor 时会发生 NoSuchFieldException?
- azure-logic-apps - 如何检索多个逻辑应用程序的“已完成运行”计数
- php - ~/.composer/vendor/laravel/valet/server.php 中的权限被拒绝
- ruby-on-rails - 无法将 project_id 设置为嵌套路由中的数据库
- php - 无法使用 curl 或 file_get_contents 在单独的网站上执行命令
- android-layout - 如何实现以下 xml 布局?