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
+15 -3
View File
@@ -154,9 +154,21 @@ func New(ctx context.Context, cfg *config.Config, dist embed.FS) (*App, error) {
})
wsRepo := workspace.NewPostgresRepository(pool)
// 进程启动时把卡死的 cloning/syncing 复位为 error,避免行永远卡住
if err := wsRepo.ResetStuckSyncStatuses(ctx); err != nil {
// 进程启动时把卡死的 cloning/syncing 复位为 error,避免行永远卡住
// 每个被复位的工作区写一条 workspace.sync_aborted_on_restart audit。
if abortedIDs, err := wsRepo.ResetStuckSyncStatuses(ctx); err != nil {
log.Warn("reset stuck workspace sync statuses", "err", err.Error())
} else {
for _, wsID := range abortedIDs {
if rerr := auditRec.Record(ctx, audit.Entry{
Action: "workspace.sync_aborted_on_restart",
TargetType: "workspace",
TargetID: wsID.String(),
}); rerr != nil {
log.Warn("workspace.sync_aborted_on_restart audit failed",
"workspace_id", wsID, "err", rerr.Error())
}
}
}
pa := projectAccessAdapter{p: projectSvc}
@@ -614,7 +626,7 @@ func (a worktreePruneAdapter) enrichWorktrees(ctx context.Context, rows []*works
}
func (a worktreePruneAdapter) enrichOne(ctx context.Context, w *workspace.Worktree) runners.WorktreeRow {
row := runners.WorktreeRow{ID: w.ID, Branch: w.Branch, Path: w.Path}
row := runners.WorktreeRow{ID: w.ID, WorkspaceID: w.WorkspaceID, Branch: w.Branch, Path: w.Path}
ws, err := a.wsRepo.GetWorkspaceByID(ctx, w.WorkspaceID)
if err != nil {
a.log.Warn("worktree_prune.adapter.lookup_workspace_failed",