/* Init returns an initialised Map180. d must have access to the map180 tables in the public schema. cacheBytes is the size of the memory cache for land and lake layers. region must be a valid Region. Example: wm, err = map180.Init(db, map180.Region(`newzealand`), 256000000) */ func Init(d *sql.DB, region Region, cacheBytes int64) (*Map180, error) { w := &Map180{} var err error if _, ok := allZoomRegions[region]; !ok { err = fmt.Errorf("invalid region (allZoomRegions): %s", region) return w, err } if _, ok := allMapBounds[region]; !ok { err = fmt.Errorf("invalid region (allMapBounds): %s", region) return w, err } if _, ok := allNamedMapBounds[region]; !ok { err = fmt.Errorf("invalid region (allNamedMapBounds): %s", region) return w, err } zoomRegion = allZoomRegions[region] mapBounds = allMapBounds[region] namedMapBounds = allNamedMapBounds[region] db = d mapLayers = groupcache.NewGroup("mapLayers", cacheBytes, groupcache.GetterFunc(layerGetter)) landLayers = groupcache.NewGroup("landLayers", cacheBytes, groupcache.GetterFunc(landGetter)) lakeLayers = groupcache.NewGroup("lakeLayers", cacheBytes, groupcache.GetterFunc(lakeGetter)) return w, nil }
func main() { // STARTINIT OMIT me := "http://127.0.0.1:11211" peers := groupcache.NewHTTPPool(me) // Whenever peers change: peers.Set("http://127.0.0.1:11211") // ENDINIT OMIT // STARTGROUP OMIT var thumbNails = groupcache.NewGroup("thumbnail", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { dest.SetBytes(generateThumbnail(key)) return nil })) // ENDGROUP OMIT var ctx groupcache.Context // STARTUSE OMIT var data []byte thumbNails.Get(ctx, "big-file.jpg", groupcache.AllocatingByteSliceSink(&data)) fmt.Println(string(data)) }
// SetCacheMaxSize enables icon caching if sizeInMB > 0. func SetCacheMaxSize(sizeInMB int64) { if sizeInMB > 0 { iconCache = groupcache.NewGroup("icons", sizeInMB<<20, groupcache.GetterFunc(generatorFunc)) } else { iconCache = nil } }
func main() { flag.Parse() peers := gc.NewHTTPPool("http://localhost:" + *port) peers.Set("http://localhost:8001", "http://localhost:8002") cg = gc.NewGroup("QRCache", 1<<20, gc.GetterFunc( func(ctx gc.Context, key string, dest gc.Sink) error { fmt.Printf("asking for data of %s\n", key) url := fmt.Sprintf("http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl=%s", key) resp, err := http.Get(url) if err != nil { return nil } body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil } value := base64.StdEncoding.EncodeToString(body) dest.SetBytes([]byte(value)) return nil })) // run groupcache process in goroutine go http.ListenAndServe("localhost:"+*port, peers) http.Handle("/", http.HandlerFunc(QR)) err := http.ListenAndServe(*addr, nil) if err != nil { log.Fatal("ListenAndServe:", err) } }
func main() { me := ":" + os.Args[1] peers := groupcache.NewHTTPPool("http://localhost" + me) peers.Set("http://localhost:8081", "http://localhost:8082", "http://localhost:8083") helloworld := groupcache.NewGroup("helloworld", 1024*1024*10, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { log.Println(me) dest.SetString(me + "->" + key) return nil })) fmt.Println("GroupName: ", helloworld.Name()) http.HandleFunc("/xbox/", func(w http.ResponseWriter, r *http.Request) { parts := strings.SplitN(r.URL.Path[len("/xbox/"):], "/", 1) for _, x := range parts { fmt.Println("get: ", x) } if len(parts) != 1 { http.Error(w, "Bad Request", http.StatusBadRequest) return } var data []byte helloworld.Get(nil, parts[0], groupcache.AllocatingByteSliceSink(&data)) w.Write(data) log.Println("Gets: ", helloworld.Stats.Gets.String()) log.Println("Load: ", helloworld.Stats.Loads.String()) log.Println("LocalLoad: ", helloworld.Stats.LocalLoads.String()) log.Println("PeerError: ", helloworld.Stats.PeerErrors.String()) log.Println("PeerLoad: ", helloworld.Stats.PeerLoads.String()) }) http.ListenAndServe(me, nil) }
// StartCache is used to start up the groupcache mechanism func (c *Constellation) StartCache() { log.Print("Starting AuthCache") var peers []string if c.PeerList == nil { log.Print("Initializing PeerList") c.PeerList = make(map[string]string) } for _, peer := range c.PeerList { log.Printf("Assigning peer '%s'", peer) if peer > "" { peers = append(peers, "http://"+peer+":"+GCPORT) } } c.Peers.Set(peers...) var authcache = groupcache.NewGroup(c.Groupname, 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { pod := key auth := c.GetAuthForPodFromConfig(pod) if auth > "" { dest.SetString(auth) return nil } err := fmt.Errorf("Found no value for auth on pod %s, not storing anything", pod) return err })) c.AuthCache = NewCache(authcache) }
func main() { /* me := "http://127.0.0.1" peers := groupcache.NewHTTPPool(me) // Whenever peers change: peers.Set("http://127.0.0.1", "http://10.0.0.2", "http://10.0.0.3")*/ getter := groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { // fileName := key bytes := []byte{'a', 'b', 'c'} dest.SetBytes(bytes) return nil }) func(g *igetter) Get(ctx Content, key string, dest Sink) { } grp := groupcache.NewGroup("Grp", 64<<20, getter) err := grp.Get(ctx groupcache.Context, key string, dest groupcache.Sink) //hook /* hook := groupcache.RegisterNewGroupHook(func(grp1 *groupcache.Group) { fmt.Println(grp1.Name()) fmt.Println("hook") })*/ fmt.Println(grp.Name()) fmt.Println(grp.Stats) }
func main() { flag.Parse() // Setup the doozer connection. d, err := doozer.Dial(daddr) if err != nil { log.Fatalf("connecting to doozer: %v\n", err) } defer d.Close() // Setup the cache. pool = groupcache.NewHTTPPool("http://" + addr) dict = groupcache.NewGroup("dict", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { def, err := query(key) if err != nil { err = fmt.Errorf("querying remote dictionary: %v", err) log.Println(err) return err } log.Println("retrieved remote definition for", key) dest.SetString(def) return nil })) // Start watching for changes and signals. go watch(d) // Add the handler for definition requests and then start the // server. http.Handle("/define/", http.HandlerFunc(handler)) log.Println(http.ListenAndServe(addr, nil)) }
func main() { // STARTINIT OMIT me := "http://10.0.0.1" peers := groupcache.NewHTTPPool(me) // Whenever peers change: peers.Set("http://10.0.0.1", "http://10.0.0.2", "http://10.0.0.3") // ENDINIT OMIT // STARTGROUP OMIT var thumbNails = groupcache.NewGroup("thumbnail", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { fileName := key dest.SetBytes(generateThumbnail(fileName)) return nil })) // ENDGROUP OMIT var ctx groupcache.Context var w http.ResponseWriter var r *http.Request // STARTUSE OMIT var data []byte err := thumbNails.Get(ctx, "big-file.jpg", groupcache.AllocatingByteSliceSink(&data)) // ... _ = err // OMIT var modTime time.Time // OMIT http.ServeContent(w, r, "big-file-thumb.jpg", modTime, bytes.NewReader(data)) // ENDUSE OMIT }
func (s *Server) initCache() { s.zoomedFloorCache = groupcache.GetGroup("zoomedImages") if s.zoomedFloorCache == nil { g := zoomedImageGetter{s} s.zoomedFloorCache = groupcache.NewGroup("zoomedImages", int64(256*units.MiB), g) } }
func (g *GGFetchHandler) Register(name string, fetcher Fetcher, size int64) { fmt.Println("Register", name, size) if g.methods == nil { g.methods = make(map[string]entry) } g.methods[name] = entry{ Group: groupcache.NewGroup(name, size, fetcherGetter{fetcher}), Fetcher: fetcher, } }
func InitRadosCache(name string, size int64, chunkSize int) { if cacheMade { panic("groupcache: InitRadosCache must be called only once") } cacheMade = true radosCache = groupcache.NewGroup(name, size, groupcache.GetterFunc(radosGetter)) chunkPool = sync.Pool{ New: func() interface{} { return make([]byte, chunkSize) }, } }
// NewGroupCache function func NewGroupCache(cacheSize int64, redisGetFunc GetFunc) Cache { return &groupCacheMgr{ group: gc.NewGroup(singleGroupName, cacheSize, gc.GetterFunc(func(ctx gc.Context, key string, dest gc.Sink) error { log.WithField("domain", key).Info("GroupCache:RedisRequest") redisRequest := api.NewValueRequest(key) redisGetFunc(redisRequest) redisResponse := <-redisRequest.Response log.WithField("domain", key).Info("GroupCache:RedisRequest:Done") return dest.SetString(redisResponse.Value) }))} }
func setupGroupcache(config GroupcacheConfig) error { if config.GB == 0 { return nil } var cacheBytes int64 cacheBytes = int64(config.GB) << 30 pool := groupcache.NewHTTPPool(config.Host) if pool != nil { dvid.Infof("Initializing groupcache with %d GB at %s...\n", config.GB, config.Host) manager.gcache.cache = groupcache.NewGroup("immutable", cacheBytes, groupcache.GetterFunc( func(c groupcache.Context, key string, dest groupcache.Sink) error { // Use KeyValueDB defined as context. gctx, ok := c.(GroupcacheCtx) if !ok { return fmt.Errorf("bad groupcache context: expected GroupcacheCtx, got %v", c) } // First four bytes of key is instance ID to isolate groupcache collisions. tk := TKey(key[4:]) data, err := gctx.KeyValueDB.Get(gctx.Context, tk) if err != nil { return err } return dest.SetBytes(data) })) manager.gcache.supported = make(map[dvid.DataSpecifier]struct{}) for _, dataspec := range config.Instances { name := strings.Trim(dataspec, "\"") parts := strings.Split(name, ":") switch len(parts) { case 2: dataid := dvid.GetDataSpecifier(dvid.InstanceName(parts[0]), dvid.UUID(parts[1])) manager.gcache.supported[dataid] = struct{}{} default: dvid.Errorf("bad data instance specification %q given for groupcache support in config file\n", dataspec) } } // If we have additional peers, add them and start a listener via the HTTP port. if len(config.Peers) > 0 { peers := []string{config.Host} peers = append(peers, config.Peers...) pool.Set(peers...) dvid.Infof("Groupcache configuration has %d peers in addition to local host.\n", len(config.Peers)) dvid.Infof("Starting groupcache HTTP server on %s\n", config.Host) http.ListenAndServe(config.Host, http.HandlerFunc(pool.ServeHTTP)) } } return nil }
func (g *GroupCacheProxy) MakeCache(c *Cluster, size int64) CacheGetter { return groupcache.NewGroup( "ReticulumCache", size, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { // get image from disk ri := NewImageSpecifier(key) img_data, err := c.RetrieveImage(ri) if err != nil { return err } dest.SetBytes([]byte(img_data)) return nil })) }
func main() { var err error p = groupcache.NewHTTPPool("http://127.0.0.1:50000") // update p's list p.Set("http://127.0.0.1:50001", "http://127.0.0.1:50002") // create a new group by name and set a function for get a value by key // if you g.Get KEY at first time, it will store the value use sink, run the function // if you g.Get KEY not at first time, actually it NOT entry the function // does not support update a key's value g = groupcache.NewGroup("dns", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) (err error) { if ctx == nil { ctx = "f**k" } log.Println(key, ctx) err = dest.SetString(ctx.(string)) return })) // let it listen go http.ListenAndServe("127.0.0.1:50000", nil) // get a key's value into data time.Sleep(2 * time.Second) var data []byte var key = "key" err = g.Get("aa", key, groupcache.AllocatingByteSliceSink(&data)) if err != nil { log.Println("get error:", err) } log.Println(string(data)) time.Sleep(2 * time.Second) key = "key1" err = g.Get("bb", key, groupcache.AllocatingByteSliceSink(&data)) if err != nil { log.Println("get error:", err) } log.Println(string(data)) time.Sleep(2 * time.Second) key = "key" err = g.Get("cc", key, groupcache.AllocatingByteSliceSink(&data)) if err != nil { log.Println("get error:", err) } log.Println(string(data)) }
func main() { runtime.GOMAXPROCS(runtime.NumCPU()) awsAuth, err := aws.EnvAuth() if err != nil { log.Fatalf(err.Error()) } s3conn := s3.New(awsAuth, getRegion()) storage = store.NewS3Store(s3conn) peers = peer.DebugPool() peers.SetContext(func(r *http.Request) groupcache.Context { return fetch.RequestContext(r) }) cache = groupcache.NewGroup("ImageProxyCache", 64<<20, groupcache.GetterFunc( func(c groupcache.Context, key string, dest groupcache.Sink) error { log.Printf("Cache MISS for key -> %s", key) // Get image data from S3 b, err := fetch.ImageData(storage, c) if err != nil { return err } return dest.SetBytes(b) })) if !*verbose { logwriter, err := syslog.Dial("udp", "app_syslog:514", syslog.LOG_NOTICE, "vip") if err != nil { log.Println(err.Error()) log.Println("using default logger") } else { log.SetOutput(logwriter) } } go peers.Listen() go listenHttp() go Queue.Start(4) log.Println("Cache listening on port :" + peers.Port()) s := &http.Server{ Addr: ":" + peers.Port(), Handler: peers, } s.ListenAndServe() }
func TestGetSetGC(t *testing.T) { tt := T{1} mcStorage := NewMcStorage([]string{"localhost:12000"}, "test", 0, reflect.TypeOf(&tt)) mcStorage.Set("1", tt) res, _ := mcStorage.Get("1") defer mcStorage.Delete("1") if reflect.TypeOf(res) != reflect.TypeOf(tt) { t.Error("res type is not T") } ttRes := res.(T) if ttRes.A != tt.A { t.Error("res A field is not equals tt field") } var groupcache = groupcache.NewGroup("SlowDBCache", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { result, err := mcStorage.Get(key) if err != nil { return nil } bytes, err := json.Marshal(result) if err != nil { return nil } dest.SetBytes(bytes) return nil })) gcStorage := &GroupCacheKvStorage{groupcache, 0, reflect.TypeOf(&tt)} res, _ = gcStorage.Get("1") if reflect.TypeOf(res) != reflect.TypeOf(tt) { t.Error("res type is not T") } ttRes = res.(T) if ttRes.A != tt.A { t.Error("res A field is not equals tt field") } mcStorage.Delete("1") res, _ = gcStorage.Get("1") if reflect.TypeOf(res) != reflect.TypeOf(tt) { t.Error("res type is not T") } ttRes = res.(T) if ttRes.A != tt.A { t.Error("res A field is not equals tt field") } }
func TestServerErrorImageUnmarshal(t *testing.T) { srv := &Server{ Group: groupcache.NewGroup( newTestServerName(), testSize, groupcache.GetterFunc(func(ctx groupcache.Context, key string, dest groupcache.Sink) error { dest.SetBytes(nil) return nil }), ), KeyGenerator: imageserver_cache.StringKeyGenerator("test"), } _, err := srv.Get(imageserver.Params{}) if err == nil { t.Fatal("no error") } }
func beChildForTestGRPCPool() { addrs := strings.Split(*peerAddrs, ",") server := grpc.NewServer() p := NewGRPCPool(addrs[*peerIndex], server) p.Set(addrs...) getter := groupcache.GetterFunc(func(ctx groupcache.Context, key string, dest groupcache.Sink) error { dest.SetString(strconv.Itoa(*peerIndex) + ":" + key) return nil }) groupcache.NewGroup("grpcPoolTest", 1<<20, getter) lis, err := net.Listen("tcp", addrs[*peerIndex]) if err != nil { log.Fatalf("Failed to listen on %s", addrs[*peerIndex]) } server.Serve(lis) }
func start() { pool = groupcache.NewHTTPPool("http://" + addr) dns = groupcache.NewGroup("dns", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { // Lookup the adddress based on the hostname (key). addrs, err := net.LookupHost(key) if err != nil { return err } // We'll just store the first. dest.SetString(addrs[0]) return nil })) // Run in the background so we can use the console. go http.ListenAndServe(addr, nil) }
func NewDimensionsCache() *DimensionsCache { g := groupcache.NewGroup("DimensionsCache", 64<<18, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { fmt.Printf("Calculating Dimensions for %s\n", key) u, err := url.Parse(key) if err != nil { return err } result := calculateDimensions(u) var buffer = bytes.Buffer{} binary.Write(&buffer, binary.BigEndian, result) dest.SetBytes(buffer.Bytes()) fmt.Println("Filled Cache") return nil })) dc := DimensionsCache{g} return &dc }
func initCacheGroup() { self := config.Get().CacheSelf() pool := groupcache.NewHTTPPool(self) pool.Set(config.Get().CachePeers()...) if self != "" { log.Println("Cache listen on:", strings.TrimLeft(self, "http://")) go http.ListenAndServe(strings.TrimLeft(self, "http://"), http.HandlerFunc(pool.ServeHTTP)) } cacheGroup = groupcache.NewGroup("imagio-storage", config.Get().CacheSize(), groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { dest.SetBytes(imgproc.Do( Construct(new(query.Options), key).(*query.Options), )) return nil }), ) }
func main() { flag.Set("logtostderr", "true") flag.Parse() me := ":8080" peers := groupcache.NewHTTPPool("http://localhost" + me) peers.Set("http://localhost:8081", "http://localhost:8082", "http://localhost:8083") helloworld := groupcache.NewGroup("helloworld", 1024*1024*1024*16, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { glog.Infof("%v, key = %v", me, key) dest.SetString(key) return nil })) glog.Infof("GroupName: %v", helloworld.Name()) http.HandleFunc("/xbox/", func(w http.ResponseWriter, r *http.Request) { parts := strings.SplitN(r.URL.Path[len("/xbox/"):], "/", 1) glog.Infof("parts: %v", parts) if len(parts) != 1 { http.Error(w, "Bad Request", http.StatusBadRequest) return } var data []byte helloworld.Get(nil, parts[0], groupcache.AllocatingByteSliceSink(&data)) w.Write(data) glog.Infof("data: %s", data) glog.Infof("Stats: %#v", helloworld.Stats) //glog.Infof("Gets: %v", helloworld.Stats.Gets.String()) //glog.Infof("Load: %v", helloworld.Stats.Loads.String()) //glog.Infof("LocalLoad: %v", helloworld.Stats.LocalLoads.String()) //glog.Infof("PeerError: %v", helloworld.Stats.PeerErrors.String()) //glog.Infof("PeerLoad: %v", helloworld.Stats.PeerLoads.String()) }) http.ListenAndServe(me, nil) }
func main() { if !flag.Parsed() { flag.Parse() } // etcd := os.Getenv("ETCD_ADDR") ip := os.Getenv("PUBLIC_HOSTIP") pport := os.Getenv("PUBLIC_PORT") cache := etcd_groupcache.New(fmt.Sprintf("http://%s:%s", ip, pport), nil, nil) peers := []string{fmt.Sprintf("http://%s:8080", ip), fmt.Sprintf("http://%s:8081", ip)} log.Infoln(peers) cache.Set(peers...) http.Handle("/_groupcache/", cache) var stringcache = groupcache.NewGroup("SlowDBCache", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { log.Infoln(pport) dest.SetString(key + "heyo") return nil })) go func() { var data []byte key := "some key" err := stringcache.Get(nil, key, groupcache.AllocatingByteSliceSink(&data)) if err != nil { log.Errorln(err) } log.Infoln(string(data)) }() log.Infoln("Groupcache Listening 8080") if err := http.ListenAndServe(":"+*port, nil); err != nil { panic(err) } }
func main() { // setup group stringGroup = gc.NewGroup(stringGroupName, cacheSize, gc.GetterFunc(func(_ gc.Context, key string, dest gc.Sink) error { fmt.Fprintf(os.Stdout, "Setting cache key: %s\n", key) return dest.SetString("ECHO:" + key) })) // Get Items for j := 0; j < 4; j++ { for i := 0; i < 4; i++ { var s string if err := stringGroup.Get(dummyCtx, "TestCaching-key"+strconv.Itoa(i), gc.StringSink(&s)); err != nil { fmt.Fprintf(os.Stdout, "TestCaching-key value: failed%s\n", err) return } fmt.Fprintf(os.Stdout, "TestCaching-key value:%s\n", s) } fmt.Fprintln(os.Stdout, "---") } fmt.Fprintln(os.Stdout, "Done.") }
func ServeDir(mountpoint string, target string, limit int, me string, peerlist []string) { peers := groupcache.NewHTTPPool(me) if peerlist != nil && len(peerlist) > 0 { peers.Set(peerlist...) } filecache = groupcache.NewGroup("filecache", int64(limit)<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { contents, err := ioutil.ReadFile(key) dest.SetBytes(contents) return err })) c, err := fuse.Mount(mountpoint) if err != nil { log.Fatal(err) } fs.Serve(c, TargetDir{target}) }
func main() { var port = flag.String("port", "8001", "groupcache port") flag.Parse() peers := groupcache.NewHTTPPool("http://localhost:" + *port) client := new(client.Client) var stringcache = groupcache.NewGroup("SlowDBCache", 64<<20, groupcache.GetterFunc( func(ctx groupcache.Context, key string, dest groupcache.Sink) error { result := client.Get(key) fmt.Printf("asking for %s from dbserver\n", key) dest.SetBytes([]byte(result)) return nil })) peers.Set("http://localhost:8001", "http://localhost:8002", "http://localhost:8003") frontendServer := NewServer(stringcache) i, err := strconv.Atoi(*port) if err != nil { // handle error fmt.Println(err) os.Exit(2) } var frontEndport = ":" + strconv.Itoa(i+1000) go frontendServer.Start(frontEndport) fmt.Println(stringcache) fmt.Println("cachegroup slave starting on " + *port) fmt.Println("frontend starting on " + frontEndport) http.ListenAndServe("127.0.0.1:"+*port, http.HandlerFunc(peers.ServeHTTP)) }
"github.com/golang/groupcache" "io/ioutil" "log" "net/http" ) func getter(ctx groupcache.Context, key string, dest groupcache.Sink) error { resp, _ := http.Get(key) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) log.Printf("asking for %s from solr\n", key) dest.SetString(string(body)) return nil } var stringcache = groupcache.NewGroup("Solr", 64<<20, groupcache.GetterFunc(getter)) func proxyHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") url := "http://moapi.com:8080" + r.URL.Path + "?" + r.URL.RawQuery var s string stringcache.Get(nil, url, groupcache.StringSink(&s)) fmt.Fprintf(w, s) } func startProxy() { log.Print("starting") handler := http.NewServeMux() handler.HandleFunc("/select/", proxyHandler) server := &http.Server{Addr: ":8889", Handler: handler}
// NewServer is a helper to create a new groupcache Server. func NewServer(srv imageserver.Server, kg imageserver_cache.KeyGenerator, name string, cacheBytes int64) *Server { return &Server{ Group: groupcache.NewGroup(name, cacheBytes, &Getter{Server: srv}), KeyGenerator: kg, } }