decay.go 3.37 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
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.
Raúl Kripalani's avatar
Raúl Kripalani committed
23
// Behaviours that are straightforward to implement include:
24 25 26 27 28 29
//
//  * 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.
//
Raúl Kripalani's avatar
Raúl Kripalani committed
30
// Commonly used DecayFns and BumpFns are provided in this package.
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
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
	// may be applied asynchronously, in which case the returned error is used
	// to indicate an anomaly when queuing.
	Bump(peer peer.ID, delta int) 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
}