decay.go 3.99 KB
Newer Older
1 2 3 4 5 6
package connmgr

import (
	"io"
	"time"

tavit ohanian's avatar
tavit ohanian committed
7
	"gitlab.dms3.io/p2p/go-p2p-core/peer"
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
)

// 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
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
Raúl Kripalani's avatar
Raúl Kripalani committed
70 71
	// will be applied asynchronously, and a non-nil error indicates a fault
	// when queuing.
72
	Bump(peer peer.ID, delta int) error
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

	// 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
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
}

// 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
}