Files
kandev/apps/backend/internal/gitlab/service_watch_reset.go
T
2026-07-21 23:24:22 +01:00

162 lines
4.6 KiB
Go

package gitlab
import (
"context"
"errors"
"go.uber.org/zap"
"github.com/kandev/kandev/internal/watchreset"
)
type reviewWatchResetter struct {
store *Store
watchID string
}
func (r reviewWatchResetter) ListTaskIDs(ctx context.Context) ([]string, error) {
return r.store.ListReviewMRTaskIDsByWatch(ctx, r.watchID)
}
func (r reviewWatchResetter) Clear(ctx context.Context) error {
return r.store.ResetReviewWatchState(ctx, r.watchID)
}
type issueWatchResetter struct {
store *Store
watchID string
}
func (r issueWatchResetter) ListTaskIDs(ctx context.Context) ([]string, error) {
return r.store.ListIssueWatchTaskIDsByWatch(ctx, r.watchID)
}
func (r issueWatchResetter) Clear(ctx context.Context) error {
return r.store.ResetIssueWatchState(ctx, r.watchID)
}
func (s *Service) PreviewResetReviewWatch(ctx context.Context, watchID string) (int, error) {
store := s.requireStore()
if store == nil {
return 0, errStoreUnavailable
}
return watchreset.Preview(ctx, reviewWatchResetter{store: store, watchID: watchID})
}
func (s *Service) DisableReviewWatchWithError(ctx context.Context, watchID, cause string) error {
store := s.requireStore()
if store == nil {
return errStoreUnavailable
}
return store.DisableReviewWatchWithError(ctx, watchID, cause)
}
func (s *Service) ResetReviewWatch(ctx context.Context, watchID string) (int, error) {
store := s.requireStore()
if store == nil {
return 0, errStoreUnavailable
}
s.mu.RLock()
deleter := s.cascadeTaskDeleter
s.mu.RUnlock()
if deleter == nil {
return 0, errors.New("gitlab: cascade task deleter not wired; reset unavailable")
}
if err := ctx.Err(); err != nil {
return 0, err
}
reimportCtx := ctx
ctx = context.WithoutCancel(ctx)
invalidation, err := store.BeginReviewWatchReset(ctx, watchID)
if err != nil {
return 0, err
}
deleted := s.deleteInvalidatedWatchTasks(ctx, watchID, invalidation.TaskIDs, deleter)
err = store.FinishReviewWatchReset(ctx, watchID, invalidation.Generation)
if err == nil {
s.reimportReviewWatchAfterReset(reimportCtx, watchID)
}
return deleted, err
}
func (s *Service) reimportReviewWatchAfterReset(ctx context.Context, watchID string) {
watch, err := s.GetReviewWatch(ctx, watchID)
if err != nil || watch == nil || !watch.Enabled {
if err != nil {
s.logger.Warn("reset review watch: load for re-import", zap.String("watch_id", watchID), zap.Error(err))
}
return
}
if _, err := s.TriggerReviewWatch(ctx, watchID); err != nil {
s.logger.Warn("reset review watch: re-import failed", zap.String("watch_id", watchID), zap.Error(err))
}
}
func (s *Service) PreviewResetIssueWatch(ctx context.Context, watchID string) (int, error) {
store := s.requireStore()
if store == nil {
return 0, errStoreUnavailable
}
return watchreset.Preview(ctx, issueWatchResetter{store: store, watchID: watchID})
}
func (s *Service) DisableIssueWatchWithError(ctx context.Context, watchID, cause string) error {
store := s.requireStore()
if store == nil {
return errStoreUnavailable
}
return store.DisableIssueWatchWithError(ctx, watchID, cause)
}
func (s *Service) ResetIssueWatch(ctx context.Context, watchID string) (int, error) {
store := s.requireStore()
if store == nil {
return 0, errStoreUnavailable
}
s.mu.RLock()
deleter := s.cascadeTaskDeleter
s.mu.RUnlock()
if deleter == nil {
return 0, errors.New("gitlab: cascade task deleter not wired; reset unavailable")
}
if err := ctx.Err(); err != nil {
return 0, err
}
ctx = context.WithoutCancel(ctx)
invalidation, err := store.BeginIssueWatchReset(ctx, watchID)
if err != nil {
return 0, err
}
deleted := s.deleteInvalidatedWatchTasks(ctx, watchID, invalidation.TaskIDs, deleter)
err = store.FinishIssueWatchReset(ctx, watchID, invalidation.Generation)
return deleted, err
}
func (s *Service) deleteInvalidatedWatchTasks(ctx context.Context, watchID string, ids []string, deleter watchreset.TaskDeleter) int {
deleted := 0
for _, id := range ids {
if id == "" {
continue
}
if _, err := deleter.DeleteTaskTree(ctx, id, true); err != nil {
s.logger.Warn("watch reset: task tree cleanup failed",
zap.String("watch_id", watchID), zap.String("task_id", id), zap.Error(err))
continue
}
deleted++
}
return deleted
}
func (s *Service) deleteWatchTaskTrees(ctx context.Context, watchID string, ids []string, deleter watchreset.TaskDeleter) {
for _, id := range ids {
if id == "" {
continue
}
if _, err := deleter.DeleteTaskTree(ctx, id, true); err != nil {
s.logger.Warn("delete watch: task tree cleanup failed",
zap.String("watch_id", watchID), zap.String("task_id", id), zap.Error(err))
}
}
}