/
realtime.go
111 lines (92 loc) · 2.86 KB
/
realtime.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package resource
import (
"github.com/gbl08ma/sqalx"
"github.com/underlx/disturbancesmlx/types"
"github.com/yarf-framework/yarf"
)
// RealtimeStatsHandler handles real-time network statistics such as the number of users in transit
type RealtimeStatsHandler interface {
RegisterActivity(lines []*types.Line, user *types.APIPair, justEntered bool)
}
// RealtimeVehicleHandler handles real-time vehicle information such as the position of trains in a network
type RealtimeVehicleHandler interface {
RegisterTrainPassenger(currentStation *types.Station, direction *types.Station)
}
// Realtime composites resource, handles real-time location submissions
type Realtime struct {
resource
statsHandler RealtimeStatsHandler
vehicleHandler RealtimeVehicleHandler
}
// WithNode associates a sqalx Node with this resource
func (r *Realtime) WithNode(node sqalx.Node) *Realtime {
r.node = node
return r
}
// WithHashKey associates a HMAC key with this resource so it can participate in authentication processes
func (r *Realtime) WithHashKey(key []byte) *Realtime {
r.hashKey = key
return r
}
// WithStatsHandler associates a RealtimeStatsHandler with this resource
func (r *Realtime) WithStatsHandler(handler RealtimeStatsHandler) *Realtime {
r.statsHandler = handler
return r
}
// WithVehicleHandler associates a RealtimeVehicleHandler with this resource
func (r *Realtime) WithVehicleHandler(handler RealtimeVehicleHandler) *Realtime {
r.vehicleHandler = handler
return r
}
// msgpack and json field names are very small to optimize bandwidth usage
// (in the subway network, the connection is certainly spotty)
type apiRealtimeLocation struct {
StationID string `msgpack:"s" json:"s"`
// DirectionID may be missing/empty if the user just entered the network
DirectionID string `msgpack:"d" json:"d"`
Submitter *types.APIPair `msgpack:"-" json:"-"`
}
// Post serves HTTP POST requests on this resource
func (r *Realtime) Post(c *yarf.Context) error {
tx, err := r.Beginx()
if err != nil {
return err
}
defer tx.Commit() // read-only tx
pair, err := r.AuthenticateClient(c)
if err != nil {
RenderUnauthorized(c)
return nil
}
var request apiRealtimeLocation
err = r.DecodeRequest(c, &request)
if err != nil {
return err
}
request.Submitter = pair
station, err := types.GetStation(tx, request.StationID)
if err != nil {
return err
}
lines, err := station.Lines(tx)
if err != nil {
return err
}
if r.statsHandler != nil {
if request.DirectionID == "" {
r.statsHandler.RegisterActivity(lines, request.Submitter, true)
} else {
r.statsHandler.RegisterActivity(lines, request.Submitter, false)
}
}
if r.vehicleHandler != nil {
if request.DirectionID != "" {
direction, err := types.GetStation(tx, request.DirectionID)
if err != nil {
return err
}
r.vehicleHandler.RegisterTrainPassenger(station, direction)
}
}
return nil
}