From 1fc68a692b4a494e7acd24ddf33e130eee45779d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 13 Apr 2020 13:41:24 -0400 Subject: [PATCH] api: implement query { user } --- api/go.sum | 1 + api/graph/schema.resolvers.go | 2 +- api/loaders/middleware.go | 44 +++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/api/go.sum b/api/go.sum index 047b528..fca2176 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,4 +1,5 @@ git.sr.ht/~sircmpwn/git.sr.ht v0.0.0-20200405134845-b8fbf5bf484f h1:SW8+xV65kcga0rHmQbnZkLG36yp286BcbVOdQTVo1m8= +git.sr.ht/~sircmpwn/git.sr.ht v0.0.0-20200413150414-046cd382d7b7 h1:PYRTIcsHR5W+aPn98OCC73ly528uw5o/4Z3b5Rvc7vA= git.sr.ht/~sircmpwn/gqlgen v0.0.0-20200412134447-57d7234737d4 h1:J/Sb88htNHzZaN6ZEF8BnRWj3LzYoTrOL4WRhZEEiQE= git.sr.ht/~sircmpwn/gqlgen v0.0.0-20200412134447-57d7234737d4/go.mod h1:W1cijL2EqAyL1eo1WAJ3ijNVkZM2okpYyCF5TRu1VfI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go index a187a4a..87f4f2e 100644 --- a/api/graph/schema.resolvers.go +++ b/api/graph/schema.resolvers.go @@ -69,7 +69,7 @@ func (r *queryResolver) Me(ctx context.Context) (*model.User, error) { } func (r *queryResolver) User(ctx context.Context, username string) (*model.User, error) { - panic(fmt.Errorf("not implemented")) + return loaders.ForContext(ctx).UsersByName.Load(username) } func (r *queryResolver) Repositories(ctx context.Context, next *int, filter *model.FilterBy) ([]*model.Repository, error) { diff --git a/api/loaders/middleware.go b/api/loaders/middleware.go index 57c9858..75aa823 100644 --- a/api/loaders/middleware.go +++ b/api/loaders/middleware.go @@ -24,12 +24,12 @@ type contextKey struct { type Loaders struct { UsersByID UsersByIDLoader + UsersByName UsersByNameLoader RepositoriesByID RepositoriesByIDLoader } func fetchUsersByID(ctx context.Context, db *sql.DB) func (ids []int) ([]*model.User, []error) { - return func (ids []int) ([]*model.User, []error) { var ( err error @@ -64,9 +64,44 @@ func fetchUsersByID(ctx context.Context, } } +func fetchUsersByName(ctx context.Context, + db *sql.DB) func (names []string) ([]*model.User, []error) { + return func (names []string) ([]*model.User, []error) { + var ( + err error + rows *sql.Rows + ) + if rows, err = db.QueryContext(ctx,` + SELECT `+(&model.User{}).Columns(ctx, "u")+` + FROM "user" u + WHERE u.username = ANY($1)`, pq.Array(names)); err != nil { + panic(err) + } + defer rows.Close() + + usersByName := map[string]*model.User{} + for rows.Next() { + user := model.User{} + if err := rows.Scan(user.Fields(ctx)...); err != nil { + panic(err) + } + usersByName[user.Username] = &user + } + if err = rows.Err(); err != nil { + panic(err) + } + + users := make([]*model.User, len(names)) + for i, name := range names { + users[i] = usersByName[name] + } + + return users, nil + } +} + func fetchRepositoriesByID(ctx context.Context, db *sql.DB) func (ids []int) ([]*model.Repository, []error) { - return func (ids []int) ([]*model.Repository, []error) { var ( err error @@ -117,6 +152,11 @@ func Middleware(db *sql.DB) func(http.Handler) http.Handler { wait: 1 * time.Millisecond, fetch: fetchUsersByID(r.Context(), db), }, + UsersByName: UsersByNameLoader{ + maxBatch: 100, + wait: 1 * time.Millisecond, + fetch: fetchUsersByName(r.Context(), db), + }, RepositoriesByID: RepositoriesByIDLoader{ maxBatch: 100, wait: 1 * time.Millisecond, -- 2.38.4