| package session |
| |
| import ( |
| "context" |
| "time" |
| |
| "github.com/pkg/errors" |
| ) |
| |
| type Group interface { |
| SessionIterator() Iterator |
| } |
| type Iterator interface { |
| NextSession() string |
| } |
| |
| func NewGroup(ids ...string) Group { |
| return &group{ids: ids} |
| } |
| |
| type group struct { |
| ids []string |
| } |
| |
| func (g *group) SessionIterator() Iterator { |
| return &group{ids: g.ids} |
| } |
| |
| func (g *group) NextSession() string { |
| if len(g.ids) == 0 { |
| return "" |
| } |
| v := g.ids[0] |
| g.ids = g.ids[1:] |
| return v |
| } |
| |
| func AllSessionIDs(g Group) (out []string) { |
| if g == nil { |
| return nil |
| } |
| it := g.SessionIterator() |
| if it == nil { |
| return nil |
| } |
| for { |
| v := it.NextSession() |
| if v == "" { |
| return |
| } |
| out = append(out, v) |
| } |
| } |
| |
| func (sm *Manager) Any(ctx context.Context, g Group, f func(context.Context, string, Caller) error) error { |
| if g == nil { |
| return nil |
| } |
| |
| iter := g.SessionIterator() |
| if iter == nil { |
| return nil |
| } |
| |
| var lastErr error |
| for { |
| id := iter.NextSession() |
| if id == "" { |
| if lastErr != nil { |
| return lastErr |
| } |
| return errors.Errorf("no active sessions") |
| } |
| |
| timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second) |
| defer cancel() |
| c, err := sm.Get(timeoutCtx, id) |
| if err != nil { |
| lastErr = err |
| continue |
| } |
| if err := f(ctx, id, c); err != nil { |
| lastErr = err |
| continue |
| } |
| return nil |
| } |
| } |