in swim/ping_sender.go [61:122]
func sendPingWithChanges(node *Node, target string, changes []Change, timeout time.Duration) (*ping, error) {
req := ping{
Checksum: node.memberlist.Checksum(),
Changes: changes,
Source: node.Address(),
SourceIncarnation: node.Incarnation(),
App: node.app,
}
node.EmitEvent(PingSendEvent{
Local: node.Address(),
Remote: target,
Changes: req.Changes,
})
logging.Logger("ping").WithFields(log.Fields{
"local": node.Address(),
"remote": target,
"changes": req.Changes,
}).Debug("ping send")
ctx, cancel := shared.NewTChannelContext(timeout)
defer cancel()
peer := node.channel.Peers().GetOrAdd(target)
startTime := time.Now()
// send the ping
errC := make(chan error, 1)
res := &ping{}
go func() {
errC <- json.CallPeer(ctx, peer, node.service, "/protocol/ping", req, res)
}()
// get result or timeout
var err error
select {
case err = <-errC:
case <-ctx.Done():
err = errors.New("ping timed out")
}
if err != nil {
// ping failed
logging.Logger("ping").WithFields(log.Fields{
"local": node.Address(),
"remote": target,
"error": err,
}).Debug("ping failed")
return nil, err
}
node.EmitEvent(PingSendCompleteEvent{
Local: node.Address(),
Remote: target,
Changes: req.Changes,
Duration: time.Now().Sub(startTime),
})
return res, err
}