yao/agent/robot/cache/refresh.go
Max 1bddac44a4 refactor(robot): rename ListRobots to ListAllRobots and enhance caching logic
- Renamed ListRobots function to ListAllRobots for clarity and consistency across the codebase.
- Updated related API endpoints and tests to reflect the new function name.
- Improved caching logic to ensure both autonomous and non-autonomous robots are loaded correctly.
- Enhanced filtering and pagination capabilities within the ListAllRobots function.
- Added new test cases to validate the updated functionality and ensure robust performance.
2026-03-23 12:25:17 +08:00

150 lines
3.1 KiB
Go

package cache
import (
"sync"
"time"
"github.com/yaoapp/yao/agent/robot/types"
)
// RefreshConfig holds refresh configuration
type RefreshConfig struct {
Interval time.Duration // full refresh interval (default: 1 hour)
}
// DefaultRefreshConfig returns default refresh configuration
func DefaultRefreshConfig() *RefreshConfig {
return &RefreshConfig{
Interval: time.Hour,
}
}
// refreshState holds the refresh goroutine state
type refreshState struct {
ticker *time.Ticker
done chan struct{}
mu sync.Mutex
}
var refresher = &refreshState{}
// Refresh refreshes a single robot's config from database
func (c *Cache) Refresh(ctx *types.Context, memberID string) error {
robot, err := c.LoadByID(ctx, memberID)
if err != nil {
// If robot not found, remove from cache
if err == types.ErrRobotNotFound {
c.Remove(memberID)
return nil
}
return err
}
// Update cache
c.Add(robot)
return nil
}
// StartAutoRefresh starts periodic full refresh
func (c *Cache) StartAutoRefresh(ctx *types.Context, config *RefreshConfig) {
if config == nil {
config = DefaultRefreshConfig()
}
refresher.mu.Lock()
defer refresher.mu.Unlock()
// Stop existing refresher if any
if refresher.done != nil {
close(refresher.done)
}
refresher.ticker = time.NewTicker(config.Interval)
refresher.done = make(chan struct{})
go func() {
for {
select {
case <-refresher.done:
refresher.ticker.Stop()
return
case <-refresher.ticker.C:
// Perform full refresh
_ = c.Load(ctx)
}
}
}()
}
// StopAutoRefresh stops the periodic refresh
func (c *Cache) StopAutoRefresh() {
refresher.mu.Lock()
defer refresher.mu.Unlock()
if refresher.done != nil {
close(refresher.done)
refresher.done = nil
}
}
// RefreshAll reloads all robots from database
func (c *Cache) RefreshAll(ctx *types.Context) error {
return c.Load(ctx)
}
// Count returns the number of cached robots
func (c *Cache) Count() int {
c.mu.RLock()
defer c.mu.RUnlock()
return len(c.robots)
}
// ListAll returns all cached robots (across all teams)
func (c *Cache) ListAll() []*types.Robot {
c.mu.RLock()
defer c.mu.RUnlock()
robots := make([]*types.Robot, 0, len(c.robots))
for _, robot := range c.robots {
robots = append(robots, robot)
}
return robots
}
// ListAutonomous returns all cached robots with AutonomousMode=true.
func (c *Cache) ListAutonomous() []*types.Robot {
c.mu.RLock()
defer c.mu.RUnlock()
robots := make([]*types.Robot, 0, len(c.robots)/2)
for _, r := range c.robots {
if r.AutonomousMode {
robots = append(robots, r)
}
}
return robots
}
// GetByStatus returns robots with the specified status
func (c *Cache) GetByStatus(status types.RobotStatus) []*types.Robot {
c.mu.RLock()
defer c.mu.RUnlock()
var robots []*types.Robot
for _, robot := range c.robots {
if robot.Status == status {
robots = append(robots, robot)
}
}
return robots
}
// GetIdle returns all idle robots ready to execute
func (c *Cache) GetIdle() []*types.Robot {
return c.GetByStatus(types.RobotIdle)
}
// GetWorking returns all currently working robots
func (c *Cache) GetWorking() []*types.Robot {
return c.GetByStatus(types.RobotWorking)
}