feat(workspace,jobs): emit sync_aborted_on_restart audit + enrich worktree.pruned metadata

- workspace.ResetStuckSyncStatuses now returns affected IDs so app.New can record one workspace.sync_aborted_on_restart audit per reset row
- worktree_prune audit metadata gains workspace_id and path alongside existing branch
- updated fakeRepo + integration test for new ResetStuckSyncStatuses signature
- add TestWorktreePrune_AuditMetadataContainsWorkspaceIDAndPath
This commit is contained in:
2026-05-07 10:14:46 +08:00
parent b1ccce567e
commit a2b6d5382e
8 changed files with 110 additions and 22 deletions
+12 -5
View File
@@ -44,7 +44,9 @@ type Repository interface {
UpdateWorkspaceCore(ctx context.Context, id uuid.UUID, name, description, defaultBranch string) (*Workspace, error)
UpdateWorkspaceSyncStatus(ctx context.Context, id uuid.UUID, st SyncStatus, syncedAt *time.Time, errMsg string) (*Workspace, error)
DeleteWorkspace(ctx context.Context, id uuid.UUID) error
ResetStuckSyncStatuses(ctx context.Context) error
// ResetStuckSyncStatuses 把启动时残留的 cloning/syncing 复位为 error,
// 返回被复位的工作区 ID 列表(按发生顺序),由调用方写 audit。
ResetStuckSyncStatuses(ctx context.Context) ([]uuid.UUID, error)
// Worktree (no-tx 部分)
GetWorktreeByID(ctx context.Context, id uuid.UUID) (*Worktree, error)
@@ -240,11 +242,16 @@ func (r *pgRepo) DeleteWorkspace(ctx context.Context, id uuid.UUID) error {
return nil
}
func (r *pgRepo) ResetStuckSyncStatuses(ctx context.Context) error {
if err := r.q.ResetStuckSyncStatuses(ctx); err != nil {
return errs.Wrap(err, errs.CodeInternal, "reset stuck sync")
func (r *pgRepo) ResetStuckSyncStatuses(ctx context.Context) ([]uuid.UUID, error) {
rows, err := r.q.ResetStuckSyncStatuses(ctx)
if err != nil {
return nil, errs.Wrap(err, errs.CodeInternal, "reset stuck sync")
}
return nil
ids := make([]uuid.UUID, 0, len(rows))
for _, row := range rows {
ids = append(ids, fromPgUUID(row.ID))
}
return ids, nil
}
// ===== Workspace fetch (jobs runner) =====