-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
132 lines (124 loc) · 3.52 KB
/
server.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package api
import (
"fmt"
jsoniter "github.com/json-iterator/go"
"github.com/safe-area/sa-storage/internal/models"
"github.com/safe-area/sa-storage/internal/service"
"github.com/sirupsen/logrus"
"github.com/uber/h3-go"
"github.com/valyala/fasthttp"
"github.com/valyala/fasthttprouter"
"strconv"
"time"
)
type Server struct {
r *fasthttprouter.Router
serv *fasthttp.Server
svc service.Service
port string
}
func New(svc service.Service, port string) *Server {
innerRouter := fasthttprouter.New()
innerHandler := innerRouter.Handler
s := &Server{
innerRouter,
&fasthttp.Server{
ReadTimeout: time.Duration(10) * time.Second,
WriteTimeout: time.Duration(10) * time.Second,
IdleTimeout: time.Duration(10) * time.Second,
Handler: innerHandler,
},
svc,
port,
}
s.r.GET("/api/v1/get", s.GetHandler)
s.r.POST("/api/v1/put", s.PutHandler)
return s
}
func (s *Server) GetHandler(ctx *fasthttp.RequestCtx, ps fasthttprouter.Params) {
body := ctx.PostBody()
var req models.GetRequest
err := jsoniter.Unmarshal(body, &req)
if err != nil {
logrus.Errorf("GetHandler: error while unmarshalling request: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
tsStr := string(ctx.QueryArgs().Peek("ts"))
var resp map[h3.H3Index]models.HexData
if tsStr == "" {
resp = s.svc.GetLast(req.Indexes)
} else {
var ts int64
ts, err = strconv.ParseInt(tsStr, 10, 64)
if err != nil {
logrus.Errorf("GetHandler: ts query arg must be integer number or empty: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
resp = s.svc.GetWithTimestamp(req.Indexes, ts)
}
var bs []byte
bs, err = jsoniter.Marshal(resp)
if err != nil {
logrus.Errorf("GetHandler: error while unmarshalling request: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
ctx.Write(bs)
ctx.SetContentType("application/json")
ctx.SetStatusCode(fasthttp.StatusOK)
}
func (s *Server) PutHandler(ctx *fasthttp.RequestCtx, ps fasthttprouter.Params) {
body := ctx.PostBody()
var reqs []models.PutRequest
err := jsoniter.Unmarshal(body, &reqs)
if err != nil {
logrus.Errorf("PutHandler: error while unmarshalling request: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
for _, req := range reqs {
switch {
case req.Action == models.IncInfected:
err = s.svc.IncInfected(req.Index, req.Timestamp)
if err != nil {
logrus.Errorf("PutHandler: IncInfected error: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
case req.Action == models.DecInfected:
err = s.svc.DecInfected(req.Index, req.Timestamp)
if err != nil {
logrus.Errorf("PutHandler: DecInfected error: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
case req.Action == models.IncHealthy:
err = s.svc.IncHealthy(req.Index, req.Timestamp)
if err != nil {
logrus.Errorf("PutHandler: IncHealthy error: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
case req.Action == models.DecHealthy:
err = s.svc.DecHealthy(req.Index, req.Timestamp)
if err != nil {
logrus.Errorf("PutHandler: DecHealthy error: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
default:
logrus.Errorf("PutHandler: invalid action code: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
}
ctx.SetStatusCode(fasthttp.StatusOK)
}
func (s *Server) Start() error {
return fmt.Errorf("server start: %s", s.serv.ListenAndServe(s.port))
}
func (s *Server) Shutdown() error {
return s.serv.Shutdown()
}