From 2bc462ada6dc16e25bf85fe2a6bf4035b94567c1 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 23 Oct 2026 09:56:40 -0700 Subject: [PATCH] Simplify codebase per audit of fd0529b --- internal/agents/leadtools.go | 9 +- internal/agents/workflows.go | 8 +- internal/server/changes.go | 8 +- internal/server/files.go | 5 +- internal/server/inbox.go | 13 +-- internal/server/lead.go | 20 +---- internal/server/reviews.go | 4 +- internal/server/server.go | 170 ++++++++++++----------------------- internal/server/sse.go | 9 +- internal/store/store.go | 74 ++++++--------- 10 files changed, 101 insertions(+), 219 deletions(-) diff --git a/internal/agents/leadtools.go b/internal/agents/leadtools.go index 0235391..5040d7e 100644 --- a/internal/agents/leadtools.go +++ b/internal/agents/leadtools.go @@ -90,8 +90,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { if err != nil { return "", err } - b, err := json.MarshalIndent(items, "", " ") - return string(b), err + return prettyJSON(items) }), tool("read_status", @@ -104,8 +103,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { if err != nil { return "", err } - b, err := json.MarshalIndent(status, "", " ") - return string(b), err + return prettyJSON(status) }), tool("answer_question", @@ -331,8 +329,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool { if err != nil { return "", err } - b, err := json.MarshalIndent(p, "", " ") - return string(b), err + return prettyJSON(p) }), tool("start_todo", diff --git a/internal/agents/workflows.go b/internal/agents/workflows.go index a26ded8..22656aa 100644 --- a/internal/agents/workflows.go +++ b/internal/agents/workflows.go @@ -800,8 +800,8 @@ const workflowSchemaDefs = `"$defs": { } }` -func formatDefinition(def api.WorkflowDefinition) (string, error) { - b, err := json.MarshalIndent(def, "", " ") +func prettyJSON(v any) (string, error) { + b, err := json.MarshalIndent(v, "", " ") return string(b), err } @@ -852,7 +852,7 @@ func (m *Manager) workflowTools(tool func(name, description, schema string, run if err != nil { return "", err } - text, err := formatDefinition(frozen.Definition) + text, err := prettyJSON(frozen.Definition) if err != nil { return "", err } @@ -862,7 +862,7 @@ func (m *Manager) workflowTools(tool func(name, description, schema string, run if err != nil { return "", err } - return formatDefinition(def) + return prettyJSON(def) }), tool("save_workflow", diff --git a/internal/server/changes.go b/internal/server/changes.go index 40a3823..fadde2b 100644 --- a/internal/server/changes.go +++ b/internal/server/changes.go @@ -17,7 +17,7 @@ func (s *Server) GetTaskChanges(w http.ResponseWriter, r *http.Request, taskID s return } - step := params.Step != nil && *params.Step + step := deref(params.Step) if params.Snapshot != nil { if params.Since != nil { writeError(w, http.StatusBadRequest, errors.New("since and snapshot can't be used together")) @@ -93,11 +93,7 @@ func (s *Server) GetTaskDiff(w http.ResponseWriter, r *http.Request, taskID stri return } - oldPath := "" - if params.OldPath != nil { - oldPath = *params.OldPath - } - patch, err := git.FileDiff(r.Context(), t.WorktreePath, params.Base, params.Tree, params.Path, oldPath) + patch, err := git.FileDiff(r.Context(), t.WorktreePath, params.Base, params.Tree, params.Path, deref(params.OldPath)) if err != nil { writeError(w, http.StatusInternalServerError, err) return diff --git a/internal/server/files.go b/internal/server/files.go index a846a98..b3353e7 100644 --- a/internal/server/files.go +++ b/internal/server/files.go @@ -42,10 +42,7 @@ func (s *Server) GetProjectDir(w http.ResponseWriter, r *http.Request, projectID } func serveDir(w http.ResponseWriter, r *http.Request, root string, p *string) { - rel := "" - if p != nil { - rel = *p - } + rel := deref(p) name, full := taskPath(root, rel) f, err := os.Open(full) diff --git a/internal/server/inbox.go b/internal/server/inbox.go index abfbeb9..18e8071 100644 --- a/internal/server/inbox.go +++ b/internal/server/inbox.go @@ -8,13 +8,7 @@ import ( ) func (s *Server) ListInbox(w http.ResponseWriter, r *http.Request, params api.ListInboxParams) { - f := store.InboxFilter{State: api.Open} - if params.ProjectId != nil { - f.ProjectID = *params.ProjectId - } - if params.TaskId != nil { - f.TaskID = *params.TaskId - } + f := store.InboxFilter{State: api.Open, ProjectID: deref(params.ProjectId), TaskID: deref(params.TaskId)} if params.State != nil { f.State = *params.State } @@ -55,9 +49,8 @@ func (s *Server) AnswerAgain(w http.ResponseWriter, r *http.Request) { return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } diff --git a/internal/server/lead.go b/internal/server/lead.go index a6ae8dd..4666edd 100644 --- a/internal/server/lead.go +++ b/internal/server/lead.go @@ -52,26 +52,12 @@ func (s *Server) MessageLead(w http.ResponseWriter, r *http.Request) { return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } - model := "" - if req.Model != nil { - model = *req.Model - } - effort := "" - if req.Effort != nil { - effort = *req.Effort - } - sendID := "" - if req.SendId != nil { - sendID = *req.SendId - } - - sess, err := s.agents.MessageLead(r.Context(), u, req.Text, model, effort, sendID, r.Header.Get("Byre-Client"), images) + sess, err := s.agents.MessageLead(r.Context(), u, req.Text, deref(req.Model), deref(req.Effort), deref(req.SendId), r.Header.Get("Byre-Client"), images) if err != nil { writeAgentError(w, err) return diff --git a/internal/server/reviews.go b/internal/server/reviews.go index 32b9c99..8b52120 100644 --- a/internal/server/reviews.go +++ b/internal/server/reviews.go @@ -8,9 +8,7 @@ import ( ) func (s *Server) ListReviews(w http.ResponseWriter, r *http.Request, taskID string) { - _, err := s.store.GetTask(r.Context(), taskID) - if err != nil { - writeStoreError(w, err) + if !s.taskExists(w, r, taskID) { return } diff --git a/internal/server/server.go b/internal/server/server.go index c97fdde..3986341 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -253,10 +253,26 @@ func actor(r *http.Request) string { return r.Context().Value(ctxKey{}).(string) } -func (s *Server) GetMe(w http.ResponseWriter, r *http.Request) { +func (s *Server) actingUser(w http.ResponseWriter, r *http.Request) (api.User, bool) { u, err := s.store.GetUser(r.Context(), actor(r)) if err != nil { writeStoreError(w, err) + return u, false + } + return u, true +} + +func deref[T any](p *T) T { + var zero T + if p == nil { + return zero + } + return *p +} + +func (s *Server) GetMe(w http.ResponseWriter, r *http.Request) { + u, ok := s.actingUser(w, r) + if !ok { return } writeJSON(w, http.StatusOK, u) @@ -366,10 +382,7 @@ func (s *Server) CreateTask(w http.ResponseWriter, r *http.Request, projectID st return } - title := "" - if req.Title != nil { - title = strings.TrimSpace(*req.Title) - } + title := strings.TrimSpace(deref(req.Title)) p, err := s.store.GetProject(r.Context(), projectID) if err != nil { @@ -389,9 +402,8 @@ func (s *Server) CreateTask(w http.ResponseWriter, r *http.Request, projectID st if req.Prompt != nil && strings.TrimSpace(*req.Prompt) != "" { brief = *req.Prompt } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } tasks, err := s.agents.StartWorkflow(r.Context(), p, u, title, p.DefaultBranch, u.Login, *req.Workflow, brief, nil, "") @@ -418,28 +430,16 @@ func (s *Server) CreateTask(w http.ResponseWriter, r *http.Request, projectID st return } - prompt := "" - if req.Prompt != nil { - prompt = *req.Prompt - } + prompt := deref(req.Prompt) if strings.TrimSpace(prompt) == "" && len(images) == 0 { writeError(w, http.StatusBadRequest, errors.New("prompt is empty")) return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } - model := "" - if req.Model != nil { - model = *req.Model - } - effort := "" - if req.Effort != nil { - effort = *req.Effort - } - t, err := s.agents.StartTask(r.Context(), p, u, title, prompt, model, effort, r.Header.Get("Byre-Client"), images) + t, err := s.agents.StartTask(r.Context(), p, u, title, prompt, deref(req.Model), deref(req.Effort), r.Header.Get("Byre-Client"), images) if err != nil { writeAgentError(w, err) return @@ -479,22 +479,12 @@ func (s *Server) StartTodoItem(w http.ResponseWriter, r *http.Request, projectID return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } - model := "" - if req.Model != nil { - model = *req.Model - } - effort := "" - if req.Effort != nil { - effort = *req.Effort - } - - tasks, err := s.agents.StartTodo(r.Context(), p, u, req.Title, model, effort, u.Login, "", req.Discuss != nil && *req.Discuss) + tasks, err := s.agents.StartTodo(r.Context(), p, u, req.Title, deref(req.Model), deref(req.Effort), u.Login, "", deref(req.Discuss)) if err != nil { writeAgentError(w, err) return @@ -522,12 +512,12 @@ func (s *Server) MergeTask(w http.ResponseWriter, r *http.Request, taskID string return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } + var err error if req.Target != nil && !req.Target.Valid() { writeError(w, http.StatusBadRequest, fmt.Errorf("unknown target %q", *req.Target)) return @@ -626,9 +616,8 @@ func (s *Server) MergeIn(w http.ResponseWriter, r *http.Request, taskID string) return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } @@ -672,6 +661,15 @@ func (s *Server) PostToBoard(w http.ResponseWriter, r *http.Request, taskID stri w.WriteHeader(http.StatusNoContent) } +func (s *Server) taskExists(w http.ResponseWriter, r *http.Request, taskID string) bool { + _, err := s.store.GetTask(r.Context(), taskID) + if err != nil { + writeStoreError(w, err) + return false + } + return true +} + func (s *Server) activeTask(w http.ResponseWriter, r *http.Request, taskID string) (api.Task, bool) { t, err := s.store.GetTask(r.Context(), taskID) if err != nil { @@ -778,9 +776,7 @@ func (s *Server) status(ctx context.Context) (api.Status, error) { } func (s *Server) ListTaskEvents(w http.ResponseWriter, r *http.Request, taskID string, params api.ListTaskEventsParams) { - _, err := s.store.GetTask(r.Context(), taskID) - if err != nil { - writeStoreError(w, err) + if !s.taskExists(w, r, taskID) { return } @@ -802,9 +798,7 @@ func (s *Server) ListTaskEvents(w http.ResponseWriter, r *http.Request, taskID s } func (s *Server) ListSnapshots(w http.ResponseWriter, r *http.Request, taskID string) { - _, err := s.store.GetTask(r.Context(), taskID) - if err != nil { - writeStoreError(w, err) + if !s.taskExists(w, r, taskID) { return } @@ -817,9 +811,7 @@ func (s *Server) ListSnapshots(w http.ResponseWriter, r *http.Request, taskID st } func (s *Server) ListPreviews(w http.ResponseWriter, r *http.Request, taskID string) { - _, err := s.store.GetTask(r.Context(), taskID) - if err != nil { - writeStoreError(w, err) + if !s.taskExists(w, r, taskID) { return } @@ -837,9 +829,8 @@ func (s *Server) ForkSnapshot(w http.ResponseWriter, r *http.Request, taskID str return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } @@ -867,19 +858,6 @@ func (s *Server) ContinueSession(w http.ResponseWriter, r *http.Request, session return } - model := "" - if req.Model != nil { - model = *req.Model - } - effort := "" - if req.Effort != nil { - effort = *req.Effort - } - sendID := "" - if req.SendId != nil { - sendID = *req.SendId - } - src, err := s.store.GetSession(r.Context(), sessionID) if err != nil { writeStoreError(w, err) @@ -895,13 +873,12 @@ func (s *Server) ContinueSession(w http.ResponseWriter, r *http.Request, session writeStoreError(w, err) return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } - task, err := s.agents.Continue(r.Context(), src, t, p, u, req.Text, model, effort, sendID, r.Header.Get("Byre-Client"), images...) + task, err := s.agents.Continue(r.Context(), src, t, p, u, req.Text, deref(req.Model), deref(req.Effort), deref(req.SendId), r.Header.Get("Byre-Client"), images...) if err != nil { writeAgentError(w, err) return @@ -910,9 +887,7 @@ func (s *Server) ContinueSession(w http.ResponseWriter, r *http.Request, session } func (s *Server) ListSessions(w http.ResponseWriter, r *http.Request, taskID string) { - _, err := s.store.GetTask(r.Context(), taskID) - if err != nil { - writeStoreError(w, err) + if !s.taskExists(w, r, taskID) { return } @@ -946,26 +921,12 @@ func (s *Server) CreateSession(w http.ResponseWriter, r *http.Request, taskID st return } - u, err := s.store.GetUser(r.Context(), actor(r)) - if err != nil { - writeStoreError(w, err) + u, ok := s.actingUser(w, r) + if !ok { return } - model := "" - if req.Model != nil { - model = *req.Model - } - effort := "" - if req.Effort != nil { - effort = *req.Effort - } - sendID := "" - if req.SendId != nil { - sendID = *req.SendId - } - - sess, err := s.agents.Create(r.Context(), t, u, req.Prompt, model, effort, sendID, r.Header.Get("Byre-Client"), images...) + sess, err := s.agents.Create(r.Context(), t, u, req.Prompt, deref(req.Model), deref(req.Effort), deref(req.SendId), r.Header.Get("Byre-Client"), images...) if err != nil { writeAgentError(w, err) return @@ -998,20 +959,7 @@ func (s *Server) SendMessage(w http.ResponseWriter, r *http.Request, sessionID s return } - model := "" - if req.Model != nil { - model = *req.Model - } - effort := "" - if req.Effort != nil { - effort = *req.Effort - } - sendID := "" - if req.SendId != nil { - sendID = *req.SendId - } - - sess, _, err := s.agents.Message(r.Context(), sessionID, actor(r), req.Text, model, effort, sendID, r.Header.Get("Byre-Client"), images...) + sess, _, err := s.agents.Message(r.Context(), sessionID, actor(r), req.Text, deref(req.Model), deref(req.Effort), deref(req.SendId), r.Header.Get("Byre-Client"), images...) if err != nil { writeAgentError(w, err) return @@ -1033,15 +981,7 @@ func (s *Server) CompactSession(w http.ResponseWriter, r *http.Request, sessionI if !readJSON(w, r, &req) { return } - model := "" - if req.Model != nil { - model = *req.Model - } - effort := "" - if req.Effort != nil { - effort = *req.Effort - } - sess, err := s.agents.Compact(r.Context(), sessionID, model, effort) + sess, err := s.agents.Compact(r.Context(), sessionID, deref(req.Model), deref(req.Effort)) if err != nil { writeAgentError(w, err) return diff --git a/internal/server/sse.go b/internal/server/sse.go index 703eb7e..d5515df 100644 --- a/internal/server/sse.go +++ b/internal/server/sse.go @@ -20,13 +20,10 @@ func (s *Server) StreamEvents(w http.ResponseWriter, r *http.Request, params api last = *params.LastEventID } viewer := actor(r) - lead := params.Lead != nil && *params.Lead - taskID := "" + lead := deref(params.Lead) + taskID := deref(params.TaskId) if params.TaskId != nil { - taskID = *params.TaskId - _, err := s.store.GetTask(r.Context(), taskID) - if err != nil { - writeStoreError(w, err) + if !s.taskExists(w, r, taskID) { return } } diff --git a/internal/store/store.go b/internal/store/store.go index 606339a..2808b0a 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -215,6 +215,15 @@ func (s *Store) Path() string { return s.path } +func updatedProject(ctx context.Context, tx *sql.Tx, query string, args ...any) (string, error) { + projectID := "" + err := tx.QueryRowContext(ctx, query, args...).Scan(&projectID) + if errors.Is(err, sql.ErrNoRows) { + return "", ErrNotFound + } + return projectID, err +} + func (s *Store) EnsureUser(ctx context.Context, login, displayName string) (api.User, error) { _, err := s.db.ExecContext(ctx, ` INSERT INTO users (login, display_name, created_at) VALUES (?, ?, ?) @@ -421,12 +430,8 @@ func (s *Store) GetTask(ctx context.Context, id string) (api.Task, error) { func (s *Store) SetMergeTitle(ctx context.Context, id, title, actor string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET merge_title = ? WHERE id = ? AND status = ? AND merging_by = '' AND finalizing = '' AND merge_queued_by = '' RETURNING project_id`, - title, id, string(api.TaskStatusActive)).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { - return ErrNotFound - } + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET merge_title = ? WHERE id = ? AND status = ? AND merging_by = '' AND finalizing = '' AND merge_queued_by = '' RETURNING project_id`, + title, id, string(api.TaskStatusActive)) if err != nil { return err } @@ -436,12 +441,8 @@ func (s *Store) SetMergeTitle(ctx context.Context, id, title, actor string) erro func (s *Store) SetTitles(ctx context.Context, id, title, mergeTitle, actor string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET title = ?, merge_title = ? WHERE id = ? AND status = ? AND merging_by = '' AND finalizing = '' AND merge_queued_by = '' RETURNING project_id`, - title, mergeTitle, id, string(api.TaskStatusActive)).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { - return ErrNotFound - } + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET title = ?, merge_title = ? WHERE id = ? AND status = ? AND merging_by = '' AND finalizing = '' AND merge_queued_by = '' RETURNING project_id`, + title, mergeTitle, id, string(api.TaskStatusActive)) if err != nil { return err } @@ -487,9 +488,8 @@ func (s *Store) TakeMergingBy(ctx context.Context, id string) (string, error) { func (s *Store) ClearFinalizing(ctx context.Context, id string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET finalizing = '', finalizing_commit = '', finalizing_notes = '', finalizing_unchanged = 0 WHERE id = ? AND finalizing != '' RETURNING project_id`, id).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET finalizing = '', finalizing_commit = '', finalizing_notes = '', finalizing_unchanged = 0 WHERE id = ? AND finalizing != '' RETURNING project_id`, id) + if errors.Is(err, ErrNotFound) { return nil } if err != nil { @@ -509,12 +509,8 @@ func (s *Store) SetFinalizingUnchanged(ctx context.Context, id string) error { func (s *Store) setFinalizing(ctx context.Context, id, commit, notes, pushed string, unchanged bool) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET finalizing_commit = ?, finalizing_notes = ?, finalizing_unchanged = ? WHERE id = ? AND status = ? AND finalizing != '' RETURNING project_id`, - commit, notes, unchanged, id, string(api.TaskStatusActive)).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { - return ErrNotFound - } + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET finalizing_commit = ?, finalizing_notes = ?, finalizing_unchanged = ? WHERE id = ? AND status = ? AND finalizing != '' RETURNING project_id`, + commit, notes, unchanged, id, string(api.TaskStatusActive)) if err != nil || commit == "" { return err } @@ -592,9 +588,8 @@ func (s *Store) SetParentMerge(ctx context.Context, id, login string) error { func (s *Store) ClearParentMerge(ctx context.Context, id string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET parent_merge_by = '' WHERE id = ? AND parent_merge_by != '' RETURNING project_id`, id).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET parent_merge_by = '' WHERE id = ? AND parent_merge_by != '' RETURNING project_id`, id) + if errors.Is(err, ErrNotFound) { return nil } if err != nil { @@ -688,11 +683,7 @@ func (s *Store) SetMergeAfterReview(ctx context.Context, id string, mar MergeAft func (s *Store) CancelMergeAfterReview(ctx context.Context, id, actor string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET merge_after_review_by = '', merge_after_review_id = '', merge_after_review_target = '' WHERE id = ? AND merge_after_review_by != '' RETURNING project_id`, id).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { - return ErrNotFound - } + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET merge_after_review_by = '', merge_after_review_id = '', merge_after_review_target = '' WHERE id = ? AND merge_after_review_by != '' RETURNING project_id`, id) if err != nil { return err } @@ -728,12 +719,8 @@ func (s *Store) TakeMergeAfterReview(ctx context.Context, id string, reviewIDs [ func (s *Store) SetTaskSummary(ctx context.Context, id, summary, actor string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET summary = ? WHERE id = ? AND status = ? RETURNING project_id`, - summary, id, string(api.TaskStatusActive)).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { - return ErrNotFound - } + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET summary = ? WHERE id = ? AND status = ? RETURNING project_id`, + summary, id, string(api.TaskStatusActive)) if err != nil { return err } @@ -751,11 +738,7 @@ func (s *Store) SuggestDiscard(ctx context.Context, id, reason, actor string) er func (s *Store) ClearReady(ctx context.Context, id, actor, reason string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET ready = '' WHERE id = ? AND status = ? AND ready != '' RETURNING project_id`, id, string(api.TaskStatusActive)).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { - return ErrNotFound - } + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET ready = '' WHERE id = ? AND status = ? AND ready != '' RETURNING project_id`, id, string(api.TaskStatusActive)) if err != nil { return err } @@ -770,9 +753,8 @@ func (s *Store) ClearReady(ctx context.Context, id, actor, reason string) error func (s *Store) TakeReady(ctx context.Context, id, ready string) (bool, error) { taken := false err := s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET ready = '' WHERE id = ? AND status = ? AND ready = ? RETURNING project_id`, id, string(api.TaskStatusActive), ready).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET ready = '' WHERE id = ? AND status = ? AND ready = ? RETURNING project_id`, id, string(api.TaskStatusActive), ready) + if errors.Is(err, ErrNotFound) { return nil } if err != nil { @@ -790,11 +772,7 @@ func (s *Store) TakeReady(ctx context.Context, id, ready string) (bool, error) { func (s *Store) setReady(ctx context.Context, id, actor, ready, kind string, payload map[string]any) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - projectID := "" - err := tx.QueryRowContext(ctx, `UPDATE tasks SET ready = ? WHERE id = ? AND status = ? RETURNING project_id`, ready, id, string(api.TaskStatusActive)).Scan(&projectID) - if errors.Is(err, sql.ErrNoRows) { - return ErrNotFound - } + projectID, err := updatedProject(ctx, tx, `UPDATE tasks SET ready = ? WHERE id = ? AND status = ? RETURNING project_id`, ready, id, string(api.TaskStatusActive)) if err != nil { return err }