diff --git a/cmd/cheesegull-api/main.go b/cmd/cheesegull-api/main.go index 2b2e59f595fa56d9cd09cbffefe4e2e52a5adf51..0cb4049df847f5be392b7d53b89d622208244eda 100644 --- a/cmd/cheesegull-api/main.go +++ b/cmd/cheesegull-api/main.go @@ -113,6 +113,7 @@ func execute(c *cli.Context) error { Communication: red, APISecret: sec, FileResolver: fileresolvers.FileSystem{}, + Logging: red, }) fmt.Println("Listening on", port) diff --git a/http/api/beatmap.go b/http/api/beatmap.go index 54a65f147898b6af81cc24e104e18932c893dcea..f577e0fce55996c7fb43aaefe669a9e0aa552aaa 100644 --- a/http/api/beatmap.go +++ b/http/api/beatmap.go @@ -24,7 +24,19 @@ func RequestBeatmap(w http.ResponseWriter, r *http.Request, c *ctx.Context) { return } - err := c.Communication.SendBeatmapRequest(i) + l5m, err := c.Logging.UpdateInLast5Minutes(i) + if err != nil { + c.HandleError(err) + j(w, 200, aec) + return + } + if l5m { + resp.Message = "that beatmap was already requested in the last 5 minutes!" + j(w, 200, resp) + return + } + + err = c.Communication.SendBeatmapRequest(i) if err != nil { c.HandleError(err) j(w, 500, aec) diff --git a/http/ctx/context.go b/http/ctx/context.go index 5691fba3dc78e04b0382b45002292aa4b0260af1..aa0627a76d434f0ef16e6a021f349780874aa993 100644 --- a/http/ctx/context.go +++ b/http/ctx/context.go @@ -17,6 +17,7 @@ type Context struct { BeatmapService cheesegull.BeatmapService FileResolver cheesegull.FileResolver Communication cheesegull.CommunicationService + Logging cheesegull.Logging ErrorHandler func(error) Request *http.Request } diff --git a/http/server.go b/http/server.go index 9cf6d0337c23aa523b72ef931ce8749972678a41..64152669c5592f46f6795552ec1d887ed08d02db 100644 --- a/http/server.go +++ b/http/server.go @@ -18,6 +18,7 @@ type Options struct { BeatmapService cheesegull.BeatmapService FileResolver cheesegull.FileResolver Communication cheesegull.CommunicationService + Logging cheesegull.Logging APISecret string } @@ -74,6 +75,7 @@ func (o Options) req(a func(w http.ResponseWriter, r *http.Request, c *ctx.Conte BeatmapService: o.BeatmapService, FileResolver: o.FileResolver, Communication: o.Communication, + Logging: o.Logging, Request: r, }) fmt.Printf("%v | %-12v %-4s %-15s\n", start.Format("2006-01-02 15:04:05"), diff --git a/providers/redis/new.go b/providers/redis/new.go index 37fbb054e579dbe6af5e987852ee8ac0cbc30ea3..382d1f2ac65c8eb41b0c84a6fa03608d8b97c586 100644 --- a/providers/redis/new.go +++ b/providers/redis/new.go @@ -9,6 +9,7 @@ import ( type Provided interface { cheesegull.CommunicationService cheesegull.SystemService + cheesegull.Logging } type impl struct { diff --git a/providers/redis/system.go b/providers/redis/system.go index a71844c5faa40e43864c3a437caccd725d685694..3f77c6f1b76d1b0d210b41d92501b390395adf8e 100644 --- a/providers/redis/system.go +++ b/providers/redis/system.go @@ -1,5 +1,10 @@ package redis +import ( + "fmt" + "time" +) + func (i *impl) GetSecurityKey(def string) string { k := i.Get("system:security_key").Val() if k == "" { @@ -8,3 +13,14 @@ func (i *impl) GetSecurityKey(def string) string { } return k } + +func (i *impl) UpdateInLast5Minutes(b int) (bool, error) { + v := i.Exists(fmt.Sprintf("updates:5m:%d", b)) + if v.Err() != nil { + return false, v.Err() + } + if !v.Val() { + i.Set(fmt.Sprintf("updates:5m:%d", b), nil, time.Minute*5) + } + return v.Val(), nil +} diff --git a/system.go b/system.go index 1f065b18a8813049d0f9c6afeabc88939335fd9a..83a47645f4f84bf97e62667cd9101b7579970d62 100644 --- a/system.go +++ b/system.go @@ -9,3 +9,11 @@ type SystemService interface { // the one currently stored does not exist. GetSecurityKey(def string) string } + +// Logging is a service that logs in a database certain information. +type Logging interface { + // UpdateInLast5Minutes checks whether a beatmap (i) was requested an update + // in the previous 5 minutes, and if it wasn't it records the update being + // requested. + UpdateInLast5Minutes(i int) (bool, error) +}