github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/example/dataloader/dataloaders.go (about) 1 //go:generate go run github.com/vektah/dataloaden AddressLoader int *github.com/99designs/gqlgen/example/dataloader.Address 2 //go:generate go run github.com/vektah/dataloaden OrderSliceLoader int []*github.com/99designs/gqlgen/example/dataloader.Order 3 //go:generate go run github.com/vektah/dataloaden ItemSliceLoader int []*github.com/99designs/gqlgen/example/dataloader.Item 4 5 package dataloader 6 7 import ( 8 "context" 9 "fmt" 10 "math/rand" 11 "net/http" 12 "strconv" 13 "strings" 14 "time" 15 ) 16 17 type ctxKeyType struct{ name string } 18 19 var ctxKey = ctxKeyType{"userCtx"} 20 21 type loaders struct { 22 addressByID *AddressLoader 23 ordersByCustomer *OrderSliceLoader 24 itemsByOrder *ItemSliceLoader 25 } 26 27 // nolint: gosec 28 func LoaderMiddleware(next http.Handler) http.Handler { 29 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 ldrs := loaders{} 31 32 // set this to zero what happens without dataloading 33 wait := 250 * time.Microsecond 34 35 // simple 1:1 loader, fetch an address by its primary key 36 ldrs.addressByID = &AddressLoader{ 37 wait: wait, 38 maxBatch: 100, 39 fetch: func(keys []int) ([]*Address, []error) { 40 var keySql []string 41 for _, key := range keys { 42 keySql = append(keySql, strconv.Itoa(key)) 43 } 44 45 fmt.Printf("SELECT * FROM address WHERE id IN (%s)\n", strings.Join(keySql, ",")) 46 time.Sleep(5 * time.Millisecond) 47 48 addresses := make([]*Address, len(keys)) 49 errors := make([]error, len(keys)) 50 for i, key := range keys { 51 addresses[i] = &Address{Street: "home street", Country: "hometon " + strconv.Itoa(key)} 52 } 53 return addresses, errors 54 }, 55 } 56 57 // 1:M loader 58 ldrs.ordersByCustomer = &OrderSliceLoader{ 59 wait: wait, 60 maxBatch: 100, 61 fetch: func(keys []int) ([][]*Order, []error) { 62 var keySql []string 63 for _, key := range keys { 64 keySql = append(keySql, strconv.Itoa(key)) 65 } 66 67 fmt.Printf("SELECT * FROM orders WHERE customer_id IN (%s)\n", strings.Join(keySql, ",")) 68 time.Sleep(5 * time.Millisecond) 69 70 orders := make([][]*Order, len(keys)) 71 errors := make([]error, len(keys)) 72 for i, key := range keys { 73 id := 10 + rand.Int()%3 74 orders[i] = []*Order{ 75 {ID: id, Amount: rand.Float64(), Date: time.Now().Add(-time.Duration(key) * time.Hour)}, 76 {ID: id + 1, Amount: rand.Float64(), Date: time.Now().Add(-time.Duration(key) * time.Hour)}, 77 } 78 79 // if you had another customer loader you would prime its cache here 80 // by calling `ldrs.ordersByID.Prime(id, orders[i])` 81 } 82 83 return orders, errors 84 }, 85 } 86 87 // M:M loader 88 ldrs.itemsByOrder = &ItemSliceLoader{ 89 wait: wait, 90 maxBatch: 100, 91 fetch: func(keys []int) ([][]*Item, []error) { 92 var keySql []string 93 for _, key := range keys { 94 keySql = append(keySql, strconv.Itoa(key)) 95 } 96 97 fmt.Printf("SELECT * FROM items JOIN item_order WHERE item_order.order_id IN (%s)\n", strings.Join(keySql, ",")) 98 time.Sleep(5 * time.Millisecond) 99 100 items := make([][]*Item, len(keys)) 101 errors := make([]error, len(keys)) 102 for i := range keys { 103 items[i] = []*Item{ 104 {Name: "item " + strconv.Itoa(rand.Int()%20+20)}, 105 {Name: "item " + strconv.Itoa(rand.Int()%20+20)}, 106 } 107 } 108 109 return items, errors 110 }, 111 } 112 113 dlCtx := context.WithValue(r.Context(), ctxKey, ldrs) 114 next.ServeHTTP(w, r.WithContext(dlCtx)) 115 }) 116 } 117 118 func ctxLoaders(ctx context.Context) loaders { 119 return ctx.Value(ctxKey).(loaders) 120 }