dialqueue.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. // Copyright (C) 2021 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package connections
  7. import (
  8. "sort"
  9. "time"
  10. "github.com/syncthing/syncthing/lib/protocol"
  11. "github.com/syncthing/syncthing/lib/rand"
  12. )
  13. type dialQueueEntry struct {
  14. id protocol.DeviceID
  15. lastSeen time.Time
  16. shortLived bool
  17. targets []dialTarget
  18. }
  19. type dialQueue []dialQueueEntry
  20. func (queue dialQueue) Sort() {
  21. // Sort the queue with the most recently seen device at the head,
  22. // increasing the likelihood of connecting to a device that we're
  23. // already almost up to date with, index wise.
  24. sort.Slice(queue, func(a, b int) bool {
  25. qa, qb := queue[a], queue[b]
  26. if qa.shortLived != qb.shortLived {
  27. return qb.shortLived
  28. }
  29. return qa.lastSeen.After(qb.lastSeen)
  30. })
  31. // Shuffle the part of the connection queue that are devices we haven't
  32. // connected to recently, so that if we only try a limited set of
  33. // devices (or they in turn have limits and we're trying to load balance
  34. // over several) and the usual ones are down it won't be the same ones
  35. // in the same order every time.
  36. idx := 0
  37. cutoff := time.Now().Add(-recentlySeenCutoff)
  38. for idx < len(queue) {
  39. if queue[idx].lastSeen.Before(cutoff) {
  40. break
  41. }
  42. idx++
  43. }
  44. if idx < len(queue)-1 {
  45. rand.Shuffle(queue[idx:])
  46. }
  47. }