package incident import ( "context" "errors" "fmt" "github.com/jackc/pgx/v5" ) func (r *Repository) UpdateOwner(ctx context.Context, id, owner string, expectedRevision int64) (Incident, error) { if r == nil || r.Pool == nil { return Incident{}, ErrUnavailable } if id == "" || expectedRevision < 1 || len(owner) > 160 || (owner != "" && !ownerUUIDPattern.MatchString(owner)) { return Incident{}, ErrInvalid } var item Incident ownerValue := any(nil) if owner != "" { ownerValue = owner } err := scanIncident(r.Pool.QueryRow(ctx, `UPDATE incidents SET owner_user_id=$1::uuid,revision=revision+1,updated_at=now() WHERE id=$2 AND revision=$3 RETURNING `+incidentColumns, ownerValue, id, expectedRevision), &item) if errors.Is(err, pgx.ErrNoRows) { if _, getErr := r.Get(ctx, id); errors.Is(getErr, ErrNotFound) { return Incident{}, ErrNotFound } return Incident{}, ErrConflict } if err != nil { return Incident{}, mapError("update incident owner", err) } return r.Get(ctx, item.ID) } func (r *Repository) AddNote(ctx context.Context, incidentID, author, body string) (Note, error) { if r == nil || r.Pool == nil { return Note{}, ErrUnavailable } if incidentID == "" || author == "" || len(author) > 160 { return Note{}, ErrInvalid } sanitized, err := SanitizeNote(body) if err != nil { return Note{}, err } var note Note err = r.Pool.QueryRow(ctx, `INSERT INTO incident_notes (id,incident_id,author,body) VALUES ($1,$2,$3,$4) RETURNING id::text,incident_id::text,author,body,created_at`, newID(), incidentID, author, sanitized).Scan(¬e.ID, ¬e.IncidentID, ¬e.Author, ¬e.Body, ¬e.CreatedAt) if err != nil { return Note{}, mapError("add incident note", err) } return note, nil } func (r *Repository) ListNotes(ctx context.Context, incidentID string, limit int) ([]Note, error) { if r == nil || r.Pool == nil { return nil, ErrUnavailable } if incidentID == "" || limit < 1 || limit > 100 { return nil, ErrInvalid } rows, err := r.Pool.Query(ctx, `SELECT id::text,incident_id::text,author,body,created_at FROM incident_notes WHERE incident_id=$1 ORDER BY created_at ASC,id ASC LIMIT $2`, incidentID, limit) if err != nil { return nil, fmt.Errorf("list incident notes: %w", err) } defer rows.Close() items := make([]Note, 0, limit) for rows.Next() { var note Note if err := rows.Scan(¬e.ID, ¬e.IncidentID, ¬e.Author, ¬e.Body, ¬e.CreatedAt); err != nil { return nil, fmt.Errorf("scan incident note: %w", err) } items = append(items, note) } if err := rows.Err(); err != nil { return nil, err } return items, nil }