package api import ( "context" "encoding/json" "fmt" "net/http" "time" "git.joco.dk/sng/fermentord/internal/controllers" "git.joco.dk/sng/fermentord/internal/dal" "github.com/getsentry/sentry-go" "github.com/rs/zerolog/log" ) type API struct { db *dal.DAL config *controllers.Config configChangeCallback func() } func NewAPI(db *dal.DAL) *API { return &API{ db: db, } } func (a *API) HealthCheck(w http.ResponseWriter, r *http.Request) { defer sentry.Recover() tx, err := a.db.Begin() if err != nil { http.Error(w, "Unhealthy", http.StatusServiceUnavailable) return } var version string err = tx.QueryRow("SELECT version()").Scan(&version) if err != nil { http.Error(w, "Unhealthy", http.StatusServiceUnavailable) return } w.Write([]byte("Healthy")) } func (a *API) GetConfig(w http.ResponseWriter, r *http.Request) { defer sentry.Recover() resp, err := json.MarshalIndent(a.config, "", " ") if err != nil { log.Panic().Err(err).Msg("Error marshalling configuration.") } w.Write(resp) } func (a *API) GetTemperatures(w http.ResponseWriter, r *http.Request) { defer sentry.Recover() ctx := context.Background() tx, err := a.db.Begin() defer tx.Rollback() if err != nil { log.Panic().Err(err).Msg("Failed to start DB transaction.") } keys, ok := r.URL.Query()["since"] if !ok || len(keys[0]) < 1 { http.Error(w, "Missing since parameter.", http.StatusBadRequest) return } since, err := time.Parse(time.RFC3339, keys[0]) if err != nil { http.Error(w, "Invalid format of since parameter. Expected RFC3339 formatted string.", http.StatusBadRequest) return } dbCtx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() readings, err := dal.LoadTemperatureReadingsSince(dbCtx, tx, since) if err != nil { log.Panic().Err(err).Msg("Failed to load temperature readings from DB.") } tx.Commit() data, err := json.MarshalIndent(readings, "", " ") if err != nil { log.Panic().Err(err).Msg("Failed to serialize temperature readings to JSON.") } fmt.Fprintf(w, string(data)) } func (a *API) GetStateChanges(w http.ResponseWriter, r *http.Request) { defer sentry.Recover() ctx := context.Background() tx, err := a.db.Begin() if err != nil { log.Panic().Err(err).Msg("Failed to start DB transaction.") } keys, ok := r.URL.Query()["since"] if !ok || len(keys[0]) < 1 { http.Error(w, "Missing since parameter.", http.StatusBadRequest) return } since, err := time.Parse(time.RFC3339, keys[0]) if err != nil { http.Error(w, "Invalid format of since parameter. Expected RFC3339 formatted string.", http.StatusBadRequest) return } dbCtx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() readings, err := dal.LoadChamberStateChangesSince(dbCtx, tx, since) if err != nil { log.Panic().Err(err).Msg("Failed to load temperature readings from DB.") } tx.Commit() data, err := json.MarshalIndent(readings, "", " ") if err != nil { log.Panic().Err(err).Msg("Failed to serialize temperature readings to JSON.") } fmt.Fprintf(w, string(data)) }