-
Notifications
You must be signed in to change notification settings - Fork 1
/
service.go
100 lines (88 loc) · 2.41 KB
/
service.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
package clong
import (
"context"
"fmt"
"log"
)
// ClientConnection is a connection with a client.
type ClientConnection interface {
WriteJSON(v any) error
Close() error
}
// Service is a messaging hub for events.
type Service interface {
RegisterScreen(screen ClientConnection)
UnregisterScreen(screen ClientConnection)
RegisterController(controller ClientConnection)
UnregisterController(controller ClientConnection)
PublishEvent(ctx context.Context, event Event)
PublishControl(ctx context.Context, ctrl Control)
}
// BaseService is a messaging hub.
type BaseService struct {
controllers map[ClientConnection]bool
screens map[ClientConnection]bool
scores ScoreStore
}
// NewService creates a new service.
func NewService(scores ScoreStore) *BaseService {
svc := BaseService{
controllers: make(map[ClientConnection]bool),
screens: make(map[ClientConnection]bool),
scores: scores,
}
return &svc
}
// RegisterController registers a new controller.
func (s *BaseService) RegisterController(c ClientConnection) {
s.controllers[c] = true
}
// UnregisterController removes a controller.
func (s *BaseService) UnregisterController(c ClientConnection) {
delete(s.controllers, c)
}
// RegisterScreen registers a new screen.
func (s *BaseService) RegisterScreen(c ClientConnection) {
s.screens[c] = true
}
// UnregisterScreen removes a screen.
func (s *BaseService) UnregisterScreen(c ClientConnection) {
delete(s.screens, c)
}
// PublishEvent publishes an event to the messaging bus.
func (s *BaseService) PublishEvent(_ context.Context, event Event) {
for c := range s.controllers {
err := c.WriteJSON(event)
if err != nil {
err = c.Close()
if err != nil {
log.Fatal(fmt.Errorf("error closing controller connection: %w", err))
}
s.UnregisterController(c)
}
}
}
// PublishControl publishes a control to the messaging bus.
func (s *BaseService) PublishControl(ctx context.Context, ctrl Control) {
if ctrl.Type == "GAME_FINISHED" {
scr := Score{
Player: ctrl.Player,
FinalScore: ctrl.FinalScore,
Color: ctrl.Color,
}
err := s.scores.Add(ctx, &scr)
if err != nil {
log.Fatal(fmt.Errorf("error adding score to store: %w", err))
}
}
for scrn := range s.screens {
err := scrn.WriteJSON(ctrl)
if err != nil {
err = scrn.Close()
if err != nil {
log.Fatal(fmt.Errorf("error closing screen connection: %w", err))
}
s.UnregisterScreen(scrn)
}
}
}