diff --git a/lib/connections/service.go b/lib/connections/service.go index 39fa4b803..092b35db5 100644 --- a/lib/connections/service.go +++ b/lib/connections/service.go @@ -36,6 +36,8 @@ var ( listeners = make(map[string]listenerFactory, 0) ) +const perDeviceWarningRate = 1.0 / (15 * 60) // Once per 15 minutes + // Service listens and dials all configured unconnected devices, via supported // dialers. Successful connections are handed to the model. type Service struct { @@ -158,7 +160,8 @@ next: if protocol.IsVersionMismatch(err) { // The error will be a relatively user friendly description // of what's wrong with the version compatibility - l.Warnf("Connecting to %s (%s): %s", remoteID, c.RemoteAddr(), err) + msg := fmt.Sprintf("Connecting to %s (%s): %s", remoteID, c.RemoteAddr(), err) + warningFor(remoteID, msg) } else { // It's something else - connection reset or whatever l.Infof("Failed to exchange Hello messages with %s (%s): %s", remoteID, c.RemoteAddr(), err) @@ -588,3 +591,19 @@ func urlsToStrings(urls []*url.URL) []string { } return strings } + +var warningLimiters = make(map[protocol.DeviceID]*ratelimit.Bucket) +var warningLimitersMut = sync.NewMutex() + +func warningFor(dev protocol.DeviceID, msg string) { + warningLimitersMut.Lock() + defer warningLimitersMut.Unlock() + lim, ok := warningLimiters[dev] + if !ok { + lim = ratelimit.NewBucketWithRate(perDeviceWarningRate, 1) + warningLimiters[dev] = lim + } + if lim.TakeAvailable(1) == 1 { + l.Warnln(msg) + } +}