You've already forked agentic-coding-workflow
feat(jobs/runners): worktree prune two-phase + workspace prune queries/repo methods
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
tcpg "github.com/testcontainers/testcontainers-go/modules/postgres"
|
||||
|
||||
"github.com/yan1h/agent-coding-workflow/internal/infra/db"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/infra/errs"
|
||||
)
|
||||
|
||||
// setupRepo 起一个临时 postgres 容器、跑迁移、注入一条 user/project 行做外键,
|
||||
@@ -186,3 +187,83 @@ func TestRepo_SetWorktreeActive_ClearsPruneWarning(t *testing.T) {
|
||||
require.NoError(t, pool.QueryRow(ctx, `SELECT prune_warning_at FROM workspace_worktrees WHERE id = $1`, wtID).Scan(&pwAt))
|
||||
require.Nil(t, pwAt, "SetWorktreeIdle should clear prune_warning_at")
|
||||
}
|
||||
|
||||
// TestRepo_TryStartPrune_CASLossReturnsAlreadyActive 验证:对一个已变为 active 的
|
||||
// worktree 调用 TryStartPrune 会返回 CodeWorktreeAlreadyActive。
|
||||
func TestRepo_TryStartPrune_CASLossReturnsAlreadyActive(t *testing.T) {
|
||||
t.Parallel()
|
||||
repo, pool, pid := setupRepo(t)
|
||||
ctx := context.Background()
|
||||
wsID := uuid.New()
|
||||
_, err := repo.CreateWorkspace(ctx, &Workspace{
|
||||
ID: wsID, ProjectID: pid, Slug: "ws-cas", Name: "CAS",
|
||||
GitRemoteURL: "https://x", DefaultBranch: "main", MainPath: "/x", SyncStatus: SyncStatusIdle,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
wtID := uuid.New()
|
||||
require.NoError(t, repo.InTx(ctx, func(tx Tx) error {
|
||||
_, e := tx.InsertWorktree(ctx, &Worktree{
|
||||
ID: wtID, WorkspaceID: wsID, Branch: "cas-branch",
|
||||
Path: "/x/.worktrees/cas", Status: WorktreeStatusIdle,
|
||||
})
|
||||
return e
|
||||
}))
|
||||
|
||||
// 绕过 service 直接把 status 改成 active,模拟 CAS 竞争丢失。
|
||||
_, err = pool.Exec(ctx, `UPDATE workspace_worktrees SET status = 'active' WHERE id = $1`, wtID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = repo.TryStartPrune(ctx, wtID)
|
||||
require.Error(t, err)
|
||||
appErr, ok := errs.As(err)
|
||||
require.True(t, ok, "expected AppError")
|
||||
require.Equal(t, errs.CodeWorktreeAlreadyActive, appErr.Code)
|
||||
}
|
||||
|
||||
// TestRepo_ListWorktreesNeedingPruneWarning_FiltersExisting 验证:已有
|
||||
// prune_warning_at 的 worktree 不会被返回,仅返回尚未标记的。
|
||||
func TestRepo_ListWorktreesNeedingPruneWarning_FiltersExisting(t *testing.T) {
|
||||
t.Parallel()
|
||||
repo, pool, pid := setupRepo(t)
|
||||
ctx := context.Background()
|
||||
wsID := uuid.New()
|
||||
_, err := repo.CreateWorkspace(ctx, &Workspace{
|
||||
ID: wsID, ProjectID: pid, Slug: "ws-pwf", Name: "PWF",
|
||||
GitRemoteURL: "https://x", DefaultBranch: "main", MainPath: "/x", SyncStatus: SyncStatusIdle,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
cutoff := time.Now().Add(-24 * time.Hour)
|
||||
|
||||
// worktree A:没有 prune_warning_at,last_used_at 在 cutoff 之前 → 应返回。
|
||||
wtA := uuid.New()
|
||||
require.NoError(t, repo.InTx(ctx, func(tx Tx) error {
|
||||
_, e := tx.InsertWorktree(ctx, &Worktree{
|
||||
ID: wtA, WorkspaceID: wsID, Branch: "prune-a",
|
||||
Path: "/x/.worktrees/a", Status: WorktreeStatusIdle,
|
||||
})
|
||||
return e
|
||||
}))
|
||||
_, err = pool.Exec(ctx, `UPDATE workspace_worktrees SET last_used_at = $1 WHERE id = $2`, cutoff.Add(-time.Hour), wtA)
|
||||
require.NoError(t, err)
|
||||
|
||||
// worktree B:已经有 prune_warning_at,last_used_at 同样在 cutoff 前 → 不应返回。
|
||||
wtB := uuid.New()
|
||||
require.NoError(t, repo.InTx(ctx, func(tx Tx) error {
|
||||
_, e := tx.InsertWorktree(ctx, &Worktree{
|
||||
ID: wtB, WorkspaceID: wsID, Branch: "prune-b",
|
||||
Path: "/x/.worktrees/b", Status: WorktreeStatusIdle,
|
||||
})
|
||||
return e
|
||||
}))
|
||||
_, err = pool.Exec(ctx,
|
||||
`UPDATE workspace_worktrees SET last_used_at = $1, prune_warning_at = now() WHERE id = $2`,
|
||||
cutoff.Add(-time.Hour), wtB)
|
||||
require.NoError(t, err)
|
||||
|
||||
rows, err := repo.ListWorktreesNeedingPruneWarning(ctx, cutoff)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, rows, 1)
|
||||
require.Equal(t, wtA, rows[0].ID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user