open-consul/consul/coordinate_endpoint.go

85 lines
2.2 KiB
Go

package consul
import (
"time"
"github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/serf/coordinate"
)
type Coordinate struct {
srv *Server
}
var (
// We batch updates and send them together every 30 seconds, or every 1000 updates,
// whichever comes sooner
updatePeriod = time.Duration(30) * time.Second
updateBatchMaxSize = 1000
updateBuffer []*structs.CoordinateUpdateRequest
updateLastSent time.Time
)
func init() {
updateBuffer = nil
updateLastSent = time.Now()
}
// Get returns the the LAN coordinate of a node.
func (c *Coordinate) GetLAN(args *structs.NodeSpecificRequest, reply *structs.IndexedCoordinate) error {
if done, err := c.srv.forward("Coordinate.GetLAN", args, args, reply); done {
return err
}
state := c.srv.fsm.State()
return c.srv.blockingRPC(&args.QueryOptions,
&reply.QueryMeta,
state.QueryTables("Coordinates"),
func() error {
idx, coord, err := state.CoordinateGet(args.Node)
reply.Index = idx
reply.Coord = coord.Coord
return err
})
}
// Get returns the the WAN coordinate of a datacenter.
func (c *Coordinate) GetWAN(args *structs.DCSpecificRequest, reply *coordinate.Coordinate) error {
if args.Datacenter == c.srv.config.Datacenter {
*reply = *c.srv.GetWANCoordinate()
} else {
servers := c.srv.remoteConsuls[args.Datacenter] // servers in the specified DC
for i := 0; i < len(servers); i++ {
if coord := c.srv.serfWAN.GetCachedCoordinate(servers[i].Name); coord != nil {
*reply = *coord
}
}
}
return nil
}
// Update updates the the LAN coordinate of a node.
func (c *Coordinate) Update(args *structs.CoordinateUpdateRequest, reply *struct{}) error {
if done, err := c.srv.forward("Coordinate.Update", args, args, reply); done {
return err
}
updateBuffer = append(updateBuffer, args)
if time.Since(updateLastSent) > updatePeriod || len(updateBuffer) > updateBatchMaxSize {
_, err := c.srv.raftApply(structs.CoordinateRequestType, updateBuffer)
// We clear the buffer regardless of whether the raft transaction succeeded, just so the
// buffer doesn't keep growing without bound.
updateBuffer = nil
updateLastSent = time.Now()
if err != nil {
c.srv.logger.Printf("[ERR] consul.coordinate: Update failed: %v", err)
return err
}
}
return nil
}