github.com/operandinc/gqlgen@v0.16.1/docs/content/reference/apq.md (about)

     1  ---
     2  title: "Automatic persisted queries"
     3  description:
     4  linkTitle: "APQ"
     5  menu: { main: { parent: "reference", weight: 10 } }
     6  ---
     7  
     8  When you work with GraphQL by default your queries are transferred with every request. That can waste significant
     9  bandwidth. To avoid that you can use Automatic Persisted Queries (APQ).
    10  
    11  With APQ you send only query hash to the server. If hash is not found on a server then client makes a second request
    12  to register query hash with original query on a server.
    13  
    14  ## Usage
    15  
    16  In order to enable Automatic Persisted Queries you need to change your client. For more information see
    17  [Automatic Persisted Queries Link](https://www.apollographql.com/docs/resources/graphql-glossary/#automatic-persisted-queries-apq) documentation.
    18  
    19  For the server you need to implement the `graphql.Cache` interface and pass an instance to
    20  the `extension.AutomaticPersistedQuery` type. Make sure the extension is applied to your GraphQL handler.
    21  
    22  See example using [go-redis](https://github.com/go-redis/redis) package below:
    23  
    24  ```go
    25  import (
    26  	"context"
    27  	"time"
    28  
    29  	"github.com/operandinc/gqlgen/graphql/handler"
    30  	"github.com/operandinc/gqlgen/graphql/handler/extension"
    31  	"github.com/operandinc/gqlgen/graphql/handler/transport"
    32  	"github.com/go-redis/redis"
    33  )
    34  
    35  type Cache struct {
    36  	client redis.UniversalClient
    37  	ttl    time.Duration
    38  }
    39  
    40  const apqPrefix = "apq:"
    41  
    42  func NewCache(redisAddress string, ttl time.Duration) (*Cache, error) {
    43  	client := redis.NewClient(&redis.Options{
    44  		Addr:     redisAddress,
    45  	})
    46  
    47  	err := client.Ping().Err()
    48  	if err != nil {
    49  		return nil, fmt.Errorf("could not create cache: %w", err)
    50  	}
    51  
    52  	return &Cache{client: client, ttl: ttl}, nil
    53  }
    54  
    55  func (c *Cache) Add(ctx context.Context, key string, value interface{}) {
    56  	c.client.Set(apqPrefix+key, value, c.ttl)
    57  }
    58  
    59  func (c *Cache) Get(ctx context.Context, key string) (interface{}, bool) {
    60  	s, err := c.client.Get(apqPrefix + key).Result()
    61  	if err != nil {
    62  		return struct{}{}, false
    63  	}
    64  	return s, true
    65  }
    66  
    67  func main() {
    68  	cache, err := NewCache(cfg.RedisAddress, 24*time.Hour)
    69  	if err != nil {
    70  		log.Fatalf("cannot create APQ redis cache: %v", err)
    71  	}
    72  
    73  	c := Config{ Resolvers: &resolvers{} }
    74  	gqlHandler := handler.New(
    75  		generated.NewExecutableSchema(c),
    76  	)
    77  	gqlHandler.AddTransport(transport.POST{})
    78  	gqlHandler.Use(extension.AutomaticPersistedQuery{Cache: cache})
    79  	http.Handle("/query", gqlHandler)
    80  }
    81  ```