package graphql import ( "context" "net/http" "strconv" "tercul/internal/app" "tercul/internal/app/author" "tercul/internal/domain" "github.com/graph-gophers/dataloader/v7" ) type ctxKey string const ( loadersKey = ctxKey("dataloaders") ) type Dataloaders struct { AuthorLoader *dataloader.Loader[string, *domain.Author] } func newAuthorLoader(authorQueries *author.AuthorQueries) *dataloader.Loader[string, *domain.Author] { return dataloader.NewBatchedLoader(func(ctx context.Context, keys []string) []*dataloader.Result[*domain.Author] { ids := make([]uint, len(keys)) for i, key := range keys { id, err := strconv.ParseUint(key, 10, 32) if err != nil { // handle error } ids[i] = uint(id) } authors, err := authorQueries.GetAuthorsByIDs(ctx, ids) if err != nil { // handle error } authorMap := make(map[string]*domain.Author) for _, author := range authors { authorMap[strconv.FormatUint(uint64(author.ID), 10)] = &author } results := make([]*dataloader.Result[*domain.Author], len(keys)) for i, key := range keys { results[i] = &dataloader.Result[*domain.Author]{Data: authorMap[key]} } return results }) } func Middleware(app *app.Application, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { loaders := Dataloaders{ AuthorLoader: newAuthorLoader(app.AuthorQueries), } ctx := context.WithValue(r.Context(), loadersKey, loaders) r = r.WithContext(ctx) next.ServeHTTP(w, r) }) } func For(ctx context.Context) Dataloaders { return ctx.Value(loadersKey).(Dataloaders) }