func (ac *Autocache) NotifyJoin(node *memberlist.Node) {
	uri := ac.groupcacheURL(node.Addr.String())
	ac.removePeer(uri)
	ac.peers = append(ac.peers, uri)
	if ac.GroupcachePool != nil {
		ac.GroupcachePool.Set(ac.peers...)
		ac.logger.Printf("Autocache/NotifyJoin: %s peers: %v", uri, len(ac.peers))
	}
}
NotifyJoin is invoked when a node is detected to have joined.
The Node argument must not be modified. Implements memberlist's
EventDelegate's interface.
package autocache  
import (
	"context"
	"errors"
	"fmt"
	"log"
	"net/http"
	"os"
	"github.com/golang/groupcache"
	"github.com/hashicorp/memberlist"
)
var _ memberlist.EventDelegate = &Autocache{}
type Options struct {
	PoolOptions *groupcache.HTTPPoolOptions
	PoolScheme  string
	PoolPort    int
	PoolTransportFn func(context.Context) http.RoundTripper
	PoolContext func(*http.Request) context.Context
	MemberlistConfig *memberlist.Config
	Logger *log.Logger
}
type Autocache struct {
	GroupcachePool *groupcache.HTTPPool
	Memberlist     *memberlist.Memberlist
	self   string
	peers  []string
	scheme string
	port   string
	logger *log.Logger
}
func New(o *Options) (*Autocache, error) {
	var err error
	ac := Autocache{
		scheme: o.PoolScheme,
		port:   fmt.Sprintf("%d", o.PoolPort),
		logger: o.Logger,
	}
	if ac.logger == nil {
		ac.logger = log.New(os.Stderr, "", log.LstdFlags)
	}
	ac.logger.Printf("autocache: with options: %+v", o)
	if ac.scheme == "" {
		ac.logger.Printf("autocache: pool scheme not set, assuming http://")
		ac.scheme = "http"
	}
	if ac.port == "0" {
		ac.logger.Printf("autocache: pool port not set, assuming empty")
		ac.port = ""
	}
	mlConfig := o.MemberlistConfig
	if mlConfig == nil {
		ac.logger.Println("autocache: defaulting to lan configuration")
		mlConfig = memberlist.DefaultLANConfig()
	}
	mlConfig.Events = &ac
	mlConfig.Logger = ac.logger
	if ac.Memberlist, err = memberlist.Create(mlConfig); err != nil {
		return nil, fmt.Errorf("autocache: can't create memberlist: %w", err)
	}
	if len(ac.Memberlist.Members()) == 0 {
		return nil, errors.New("memberlist can't find self")
	}
	self := ac.Memberlist.Members()[0]
	if self.Addr == nil {
		return nil, errors.New("self addr cannot be nil")
	}
	ac.self = self.Addr.String()
	ac.logger.Printf("autocache: self addr is: %s", ac.self)
	poolOptions := &groupcache.HTTPPoolOptions{}
	if o.PoolOptions != nil {
		poolOptions = o.PoolOptions
	}
	gcSelf := ac.groupcacheURL(ac.self)
	ac.logger.Printf("autocache: groupcache self: %s options: %+v", gcSelf, poolOptions)
	ac.GroupcachePool = groupcache.NewHTTPPoolOpts(gcSelf, poolOptions)
	if o.PoolTransportFn != nil {
		ac.GroupcachePool.Transport = o.PoolTransportFn
	}
	if o.PoolContext != nil {
		ac.GroupcachePool.Context = o.PoolContext
	}
	return &ac, nil
}
func (ac *Autocache) Join(existing []string) (int, error) {
	if ac.Memberlist == nil {
		return 0, errors.New("memberlist cannot be nil")
	}
	existing = append(existing, ac.self)
	return ac.Memberlist.Join(existing)
}
func (ac *Autocache) groupcacheURL(addr string) string {
	u := fmt.Sprintf("%s://%s", ac.scheme, addr)
	if ac.port != "" {
		u = fmt.Sprintf("%s:%s", u, ac.port)
	}
	return u
}