]> git.giacomolli.uk - onehouse/blob - driver/alamo/gateway.go
Share the Alamo gateway request budget
[onehouse] / driver / alamo / gateway.go
1 package alamo
2
3 import (
4 "context"
5 "fmt"
6 "time"
7 )
8
9 const (
10 gatewayRequestInterval = 6 * time.Second
11 gatewayExchangeTimeout = 5 * time.Second
12 )
13
14 type gateway struct {
15 client Client
16 nextStart time.Time
17 }
18
19 func (g *gateway) status(ctx context.Context) ([]State, error) {
20 err := g.wait(ctx)
21 if err != nil {
22 return nil, fmt.Errorf("wait for status slot: %w", err)
23 }
24
25 ctx, cancel := context.WithTimeout(ctx, gatewayExchangeTimeout)
26 defer cancel()
27
28 states, err := g.client.Status(ctx)
29 if err != nil {
30 return nil, fmt.Errorf("read gateway status: %w", err)
31 }
32
33 return states, nil
34 }
35
36 func (g *gateway) action(ctx context.Context, mac string, action Action) (State, error) {
37 err := g.wait(ctx)
38 if err != nil {
39 return State{}, fmt.Errorf("wait for action slot: %w", err)
40 }
41
42 ctx, cancel := context.WithTimeout(ctx, gatewayExchangeTimeout)
43 defer cancel()
44
45 state, err := g.client.Action(ctx, mac, action)
46 if err != nil {
47 return State{}, fmt.Errorf("exchange gateway action: %w", err)
48 }
49
50 return state, nil
51 }
52
53 func (g *gateway) wait(ctx context.Context) error {
54 err := ctx.Err()
55 if err != nil {
56 return err
57 }
58
59 delay := time.Until(g.nextStart)
60 if delay > 0 {
61 timer := time.NewTimer(delay)
62 defer timer.Stop()
63
64 select {
65 case <-ctx.Done():
66 return ctx.Err()
67 case <-timer.C:
68 }
69 }
70
71 err = ctx.Err()
72 if err != nil {
73 return err
74 }
75
76 g.nextStart = time.Now().Add(gatewayRequestInterval)
77
78 return nil
79 }