You've already forked agentic-coding-workflow
主流程
This commit is contained in:
@@ -23,11 +23,11 @@ type fakeRepo struct {
|
||||
projects map[uuid.UUID]*Project
|
||||
requirements map[uuid.UUID]*Requirement
|
||||
issues map[uuid.UUID]*Issue
|
||||
prototypes map[uuid.UUID]*Prototype
|
||||
artifacts map[uuid.UUID]*Artifact
|
||||
|
||||
// 置 true 时,下一次 CreatePrototype 返回一次真实的 PG 唯一约束冲突后自动复位,
|
||||
// 用于覆盖 prototypeService.createWithRetry 的 version 竞争重试分支。
|
||||
createPrototypeFailOnce bool
|
||||
// 置 true 时,下一次 CreateArtifact 返回一次真实的 PG 唯一约束冲突后自动复位,
|
||||
// 用于覆盖 artifactService.createWithRetry 的 version 竞争重试分支。
|
||||
createArtifactFailOnce bool
|
||||
}
|
||||
|
||||
func newFakeRepo() *fakeRepo {
|
||||
@@ -35,14 +35,14 @@ func newFakeRepo() *fakeRepo {
|
||||
projects: map[uuid.UUID]*Project{},
|
||||
requirements: map[uuid.UUID]*Requirement{},
|
||||
issues: map[uuid.UUID]*Issue{},
|
||||
prototypes: map[uuid.UUID]*Prototype{},
|
||||
artifacts: map[uuid.UUID]*Artifact{},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *fakeRepo) cloneProject(p *Project) *Project { v := *p; return &v }
|
||||
func (r *fakeRepo) cloneReq(p *Requirement) *Requirement { v := *p; return &v }
|
||||
func (r *fakeRepo) cloneIssue(p *Issue) *Issue { v := *p; return &v }
|
||||
func (r *fakeRepo) clonePrototype(p *Prototype) *Prototype { v := *p; return &v }
|
||||
func (r *fakeRepo) cloneProject(p *Project) *Project { v := *p; return &v }
|
||||
func (r *fakeRepo) cloneReq(p *Requirement) *Requirement { v := *p; return &v }
|
||||
func (r *fakeRepo) cloneIssue(p *Issue) *Issue { v := *p; return &v }
|
||||
func (r *fakeRepo) cloneArtifact(a *Artifact) *Artifact { v := *a; return &v }
|
||||
|
||||
func (r *fakeRepo) CreateProject(_ context.Context, p *Project) (*Project, error) {
|
||||
r.mu.Lock()
|
||||
@@ -369,58 +369,63 @@ func (r *fakeRepo) ReopenIssue(_ context.Context, id uuid.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *fakeRepo) GetMaxPrototypeVersion(_ context.Context, requirementID uuid.UUID) (int, error) {
|
||||
func (r *fakeRepo) GetMaxArtifactVersion(_ context.Context, requirementID uuid.UUID, phase Phase) (int, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
maxVer := 0
|
||||
for _, x := range r.prototypes {
|
||||
if x.RequirementID == requirementID && x.Version > maxVer {
|
||||
for _, x := range r.artifacts {
|
||||
if x.RequirementID == requirementID && x.Phase == phase && x.Version > maxVer {
|
||||
maxVer = x.Version
|
||||
}
|
||||
}
|
||||
return maxVer, nil
|
||||
}
|
||||
|
||||
func (r *fakeRepo) CreatePrototype(_ context.Context, in *Prototype) (*Prototype, error) {
|
||||
func (r *fakeRepo) CreateArtifact(_ context.Context, in *Artifact) (*Artifact, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if r.createPrototypeFailOnce {
|
||||
r.createPrototypeFailOnce = false
|
||||
if r.createArtifactFailOnce {
|
||||
r.createArtifactFailOnce = false
|
||||
// 模拟真实 PG 唯一约束冲突,触发 IsUniqueViolation 重试分支。
|
||||
return nil, &pgconn.PgError{Code: pgerrcode.UniqueViolation}
|
||||
}
|
||||
for _, x := range r.prototypes {
|
||||
if x.RequirementID == in.RequirementID && x.Version == in.Version {
|
||||
for _, x := range r.artifacts {
|
||||
if x.RequirementID == in.RequirementID && x.Phase == in.Phase && x.Version == in.Version {
|
||||
return nil, &pgconn.PgError{Code: pgerrcode.UniqueViolation}
|
||||
}
|
||||
}
|
||||
in.CreatedAt = time.Now()
|
||||
r.prototypes[in.ID] = r.clonePrototype(in)
|
||||
return r.clonePrototype(in), nil
|
||||
r.artifacts[in.ID] = r.cloneArtifact(in)
|
||||
return r.cloneArtifact(in), nil
|
||||
}
|
||||
|
||||
func (r *fakeRepo) ListPrototypesByRequirement(_ context.Context, requirementID uuid.UUID) ([]*Prototype, error) {
|
||||
func (r *fakeRepo) ListArtifactsByRequirement(_ context.Context, requirementID uuid.UUID, phase Phase) ([]*Artifact, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
out := make([]*Prototype, 0)
|
||||
for _, x := range r.prototypes {
|
||||
if x.RequirementID == requirementID {
|
||||
out = append(out, r.clonePrototype(x))
|
||||
out := make([]*Artifact, 0)
|
||||
for _, x := range r.artifacts {
|
||||
if x.RequirementID == requirementID && (phase == "" || x.Phase == phase) {
|
||||
out = append(out, r.cloneArtifact(x))
|
||||
}
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool { return out[i].Version < out[j].Version })
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
if out[i].Phase != out[j].Phase {
|
||||
return out[i].Phase < out[j].Phase
|
||||
}
|
||||
return out[i].Version < out[j].Version
|
||||
})
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r *fakeRepo) GetPrototypeByVersion(_ context.Context, requirementID uuid.UUID, version int) (*Prototype, error) {
|
||||
func (r *fakeRepo) GetArtifactByVersion(_ context.Context, requirementID uuid.UUID, phase Phase, version int) (*Artifact, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
for _, x := range r.prototypes {
|
||||
if x.RequirementID == requirementID && x.Version == version {
|
||||
return r.clonePrototype(x), nil
|
||||
for _, x := range r.artifacts {
|
||||
if x.RequirementID == requirementID && x.Phase == phase && x.Version == version {
|
||||
return r.cloneArtifact(x), nil
|
||||
}
|
||||
}
|
||||
return nil, errs.New(errs.CodeNotFound, "prototype 不存在")
|
||||
return nil, errs.New(errs.CodeNotFound, "artifact 不存在")
|
||||
}
|
||||
|
||||
// spyAudit 收集所有写入的 audit entry,方便断言。
|
||||
|
||||
Reference in New Issue
Block a user