Last active
April 11, 2021 20:40
-
-
Save calam1/19cbd3ceef2d903f99a3c1696b94bdc1 to your computer and use it in GitHub Desktop.
some code snippets for gqlgen dataloader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I learned a lot from watching this youtube video - https://www.youtube.com/watch?v=D3SrjuTaUQU | |
// Gin Route File | |
import ( | |
... | |
"github.com/mycompany/menu/graph/dataloader/meal_tag" | |
) | |
func Routes(r *gin.Engine) { | |
... | |
mealTagDataloader := meal_tag.NewMealTagDataloader() | |
... | |
rg := r.Group("/mysite") | |
rg.Use( | |
... | |
meal_tag.MealTagLoaderMiddleware(productRepository), | |
... | |
{ | |
rg.POST("query", serverutils.GraphqlHandler(productRepository, mealTagDataloader)) | |
} | |
} | |
// graphql handler file | |
func GraphqlHandler(productRepo productRepo.ProductRepository, mealTagDataloader meal_tag.MealTagDataloader) gin.HandlerFunc { | |
h := handler.New(gqlGen.NewExecutableSchema(gqlGen.Config{ | |
Resolvers: &resolvers.Resolver{ | |
ProductRepository: productRepo, | |
... | |
MealTagDataloader: mealTagDataloader, | |
... | |
}, | |
Complexity: gqlGen.ComplexityRoot{}, | |
})) | |
h.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { | |
rc := graphql.GetOperationContext(ctx) | |
rc.DisableIntrospection = cfg.GraphQLDisableIntrospection | |
return next(ctx) | |
}) | |
h.Use(extension.FixedComplexityLimit(cfg.GraphQLComplexityCount)) | |
return func(c *gin.Context) { | |
h.AddTransport(transport.GET{}) | |
h.AddTransport(transport.POST{}) | |
h.ServeHTTP(c.Writer, c.Request) | |
} | |
} | |
// Dataloader file | |
const mealTagsLoaderKey = "mealTagsLoader" | |
func MealTagLoaderMiddleware(productRepo productRepo.ProductRepository) gin.HandlerFunc { | |
return func(c *gin.Context) { | |
mealTagLoader := MealTagLoader{ | |
maxBatch: 100, | |
wait: 5 * time.Millisecond, | |
fetch: func(ids []int) ([]*string, []error) { | |
mealTags, err := productRepo.MealTagAllergens(c, ids) | |
if err != nil { | |
log.Errorf("error in mealTagLoaderMiddleware retrieving mealTags %v", err) | |
return nil, []error{err} | |
} | |
return buildMealTagsAndSort(ids, mealTags) | |
}, | |
} | |
ctx := context.WithValue(c.Request.Context(), mealTagsLoaderKey, &mealTagLoader) | |
c.Request = c.Request.WithContext(ctx) | |
c.Next() | |
} | |
} | |
func buildMealTagsAndSort(ids []int, mealTags []*model.MealTag) ([]*string, []error) { | |
... do some stuff | |
result := make([]*string, len(ids)) | |
... do some more stuff | |
return result, nil | |
} | |
type MealTagDataloader interface { | |
GetMealTagLoader(ctx context.Context) *MealTagLoader | |
} | |
type MealTagDataloaderImpl struct{} | |
func NewMealTagDataloader() *MealTagDataloaderImpl { | |
return &MealTagDataloaderImpl{} | |
} | |
func (m *MealTagDataloaderImpl) GetMealTagLoader(ctx context.Context) *MealTagLoader { | |
return ctx.Value(mealTagsLoaderKey).(*MealTagLoader) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment