201 lines
3.9 KiB
Go
201 lines
3.9 KiB
Go
package switchcounter
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"path"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/celrenheit/sandflake"
|
|
r "gopkg.in/rethinkdb/rethinkdb-go.v6"
|
|
"within.website/ln"
|
|
)
|
|
|
|
func (s *Switches) ByID(ctx context.Context, id string) (*Switch, error) {
|
|
var result Switch
|
|
res, err := r.Table("switches").
|
|
Get(id).
|
|
Run(s.session)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = res.One(&result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &result, nil
|
|
}
|
|
|
|
func (s *Switches) Get(ctx context.Context, limit, page int) ([]Switch, error) {
|
|
var result []Switch
|
|
res, err := r.Table("switches").
|
|
OrderBy(r.Desc("started_at")).
|
|
Skip(page * limit).
|
|
Limit(limit).
|
|
Run(s.session)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = res.All(&result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (s *Switches) Switch(ctx context.Context, who string) (Switch, Switch, error) {
|
|
var lastSw Switch
|
|
var currentSw Switch
|
|
|
|
ln.Log(ctx, ln.Info("getting last switch"))
|
|
res, err := r.Table("switches").
|
|
OrderBy(r.Desc("started_at")).
|
|
Limit(1).
|
|
Run(s.session)
|
|
if err != nil {
|
|
return lastSw, currentSw, err
|
|
}
|
|
|
|
err = res.One(&lastSw)
|
|
if err != nil {
|
|
return lastSw, currentSw, err
|
|
}
|
|
|
|
f := ln.F{
|
|
"from": lastSw.Who,
|
|
"to": who,
|
|
}
|
|
ln.Log(ctx, f, ln.Info("got last switch"))
|
|
|
|
now := time.Now().UTC()
|
|
lastSw.EndedAt = &now
|
|
lastSw.Duration = now.Sub(lastSw.StartedAt).Round(time.Second)
|
|
err = r.Table("switches").
|
|
Update(lastSw).
|
|
Exec(s.session)
|
|
if err != nil {
|
|
return lastSw, currentSw, err
|
|
}
|
|
|
|
currentSw = Switch{
|
|
ID: sandflake.Next().String(),
|
|
Who: who,
|
|
StartedAt: now,
|
|
}
|
|
|
|
err = r.Table("switches").
|
|
Insert(currentSw).
|
|
Exec(s.session)
|
|
if err != nil {
|
|
return lastSw, currentSw, err
|
|
}
|
|
|
|
ln.Log(ctx, f, ln.Info("switched"))
|
|
|
|
return lastSw, currentSw, nil
|
|
}
|
|
|
|
func (s *Switches) GetID(rw http.ResponseWriter, req *http.Request) {
|
|
id := path.Base(req.URL.Path)
|
|
sw, err := s.ByID(req.Context(), id)
|
|
if err != nil {
|
|
ln.Error(req.Context(), err)
|
|
http.Error(rw, "can't get data", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
json.NewEncoder(rw).Encode(sw)
|
|
}
|
|
|
|
func (s *Switches) Current(rw http.ResponseWriter, req *http.Request) {
|
|
var result Switch
|
|
res, err := r.Table("switches").
|
|
OrderBy(r.Desc("started_at")).
|
|
Limit(1).
|
|
Run(s.session)
|
|
if err != nil {
|
|
ln.Error(req.Context(), err)
|
|
http.Error(rw, "can't get data", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
err = res.One(&result)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
switch req.Header.Get("Accept") {
|
|
case "text/plain":
|
|
http.Error(rw, result.Who, http.StatusOK)
|
|
return
|
|
default:
|
|
json.NewEncoder(rw).Encode(result)
|
|
}
|
|
}
|
|
|
|
func (s *Switches) GetSwitches(rw http.ResponseWriter, req *http.Request) {
|
|
var (
|
|
limit = 40
|
|
page = 0
|
|
)
|
|
q := req.URL.Query()
|
|
|
|
if val := q.Get("limit"); val != "" {
|
|
i, err := strconv.Atoi(val)
|
|
if err != nil {
|
|
http.Error(rw, "limit is bad: "+err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
limit = i
|
|
}
|
|
|
|
if val := q.Get("page"); val != "" {
|
|
i, err := strconv.Atoi(val)
|
|
if err != nil {
|
|
http.Error(rw, "page is bad: "+err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
page = i
|
|
}
|
|
|
|
switches, err := s.Get(req.Context(), limit, page)
|
|
if err != nil {
|
|
ln.Error(req.Context(), err)
|
|
http.Error(rw, "can't get data", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
json.NewEncoder(rw).Encode(switches)
|
|
}
|
|
|
|
func (s *Switches) RegisterSwitch(rw http.ResponseWriter, req *http.Request) {
|
|
who, err := ioutil.ReadAll(req.Body)
|
|
defer req.Body.Close()
|
|
if err != nil {
|
|
http.Error(rw, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
last, current, err := s.Switch(req.Context(), string(who))
|
|
if err != nil {
|
|
ln.Error(req.Context(), err)
|
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
json.NewEncoder(rw).Encode(struct {
|
|
Last Switch `json:"last"`
|
|
Current Switch `json:"current"`
|
|
}{
|
|
Last: last,
|
|
Current: current,
|
|
})
|
|
}
|