Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
356
vendor/github.com/libp2p/go-libp2p/p2p/net/connmgr/decay.go
generated
vendored
Normal file
356
vendor/github.com/libp2p/go-libp2p/p2p/net/connmgr/decay.go
generated
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
package connmgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/libp2p/go-libp2p/core/connmgr"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
|
||||
"github.com/benbjohnson/clock"
|
||||
)
|
||||
|
||||
// DefaultResolution is the default resolution of the decay tracker.
|
||||
var DefaultResolution = 1 * time.Minute
|
||||
|
||||
// bumpCmd represents a bump command.
|
||||
type bumpCmd struct {
|
||||
peer peer.ID
|
||||
tag *decayingTag
|
||||
delta int
|
||||
}
|
||||
|
||||
// removeCmd represents a tag removal command.
|
||||
type removeCmd struct {
|
||||
peer peer.ID
|
||||
tag *decayingTag
|
||||
}
|
||||
|
||||
// decayer tracks and manages all decaying tags and their values.
|
||||
type decayer struct {
|
||||
cfg *DecayerCfg
|
||||
mgr *BasicConnMgr
|
||||
clock clock.Clock // for testing.
|
||||
|
||||
tagsMu sync.Mutex
|
||||
knownTags map[string]*decayingTag
|
||||
|
||||
// lastTick stores the last time the decayer ticked. Guarded by atomic.
|
||||
lastTick atomic.Pointer[time.Time]
|
||||
|
||||
// bumpTagCh queues bump commands to be processed by the loop.
|
||||
bumpTagCh chan bumpCmd
|
||||
removeTagCh chan removeCmd
|
||||
closeTagCh chan *decayingTag
|
||||
|
||||
// closure thingies.
|
||||
closeCh chan struct{}
|
||||
doneCh chan struct{}
|
||||
err error
|
||||
}
|
||||
|
||||
var _ connmgr.Decayer = (*decayer)(nil)
|
||||
|
||||
// DecayerCfg is the configuration object for the Decayer.
|
||||
type DecayerCfg struct {
|
||||
Resolution time.Duration
|
||||
Clock clock.Clock
|
||||
}
|
||||
|
||||
// WithDefaults writes the default values on this DecayerConfig instance,
|
||||
// and returns itself for chainability.
|
||||
//
|
||||
// cfg := (&DecayerCfg{}).WithDefaults()
|
||||
// cfg.Resolution = 30 * time.Second
|
||||
// t := NewDecayer(cfg, cm)
|
||||
func (cfg *DecayerCfg) WithDefaults() *DecayerCfg {
|
||||
cfg.Resolution = DefaultResolution
|
||||
return cfg
|
||||
}
|
||||
|
||||
// NewDecayer creates a new decaying tag registry.
|
||||
func NewDecayer(cfg *DecayerCfg, mgr *BasicConnMgr) (*decayer, error) {
|
||||
// use real time if the Clock in the config is nil.
|
||||
if cfg.Clock == nil {
|
||||
cfg.Clock = clock.New()
|
||||
}
|
||||
|
||||
d := &decayer{
|
||||
cfg: cfg,
|
||||
mgr: mgr,
|
||||
clock: cfg.Clock,
|
||||
knownTags: make(map[string]*decayingTag),
|
||||
bumpTagCh: make(chan bumpCmd, 128),
|
||||
removeTagCh: make(chan removeCmd, 128),
|
||||
closeTagCh: make(chan *decayingTag, 128),
|
||||
closeCh: make(chan struct{}),
|
||||
doneCh: make(chan struct{}),
|
||||
}
|
||||
|
||||
now := d.clock.Now()
|
||||
d.lastTick.Store(&now)
|
||||
|
||||
// kick things off.
|
||||
go d.process()
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *decayer) RegisterDecayingTag(name string, interval time.Duration, decayFn connmgr.DecayFn, bumpFn connmgr.BumpFn) (connmgr.DecayingTag, error) {
|
||||
d.tagsMu.Lock()
|
||||
defer d.tagsMu.Unlock()
|
||||
|
||||
if _, ok := d.knownTags[name]; ok {
|
||||
return nil, fmt.Errorf("decaying tag with name %s already exists", name)
|
||||
}
|
||||
|
||||
if interval < d.cfg.Resolution {
|
||||
log.Warnf("decay interval for %s (%s) was lower than tracker's resolution (%s); overridden to resolution",
|
||||
name, interval, d.cfg.Resolution)
|
||||
interval = d.cfg.Resolution
|
||||
}
|
||||
|
||||
if interval%d.cfg.Resolution != 0 {
|
||||
log.Warnf("decay interval for tag %s (%s) is not a multiple of tracker's resolution (%s); "+
|
||||
"some precision may be lost", name, interval, d.cfg.Resolution)
|
||||
}
|
||||
|
||||
lastTick := d.lastTick.Load()
|
||||
tag := &decayingTag{
|
||||
trkr: d,
|
||||
name: name,
|
||||
interval: interval,
|
||||
nextTick: lastTick.Add(interval),
|
||||
decayFn: decayFn,
|
||||
bumpFn: bumpFn,
|
||||
}
|
||||
|
||||
d.knownTags[name] = tag
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
// Close closes the Decayer. It is idempotent.
|
||||
func (d *decayer) Close() error {
|
||||
select {
|
||||
case <-d.doneCh:
|
||||
return d.err
|
||||
default:
|
||||
}
|
||||
|
||||
close(d.closeCh)
|
||||
<-d.doneCh
|
||||
return d.err
|
||||
}
|
||||
|
||||
// process is the heart of the tracker. It performs the following duties:
|
||||
//
|
||||
// 1. Manages decay.
|
||||
// 2. Applies score bumps.
|
||||
// 3. Yields when closed.
|
||||
func (d *decayer) process() {
|
||||
defer close(d.doneCh)
|
||||
|
||||
ticker := d.clock.Ticker(d.cfg.Resolution)
|
||||
defer ticker.Stop()
|
||||
|
||||
var (
|
||||
bmp bumpCmd
|
||||
visit = make(map[*decayingTag]struct{})
|
||||
)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
now := d.clock.Now()
|
||||
d.lastTick.Store(&now)
|
||||
|
||||
d.tagsMu.Lock()
|
||||
for _, tag := range d.knownTags {
|
||||
if tag.nextTick.After(now) {
|
||||
// skip the tag.
|
||||
continue
|
||||
}
|
||||
// Mark the tag to be updated in this round.
|
||||
visit[tag] = struct{}{}
|
||||
}
|
||||
d.tagsMu.Unlock()
|
||||
|
||||
// Visit each peer, and decay tags that need to be decayed.
|
||||
for _, s := range d.mgr.segments.buckets {
|
||||
s.Lock()
|
||||
|
||||
// Entered a segment that contains peers. Process each peer.
|
||||
for _, p := range s.peers {
|
||||
for tag, v := range p.decaying {
|
||||
if _, ok := visit[tag]; !ok {
|
||||
// skip this tag.
|
||||
continue
|
||||
}
|
||||
|
||||
// ~ this value needs to be visited. ~
|
||||
var delta int
|
||||
if after, rm := tag.decayFn(*v); rm {
|
||||
// delete the value and move on to the next tag.
|
||||
delta -= v.Value
|
||||
delete(p.decaying, tag)
|
||||
} else {
|
||||
// accumulate the delta, and apply the changes.
|
||||
delta += after - v.Value
|
||||
v.Value, v.LastVisit = after, now
|
||||
}
|
||||
p.value += delta
|
||||
}
|
||||
}
|
||||
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
// Reset each tag's next visit round, and clear the visited set.
|
||||
for tag := range visit {
|
||||
tag.nextTick = tag.nextTick.Add(tag.interval)
|
||||
delete(visit, tag)
|
||||
}
|
||||
|
||||
case bmp = <-d.bumpTagCh:
|
||||
var (
|
||||
now = d.clock.Now()
|
||||
peer, tag = bmp.peer, bmp.tag
|
||||
)
|
||||
|
||||
s := d.mgr.segments.get(peer)
|
||||
s.Lock()
|
||||
|
||||
p := s.tagInfoFor(peer, d.clock.Now())
|
||||
v, ok := p.decaying[tag]
|
||||
if !ok {
|
||||
v = &connmgr.DecayingValue{
|
||||
Tag: tag,
|
||||
Peer: peer,
|
||||
LastVisit: now,
|
||||
Added: now,
|
||||
Value: 0,
|
||||
}
|
||||
p.decaying[tag] = v
|
||||
}
|
||||
|
||||
prev := v.Value
|
||||
v.Value, v.LastVisit = v.Tag.(*decayingTag).bumpFn(*v, bmp.delta), now
|
||||
p.value += v.Value - prev
|
||||
|
||||
s.Unlock()
|
||||
|
||||
case rm := <-d.removeTagCh:
|
||||
s := d.mgr.segments.get(rm.peer)
|
||||
s.Lock()
|
||||
|
||||
p := s.tagInfoFor(rm.peer, d.clock.Now())
|
||||
v, ok := p.decaying[rm.tag]
|
||||
if !ok {
|
||||
s.Unlock()
|
||||
continue
|
||||
}
|
||||
p.value -= v.Value
|
||||
delete(p.decaying, rm.tag)
|
||||
s.Unlock()
|
||||
|
||||
case t := <-d.closeTagCh:
|
||||
// Stop tracking the tag.
|
||||
d.tagsMu.Lock()
|
||||
delete(d.knownTags, t.name)
|
||||
d.tagsMu.Unlock()
|
||||
|
||||
// Remove the tag from all peers that had it in the connmgr.
|
||||
for _, s := range d.mgr.segments.buckets {
|
||||
// visit all segments, and attempt to remove the tag from all the peers it stores.
|
||||
s.Lock()
|
||||
for _, p := range s.peers {
|
||||
if dt, ok := p.decaying[t]; ok {
|
||||
// decrease the value of the tagInfo, and delete the tag.
|
||||
p.value -= dt.Value
|
||||
delete(p.decaying, t)
|
||||
}
|
||||
}
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
case <-d.closeCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// decayingTag represents a decaying tag, with an associated decay interval, a
|
||||
// decay function, and a bump function.
|
||||
type decayingTag struct {
|
||||
trkr *decayer
|
||||
name string
|
||||
interval time.Duration
|
||||
nextTick time.Time
|
||||
decayFn connmgr.DecayFn
|
||||
bumpFn connmgr.BumpFn
|
||||
|
||||
// closed marks this tag as closed, so that if it's bumped after being
|
||||
// closed, we can return an error.
|
||||
closed atomic.Bool
|
||||
}
|
||||
|
||||
var _ connmgr.DecayingTag = (*decayingTag)(nil)
|
||||
|
||||
func (t *decayingTag) Name() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
func (t *decayingTag) Interval() time.Duration {
|
||||
return t.interval
|
||||
}
|
||||
|
||||
// Bump bumps a tag for this peer.
|
||||
func (t *decayingTag) Bump(p peer.ID, delta int) error {
|
||||
if t.closed.Load() {
|
||||
return fmt.Errorf("decaying tag %s had been closed; no further bumps are accepted", t.name)
|
||||
}
|
||||
|
||||
bmp := bumpCmd{peer: p, tag: t, delta: delta}
|
||||
|
||||
select {
|
||||
case t.trkr.bumpTagCh <- bmp:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
"unable to bump decaying tag for peer %s, tag %s, delta %d; queue full (len=%d)",
|
||||
p, t.name, delta, len(t.trkr.bumpTagCh))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *decayingTag) Remove(p peer.ID) error {
|
||||
if t.closed.Load() {
|
||||
return fmt.Errorf("decaying tag %s had been closed; no further removals are accepted", t.name)
|
||||
}
|
||||
|
||||
rm := removeCmd{peer: p, tag: t}
|
||||
|
||||
select {
|
||||
case t.trkr.removeTagCh <- rm:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
"unable to remove decaying tag for peer %s, tag %s; queue full (len=%d)",
|
||||
p, t.name, len(t.trkr.removeTagCh))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *decayingTag) Close() error {
|
||||
if !t.closed.CompareAndSwap(false, true) {
|
||||
log.Warnf("duplicate decaying tag closure: %s; skipping", t.name)
|
||||
return nil
|
||||
}
|
||||
|
||||
select {
|
||||
case t.trkr.closeTagCh <- t:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unable to close decaying tag %s; queue full (len=%d)", t.name, len(t.trkr.closeTagCh))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user