Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

go - Should a Firestore client be created per a request with Google App Engine?

I'm confused on how to approach this.

It seems to be that GAE wants every client library to use a context.Context scoped to a http.Request.

I previously have experience doing something like this:

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,
    }
}

This has big implications on how to scope a project wide client. E.g hanging off of a server{db: client} and attaching handlers on that struct or having to pass it off via dependency injection within the request.

I do notice that the calls out using the client require another context. So maybe it should be like:

  1. main.go create a ctx := context.Background()
  2. main.go pass that into new client
  3. handler ctx := appengine.NewContext(r)

Basically the initial setup doesn't matter off of context.Background() because new requests have a different context from App Engine?

I could pass in ctx into the handler from main and then NewContext off of that + the request?

What's the idiomatic approach to this?

note: I had firestore methods off of the Firestore struct as well in previous iterations...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...