package alamo import ( "context" "fmt" "time" ) const ( gatewayRequestInterval = 6 * time.Second gatewayExchangeTimeout = 5 * time.Second ) type gateway struct { client Client nextStart time.Time } func (g *gateway) status(ctx context.Context) ([]State, error) { err := g.wait(ctx) if err != nil { return nil, fmt.Errorf("wait for status slot: %w", err) } ctx, cancel := context.WithTimeout(ctx, gatewayExchangeTimeout) defer cancel() states, err := g.client.Status(ctx) if err != nil { return nil, fmt.Errorf("read gateway status: %w", err) } return states, nil } func (g *gateway) action(ctx context.Context, mac string, action Action) (State, error) { err := g.wait(ctx) if err != nil { return State{}, fmt.Errorf("wait for action slot: %w", err) } ctx, cancel := context.WithTimeout(ctx, gatewayExchangeTimeout) defer cancel() state, err := g.client.Action(ctx, mac, action) if err != nil { return State{}, fmt.Errorf("exchange gateway action: %w", err) } return state, nil } func (g *gateway) wait(ctx context.Context) error { err := ctx.Err() if err != nil { return err } delay := time.Until(g.nextStart) if delay > 0 { timer := time.NewTimer(delay) defer timer.Stop() select { case <-ctx.Done(): return ctx.Err() case <-timer.C: } } err = ctx.Err() if err != nil { return err } g.nextStart = time.Now().Add(gatewayRequestInterval) return nil }