refactor getValue for new filter/limit structs
All checks were successful
Go / build (1.22) (push) Successful in 1m16s
Go / build (1.21) (push) Successful in 1m13s

This commit is contained in:
saji 2024-03-01 21:15:51 -06:00
parent 3f1df06d1b
commit 70e7f0f15d
2 changed files with 50 additions and 35 deletions

View file

@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"time"
"log/slog" "log/slog"
@ -189,32 +188,25 @@ func apiV1GetValues(db *db.TelemDb) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
var err error var err error
bef, err := extractBusEventFilter(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
lim, err := extractLimitModifier(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// we need a start and end time. If none is provided, // we need a start and end time. If none is provided,
// we use unix epoch as start, and now + 1 day as end. // we use unix epoch as start, and now + 1 day as end.
start := time.Unix(0, 0)
startString := r.URL.Query().Get("start")
if startString != "" {
start, err = time.Parse(time.RFC3339, startString)
if err != nil {
http.Error(w, "error getting values", http.StatusInternalServerError)
return
}
}
end := time.Now().Add(1 * time.Hour)
endParam := r.URL.Query().Get("start")
if endParam != "" {
end, err = time.Parse(time.RFC3339, endParam)
if err != nil {
http.Error(w, "error getting values", http.StatusInternalServerError)
return
}
}
name := chi.URLParam(r, "name") name := chi.URLParam(r, "name")
field := chi.URLParam(r, "field") field := chi.URLParam(r, "field")
// TODO: add limit and pagination // override the bus event filter name option
bef.Names = []string{name}
res, err := db.GetValues(r.Context(), name, field, start, end) res, err := db.GetValues(r.Context(), *bef, field, lim)
if err != nil { if err != nil {
// 500 server error: // 500 server error:
http.Error(w, "error getting values", http.StatusInternalServerError) http.Error(w, "error getting values", http.StatusInternalServerError)

View file

@ -2,6 +2,7 @@ package db
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -88,9 +89,9 @@ func (tdb *TelemDb) GetPackets(ctx context.Context, filter BusEventFilter, optio
return nil, err return nil, err
} }
BusEv := skylab.BusEvent { BusEv := skylab.BusEvent{
Timestamp: time.UnixMilli(int64(ev.Timestamp)), Timestamp: time.UnixMilli(int64(ev.Timestamp)),
Name: ev.Name, Name: ev.Name,
} }
BusEv.Data, err = skylab.FromJson(ev.Name, ev.Data) BusEv.Data, err = skylab.FromJson(ev.Name, ev.Data)
if err != nil { if err != nil {
@ -104,7 +105,6 @@ func (tdb *TelemDb) GetPackets(ctx context.Context, filter BusEventFilter, optio
return events, err return events, err
} }
// We now need a different use-case: we would like to extract a value from // We now need a different use-case: we would like to extract a value from
// a specific packet. // a specific packet.
@ -118,17 +118,37 @@ type Datum struct {
// GetValues queries the database for values in a given time range. // GetValues queries the database for values in a given time range.
// A value is a specific data point. For example, bms_measurement.current // A value is a specific data point. For example, bms_measurement.current
// would be a value. // would be a value.
func (tdb *TelemDb) GetValues(ctx context.Context, packetName, field string, start time.Time, func (tdb *TelemDb) GetValues(ctx context.Context, bef BusEventFilter,
end time.Time) ([]Datum, error) { field string, opts ...Modifier) ([]Datum, error) {
// this fragment uses json_extract from sqlite to get a single // this fragment uses json_extract from sqlite to get a single
// nested value. // nested value.
SqlFrag := ` sb := strings.Builder{}
SELECT sb.WriteString(`SELECT ts as timestamp, json_extract(data, '$.' || ?) as val FROM bus_events WHERE `)
ts as timestamp, if len(bef.Names) != 1 {
json_extract(data, '$.' || ?) as val return nil, errors.New("invalid number of names")
FROM bus_events WHERE name IS ? }
`
rows, err := tdb.db.QueryxContext(ctx, SqlFrag, field, packetName) qStrings := []string{"name is ?"}
// add timestamp limit.
if !bef.TimerangeStart.IsZero() {
qString := fmt.Sprintf("ts >= %d", bef.TimerangeStart.UnixMilli())
qStrings = append(qStrings, qString)
}
if !bef.TimerangeEnd.IsZero() {
qString := fmt.Sprintf("ts <= %d", bef.TimerangeEnd.UnixMilli())
qStrings = append(qStrings, qString)
}
// join qstrings with AND
sb.WriteString(strings.Join(qStrings, " AND "))
for _, m := range opts {
if m == nil {
continue
}
m.ModifyStatement(&sb)
}
rows, err := tdb.db.QueryxContext(ctx, sb.String(), field, bef.Names[0])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -136,7 +156,10 @@ func (tdb *TelemDb) GetValues(ctx context.Context, packetName, field string, sta
data := make([]Datum, 0, 10) data := make([]Datum, 0, 10)
for rows.Next() { for rows.Next() {
var d Datum = Datum{} var d Datum = Datum{}
err = rows.StructScan(&d) var ts int64
err = rows.Scan(&ts, &d.Value)
d.Timestamp = time.UnixMilli(ts)
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
return data, err return data, err