-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
decay.go
109 lines (93 loc) · 3.99 KB
/
decay.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package connmgr
import (
"io"
"time"
"github.com/libp2p/go-libp2p/core/peer"
)
// Decayer is implemented by connection managers supporting decaying tags. A
// decaying tag is one whose value automatically decays over time.
//
// The actual application of the decay behaviour is encapsulated in a
// user-provided decaying function (DecayFn). The function is called on every
// tick (determined by the interval parameter), and returns either the new value
// of the tag, or whether it should be erased altogether.
//
// We do not set values on a decaying tag. Rather, we "bump" decaying tags by a
// delta. This calls the BumpFn with the old value and the delta, to determine
// the new value.
//
// Such a pluggable design affords a great deal of flexibility and versatility.
// Behaviours that are straightforward to implement include:
//
// - Decay a tag by -1, or by half its current value, on every tick.
// - Every time a value is bumped, sum it to its current value.
// - Exponentially boost a score with every bump.
// - Sum the incoming score, but keep it within min, max bounds.
//
// Commonly used DecayFns and BumpFns are provided in this package.
type Decayer interface {
io.Closer
// RegisterDecayingTag creates and registers a new decaying tag, if and only
// if a tag with the supplied name doesn't exist yet. Otherwise, an error is
// returned.
//
// The caller provides the interval at which the tag is refreshed, as well
// as the decay function and the bump function. Refer to godocs on DecayFn
// and BumpFn for more info.
RegisterDecayingTag(name string, interval time.Duration, decayFn DecayFn, bumpFn BumpFn) (DecayingTag, error)
}
// DecayFn applies a decay to the peer's score. The implementation must call
// DecayFn at the interval supplied when registering the tag.
//
// It receives a copy of the decaying value, and returns the score after
// applying the decay, as well as a flag to signal if the tag should be erased.
type DecayFn func(value DecayingValue) (after int, rm bool)
// BumpFn applies a delta onto an existing score, and returns the new score.
//
// Non-trivial bump functions include exponential boosting, moving averages,
// ceilings, etc.
type BumpFn func(value DecayingValue, delta int) (after int)
// DecayingTag represents a decaying tag. The tag is a long-lived general
// object, used to operate on tag values for peers.
type DecayingTag interface {
// Name returns the name of the tag.
Name() string
// Interval is the effective interval at which this tag will tick. Upon
// registration, the desired interval may be overwritten depending on the
// decayer's resolution, and this method allows you to obtain the effective
// interval.
Interval() time.Duration
// Bump applies a delta to a tag value, calling its bump function. The bump
// will be applied asynchronously, and a non-nil error indicates a fault
// when queuing.
Bump(peer peer.ID, delta int) error
// Remove removes a decaying tag from a peer. The removal will be applied
// asynchronously, and a non-nil error indicates a fault when queuing.
Remove(peer peer.ID) error
// Close closes a decaying tag. The Decayer will stop tracking this tag,
// and the state of all peers in the Connection Manager holding this tag
// will be updated.
//
// The deletion is performed asynchronously.
//
// Once deleted, a tag should not be used, and further calls to Bump/Remove
// will error.
//
// Duplicate calls to Remove will not return errors, but a failure to queue
// the first actual removal, will (e.g. when the system is backlogged).
Close() error
}
// DecayingValue represents a value for a decaying tag.
type DecayingValue struct {
// Tag points to the tag this value belongs to.
Tag DecayingTag
// Peer is the peer ID to whom this value is associated.
Peer peer.ID
// Added is the timestamp when this value was added for the first time for
// a tag and a peer.
Added time.Time
// LastVisit is the timestamp of the last visit.
LastVisit time.Time
// Value is the current value of the tag.
Value int
}