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