package service import ( "database/sql" "encoding/json/v2" "errors" "log/slog" "net/http" "code.chimeric.al/chimerical/odidere/internal/db" ) func (svc *Service) listExecutions(w http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() log = ctx.Value(logKey).(*slog.Logger) ) rows, err := svc.dbr.SelectPendingExecutions(ctx) if err != nil { log.ErrorContext( ctx, "failed to list pending executions", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } w.Header().Set("Content-Type", "application/json") if err := json.MarshalWrite(w, rows); err != nil { log.ErrorContext( ctx, "failed to encode executions response", slog.Any("error", err), ) } } func (svc *Service) updateExecution(w http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() log = ctx.Value(logKey).(*slog.Logger) req struct { Status db.ExecutionStatus `json:"status"` } ) r.Body = http.MaxBytesReader(w, r.Body, 32<<20) if err := json.UnmarshalRead(r.Body, &req); err != nil { log.ErrorContext( ctx, "failed to decode request", slog.Any("error", err), ) http.Error(w, "invalid request", http.StatusBadRequest) return } if req.Status != db.ExecutionStatusApproved && req.Status != db.ExecutionStatusDenied { http.Error(w, "invalid status", http.StatusBadRequest) return } tx, err := svc.db.Writer.BeginTx(ctx, nil) if err != nil { log.ErrorContext( ctx, "failed to begin execution transaction", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } defer tx.Rollback() qtx := svc.dbw.WithTx(tx) execution, err := qtx.SelectExecutionId(ctx, r.PathValue("id")) if errors.Is(err, sql.ErrNoRows) { http.NotFound(w, r) return } if err != nil { log.ErrorContext( ctx, "failed to load execution", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } if execution.Status != db.ExecutionStatusPending { http.Error(w, "execution is not pending", http.StatusConflict) return } if err := qtx.UpdateExecutionStatus(ctx, db.UpdateExecutionStatusParams{ Id: execution.Id, Status: req.Status, }); err != nil { log.ErrorContext( ctx, "failed to update execution status", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } if err := tx.Commit(); err != nil { log.ErrorContext( ctx, "failed to commit execution transaction", slog.Any("error", err), ) http.Error( w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, ) return } w.WriteHeader(http.StatusNoContent) }