feat(ECR-046): ScaleDefinition 元数据写面闭环并 Closed
explore.write POST/PUT · create→draft · status 仍 ECR-008 · migration 000055 · Loop STOP Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
// ScaleDefinitionWriteInput is explore-side metadata payload (no status).
|
||||
type ScaleDefinitionWriteInput struct {
|
||||
Slug string
|
||||
Title string
|
||||
Description string
|
||||
}
|
||||
|
||||
// CreateScaleDefinitionWithAudit inserts draft scale metadata + audit.
|
||||
func (r *ScaleRepo) CreateScaleDefinitionWithAudit(
|
||||
ctx context.Context, adminID uuid.UUID, in ScaleDefinitionWriteInput, meta json.RawMessage,
|
||||
) (*ScaleAdminItem, error) {
|
||||
tx, err := r.Pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
var it ScaleAdminItem
|
||||
err = tx.QueryRow(ctx, `
|
||||
INSERT INTO scales(slug, title, description, status)
|
||||
VALUES ($1,$2,$3,'draft')
|
||||
RETURNING id, slug, title, description, status`,
|
||||
in.Slug, in.Title, in.Description,
|
||||
).Scan(&it.ID, &it.Slug, &it.Title, &it.Description, &it.Status)
|
||||
if err != nil {
|
||||
return nil, mapScaleDefinitionWriteErr(err)
|
||||
}
|
||||
if meta == nil {
|
||||
meta = json.RawMessage(`{}`)
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO admin_audit_logs(admin_id, action, target_type, target_id, meta)
|
||||
VALUES ($1,'explore.scale_definition.create','scale',$2,$3)`,
|
||||
adminID, it.ID.String(), meta,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &it, nil
|
||||
}
|
||||
|
||||
// UpdateScaleDefinitionWithAudit updates metadata only (never status).
|
||||
func (r *ScaleRepo) UpdateScaleDefinitionWithAudit(
|
||||
ctx context.Context, adminID, id uuid.UUID, in ScaleDefinitionWriteInput, meta json.RawMessage,
|
||||
) (*ScaleAdminItem, error) {
|
||||
tx, err := r.Pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
var it ScaleAdminItem
|
||||
err = tx.QueryRow(ctx, `
|
||||
UPDATE scales
|
||||
SET slug=$2, title=$3, description=$4, updated_at=now()
|
||||
WHERE id=$1 AND deleted_at IS NULL
|
||||
RETURNING id, slug, title, description, status`,
|
||||
id, in.Slug, in.Title, in.Description,
|
||||
).Scan(&it.ID, &it.Slug, &it.Title, &it.Description, &it.Status)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, pgx.ErrNoRows
|
||||
}
|
||||
if err != nil {
|
||||
return nil, mapScaleDefinitionWriteErr(err)
|
||||
}
|
||||
if meta == nil {
|
||||
meta = json.RawMessage(`{}`)
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO admin_audit_logs(admin_id, action, target_type, target_id, meta)
|
||||
VALUES ($1,'explore.scale_definition.update','scale',$2,$3)`,
|
||||
adminID, id.String(), meta,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &it, nil
|
||||
}
|
||||
|
||||
func mapScaleDefinitionWriteErr(err error) error {
|
||||
var pgErr *pgconn.PgError
|
||||
if errors.As(err, &pgErr) && pgErr.Code == "23505" {
|
||||
return errString("scale slug conflict")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ScaleSlugConflict reports unique violation.
|
||||
func ScaleSlugConflict(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "scale slug conflict")
|
||||
}
|
||||
Reference in New Issue
Block a user