WIP: Save agent roles integration work before CHORUS rebrand
- Agent roles and coordination features - Chat API integration testing - New configuration and workspace management 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
30
vendor/github.com/libp2p/go-flow-metrics/.travis.yml
generated
vendored
Normal file
30
vendor/github.com/libp2p/go-flow-metrics/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
os:
|
||||
- linux
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.17.x
|
||||
|
||||
env:
|
||||
global:
|
||||
- GOTFLAGS="-race"
|
||||
matrix:
|
||||
- BUILD_DEPTYPE=gomod
|
||||
|
||||
|
||||
# disable travis install
|
||||
install:
|
||||
- true
|
||||
|
||||
script:
|
||||
- bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh)
|
||||
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $GOPATH/pkg/mod
|
||||
- $HOME/.cache/go-build
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
21
vendor/github.com/libp2p/go-flow-metrics/LICENSE
generated
vendored
Normal file
21
vendor/github.com/libp2p/go-flow-metrics/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Protocol Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
41
vendor/github.com/libp2p/go-flow-metrics/README.md
generated
vendored
Normal file
41
vendor/github.com/libp2p/go-flow-metrics/README.md
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
go-flow-metrics
|
||||
==================
|
||||
|
||||
[](https://protocol.ai)
|
||||
[](http://webchat.freenode.net/?channels=%23libp2p)
|
||||
[](https://libp2p.io/)
|
||||
[](https://travis-ci.org/libp2p/go-flow-metrics)
|
||||
[](https://discuss.libp2p.io)
|
||||
|
||||
|
||||
> A simple library for tracking flow metrics.
|
||||
|
||||
A simple alternative to [rcrowley's
|
||||
go-metrics](https://github.com/rcrowley/go-metrics) that's a lot faster (and
|
||||
only does simple bandwidth metrics).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
make install
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
PRs are welcome!
|
||||
|
||||
Small note: If editing the Readme, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
MIT © Protocol Labs
|
||||
|
||||
---
|
||||
|
||||
The last gx published version of this module was: 0.2.0: QmQFXpvKpF34dK9HcE7k8Ksk8V4BwWYZtdEcjzu5aUgRVr
|
||||
71
vendor/github.com/libp2p/go-flow-metrics/meter.go
generated
vendored
Normal file
71
vendor/github.com/libp2p/go-flow-metrics/meter.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
package flow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Snapshot is a rate/total snapshot.
|
||||
type Snapshot struct {
|
||||
Rate float64
|
||||
Total uint64
|
||||
LastUpdate time.Time
|
||||
}
|
||||
|
||||
// NewMeter returns a new Meter with the correct idle time.
|
||||
//
|
||||
// While zero-value Meters can be used, their "last update" time will start at
|
||||
// the program start instead of when the meter was created.
|
||||
func NewMeter() *Meter {
|
||||
return &Meter{
|
||||
snapshot: Snapshot{
|
||||
LastUpdate: time.Now(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s Snapshot) String() string {
|
||||
return fmt.Sprintf("%d (%f/s)", s.Total, s.Rate)
|
||||
}
|
||||
|
||||
// Meter is a meter for monitoring a flow.
|
||||
type Meter struct {
|
||||
accumulator uint64
|
||||
|
||||
// managed by the sweeper loop.
|
||||
registered bool
|
||||
|
||||
// Take lock.
|
||||
snapshot Snapshot
|
||||
}
|
||||
|
||||
// Mark updates the total.
|
||||
func (m *Meter) Mark(count uint64) {
|
||||
if count > 0 && atomic.AddUint64(&m.accumulator, count) == count {
|
||||
// The accumulator is 0 so we probably need to register. We may
|
||||
// already _be_ registered however, if we are, the registration
|
||||
// loop will notice that `m.registered` is set and ignore us.
|
||||
globalSweeper.Register(m)
|
||||
}
|
||||
}
|
||||
|
||||
// Snapshot gets a snapshot of the total and rate.
|
||||
func (m *Meter) Snapshot() Snapshot {
|
||||
globalSweeper.snapshotMu.RLock()
|
||||
defer globalSweeper.snapshotMu.RUnlock()
|
||||
return m.snapshot
|
||||
}
|
||||
|
||||
// Reset sets accumulator, total and rate to zero.
|
||||
func (m *Meter) Reset() {
|
||||
globalSweeper.snapshotMu.Lock()
|
||||
atomic.StoreUint64(&m.accumulator, 0)
|
||||
m.snapshot.Rate = 0
|
||||
m.snapshot.Total = 0
|
||||
globalSweeper.snapshotMu.Unlock()
|
||||
}
|
||||
|
||||
func (m *Meter) String() string {
|
||||
return m.Snapshot().String()
|
||||
}
|
||||
82
vendor/github.com/libp2p/go-flow-metrics/registry.go
generated
vendored
Normal file
82
vendor/github.com/libp2p/go-flow-metrics/registry.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package flow
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MeterRegistry is a registry for named meters.
|
||||
type MeterRegistry struct {
|
||||
meters sync.Map
|
||||
}
|
||||
|
||||
// Get gets (or creates) a meter by name.
|
||||
func (r *MeterRegistry) Get(name string) *Meter {
|
||||
if m, ok := r.meters.Load(name); ok {
|
||||
return m.(*Meter)
|
||||
}
|
||||
m, _ := r.meters.LoadOrStore(name, NewMeter())
|
||||
return m.(*Meter)
|
||||
}
|
||||
|
||||
// FindIdle finds all meters that haven't been used since the given time.
|
||||
func (r *MeterRegistry) FindIdle(since time.Time) []string {
|
||||
var idle []string
|
||||
r.walkIdle(since, func(key interface{}) {
|
||||
idle = append(idle, key.(string))
|
||||
})
|
||||
return idle
|
||||
}
|
||||
|
||||
// TrimIdle trims that haven't been updated since the given time. Returns the
|
||||
// number of timers trimmed.
|
||||
func (r *MeterRegistry) TrimIdle(since time.Time) (trimmed int) {
|
||||
// keep these as interfaces to avoid allocating when calling delete.
|
||||
var idle []interface{}
|
||||
r.walkIdle(since, func(key interface{}) {
|
||||
idle = append(idle, since)
|
||||
})
|
||||
for _, i := range idle {
|
||||
r.meters.Delete(i)
|
||||
}
|
||||
return len(idle)
|
||||
}
|
||||
|
||||
func (r *MeterRegistry) walkIdle(since time.Time, cb func(key interface{})) {
|
||||
// Yes, this is a global lock. However, all taking this does is pause
|
||||
// snapshotting.
|
||||
globalSweeper.snapshotMu.RLock()
|
||||
defer globalSweeper.snapshotMu.RUnlock()
|
||||
|
||||
r.meters.Range(func(k, v interface{}) bool {
|
||||
// So, this _is_ slightly inaccurate.
|
||||
if v.(*Meter).snapshot.LastUpdate.Before(since) {
|
||||
cb(k)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// Remove removes the named meter from the registry.
|
||||
//
|
||||
// Note: The only reason to do this is to save a bit of memory. Unused meters
|
||||
// don't consume any CPU (after they go idle).
|
||||
func (r *MeterRegistry) Remove(name string) {
|
||||
r.meters.Delete(name)
|
||||
}
|
||||
|
||||
// ForEach calls the passed function for each registered meter.
|
||||
func (r *MeterRegistry) ForEach(iterFunc func(string, *Meter)) {
|
||||
r.meters.Range(func(k, v interface{}) bool {
|
||||
iterFunc(k.(string), v.(*Meter))
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// Clear removes all meters from the registry.
|
||||
func (r *MeterRegistry) Clear() {
|
||||
r.meters.Range(func(k, v interface{}) bool {
|
||||
r.meters.Delete(k)
|
||||
return true
|
||||
})
|
||||
}
|
||||
191
vendor/github.com/libp2p/go-flow-metrics/sweeper.go
generated
vendored
Normal file
191
vendor/github.com/libp2p/go-flow-metrics/sweeper.go
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
package flow
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/benbjohnson/clock"
|
||||
)
|
||||
|
||||
// IdleRate the rate at which we declare a meter idle (and stop tracking it
|
||||
// until it's re-registered).
|
||||
//
|
||||
// The default ensures that 1 event every ~30s will keep the meter from going
|
||||
// idle.
|
||||
var IdleRate = 1e-13
|
||||
|
||||
// Alpha for EWMA of 1s
|
||||
var alpha = 1 - math.Exp(-1.0)
|
||||
|
||||
// The global sweeper.
|
||||
var globalSweeper sweeper
|
||||
|
||||
var cl = clock.New()
|
||||
|
||||
// SetClock sets a clock to use in the sweeper.
|
||||
// This will probably only ever be useful for testing purposes.
|
||||
func SetClock(c clock.Clock) {
|
||||
cl = c
|
||||
}
|
||||
|
||||
type sweeper struct {
|
||||
sweepOnce sync.Once
|
||||
|
||||
snapshotMu sync.RWMutex
|
||||
meters []*Meter
|
||||
activeMeters int
|
||||
|
||||
lastUpdateTime time.Time
|
||||
registerChannel chan *Meter
|
||||
}
|
||||
|
||||
func (sw *sweeper) start() {
|
||||
sw.registerChannel = make(chan *Meter, 16)
|
||||
go sw.run()
|
||||
}
|
||||
|
||||
func (sw *sweeper) run() {
|
||||
for m := range sw.registerChannel {
|
||||
sw.register(m)
|
||||
sw.runActive()
|
||||
}
|
||||
}
|
||||
|
||||
func (sw *sweeper) register(m *Meter) {
|
||||
if m.registered {
|
||||
// registered twice, move on.
|
||||
return
|
||||
}
|
||||
m.registered = true
|
||||
sw.meters = append(sw.meters, m)
|
||||
}
|
||||
|
||||
func (sw *sweeper) runActive() {
|
||||
ticker := cl.Ticker(time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
sw.lastUpdateTime = cl.Now()
|
||||
for len(sw.meters) > 0 {
|
||||
// Scale back allocation.
|
||||
if len(sw.meters)*2 < cap(sw.meters) {
|
||||
newMeters := make([]*Meter, len(sw.meters))
|
||||
copy(newMeters, sw.meters)
|
||||
sw.meters = newMeters
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ticker.C:
|
||||
sw.update()
|
||||
case m := <-sw.registerChannel:
|
||||
sw.register(m)
|
||||
}
|
||||
}
|
||||
sw.meters = nil
|
||||
// Till next time.
|
||||
}
|
||||
|
||||
func (sw *sweeper) update() {
|
||||
sw.snapshotMu.Lock()
|
||||
defer sw.snapshotMu.Unlock()
|
||||
|
||||
now := cl.Now()
|
||||
tdiff := now.Sub(sw.lastUpdateTime)
|
||||
if tdiff <= 0 {
|
||||
return
|
||||
}
|
||||
sw.lastUpdateTime = now
|
||||
timeMultiplier := float64(time.Second) / float64(tdiff)
|
||||
|
||||
// Calculate the bandwidth for all active meters.
|
||||
for i, m := range sw.meters[:sw.activeMeters] {
|
||||
total := atomic.LoadUint64(&m.accumulator)
|
||||
diff := total - m.snapshot.Total
|
||||
instant := timeMultiplier * float64(diff)
|
||||
|
||||
if diff > 0 {
|
||||
m.snapshot.LastUpdate = now
|
||||
}
|
||||
|
||||
if m.snapshot.Rate == 0 {
|
||||
m.snapshot.Rate = instant
|
||||
} else {
|
||||
m.snapshot.Rate += alpha * (instant - m.snapshot.Rate)
|
||||
}
|
||||
m.snapshot.Total = total
|
||||
|
||||
// This is equivalent to one zeros, then one, then 30 zeros.
|
||||
// We'll consider that to be "idle".
|
||||
if m.snapshot.Rate > IdleRate {
|
||||
continue
|
||||
}
|
||||
|
||||
// Ok, so we are idle...
|
||||
|
||||
// Mark this as idle by zeroing the accumulator.
|
||||
swappedTotal := atomic.SwapUint64(&m.accumulator, 0)
|
||||
|
||||
// So..., are we really idle?
|
||||
if swappedTotal > total {
|
||||
// Not so idle...
|
||||
// Now we need to make sure this gets re-registered.
|
||||
|
||||
// First, add back what we removed. If we can do this
|
||||
// fast enough, we can put it back before anyone
|
||||
// notices.
|
||||
currentTotal := atomic.AddUint64(&m.accumulator, swappedTotal)
|
||||
|
||||
// Did we make it?
|
||||
if currentTotal == swappedTotal {
|
||||
// Yes! Nobody noticed, move along.
|
||||
continue
|
||||
}
|
||||
// No. Someone noticed and will (or has) put back into
|
||||
// the registration channel.
|
||||
//
|
||||
// Remove the snapshot total, it'll get added back on
|
||||
// registration.
|
||||
//
|
||||
// `^uint64(total - 1)` is the two's complement of
|
||||
// `total`. It's the "correct" way to subtract
|
||||
// atomically in go.
|
||||
atomic.AddUint64(&m.accumulator, ^uint64(m.snapshot.Total-1))
|
||||
}
|
||||
|
||||
// Reset the rate, keep the total.
|
||||
m.registered = false
|
||||
m.snapshot.Rate = 0
|
||||
sw.meters[i] = nil
|
||||
}
|
||||
|
||||
// Re-add the total to all the newly active accumulators and set the snapshot to the total.
|
||||
// 1. We don't do this on register to avoid having to take the snapshot lock.
|
||||
// 2. We skip calculating the bandwidth for this round so we get an _accurate_ bandwidth calculation.
|
||||
for _, m := range sw.meters[sw.activeMeters:] {
|
||||
total := atomic.AddUint64(&m.accumulator, m.snapshot.Total)
|
||||
if total > m.snapshot.Total {
|
||||
m.snapshot.LastUpdate = now
|
||||
}
|
||||
m.snapshot.Total = total
|
||||
}
|
||||
|
||||
// compress and trim the meter list
|
||||
var newLen int
|
||||
for _, m := range sw.meters {
|
||||
if m != nil {
|
||||
sw.meters[newLen] = m
|
||||
newLen++
|
||||
}
|
||||
}
|
||||
|
||||
sw.meters = sw.meters[:newLen]
|
||||
|
||||
// Finally, mark all meters still in the list as "active".
|
||||
sw.activeMeters = len(sw.meters)
|
||||
}
|
||||
|
||||
func (sw *sweeper) Register(m *Meter) {
|
||||
sw.sweepOnce.Do(sw.start)
|
||||
sw.registerChannel <- m
|
||||
}
|
||||
Reference in New Issue
Block a user