134 lines
4.2 KiB
Go
134 lines
4.2 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/kandev/kandev/internal/watchreset"
|
|
)
|
|
|
|
// --- Issue watch reset ---
|
|
|
|
// githubIssueWatchResetter is the watchreset.Resetter adapter for a single
|
|
// GitHub issue watch. Closes over the store and watch ID so the shared
|
|
// watchreset.Run helper stays integration-agnostic.
|
|
type githubIssueWatchResetter struct {
|
|
store *Store
|
|
watchID string
|
|
}
|
|
|
|
func (r *githubIssueWatchResetter) ListTaskIDs(ctx context.Context) ([]string, error) {
|
|
return r.store.ListIssueWatchTaskIDsByWatch(ctx, r.watchID)
|
|
}
|
|
|
|
func (r *githubIssueWatchResetter) Clear(ctx context.Context) error {
|
|
return r.store.ResetIssueWatchState(ctx, r.watchID)
|
|
}
|
|
|
|
// PreviewResetIssueWatch returns how many tasks ResetIssueWatch would
|
|
// cascade-delete. Used by the frontend to populate the confirmation dialog.
|
|
func (s *Service) PreviewResetIssueWatch(ctx context.Context, watchID string) (int, error) {
|
|
if s.store == nil {
|
|
return 0, errStoreUnavailable
|
|
}
|
|
watch, err := s.GetIssueWatch(ctx, watchID)
|
|
if err != nil || watch == nil {
|
|
return 0, err
|
|
}
|
|
return watchreset.Preview(ctx, &githubIssueWatchResetter{store: s.store, watchID: watchID})
|
|
}
|
|
|
|
// ResetIssueWatch is destructive: cascade-deletes every task previously
|
|
// created by the issue watch (including archived), wipes the per-watch
|
|
// dedup rows, and nulls last_polled_at so the next poll re-imports every
|
|
// currently-matching issue. Returns the count of tasks deleted.
|
|
func (s *Service) ResetIssueWatch(ctx context.Context, watchID string) (int, error) {
|
|
if s.store == nil {
|
|
return 0, errStoreUnavailable
|
|
}
|
|
watch, err := s.GetIssueWatch(ctx, watchID)
|
|
if err != nil || watch == nil {
|
|
return 0, err
|
|
}
|
|
s.mu.Lock()
|
|
td := s.cascadeTaskDeleter
|
|
s.mu.Unlock()
|
|
if td == nil {
|
|
return 0, errors.New("github: cascade task deleter not wired; reset unavailable")
|
|
}
|
|
res, err := watchreset.Run(ctx,
|
|
&githubIssueWatchResetter{store: s.store, watchID: watchID},
|
|
td, s.logger)
|
|
return res.TasksDeleted, err
|
|
}
|
|
|
|
// --- Review watch reset ---
|
|
|
|
// githubReviewWatchResetter is the watchreset.Resetter adapter for a single
|
|
// GitHub review watch.
|
|
type githubReviewWatchResetter struct {
|
|
store *Store
|
|
watchID string
|
|
}
|
|
|
|
func (r *githubReviewWatchResetter) ListTaskIDs(ctx context.Context) ([]string, error) {
|
|
return r.store.ListReviewPRTaskIDsByWatch(ctx, r.watchID)
|
|
}
|
|
|
|
func (r *githubReviewWatchResetter) Clear(ctx context.Context) error {
|
|
return r.store.ResetReviewWatchState(ctx, r.watchID)
|
|
}
|
|
|
|
// PreviewResetReviewWatch returns how many tasks ResetReviewWatch would
|
|
// cascade-delete. Used by the frontend to populate the confirmation dialog.
|
|
func (s *Service) PreviewResetReviewWatch(ctx context.Context, watchID string) (int, error) {
|
|
if s.store == nil {
|
|
return 0, errStoreUnavailable
|
|
}
|
|
return watchreset.Preview(ctx, &githubReviewWatchResetter{store: s.store, watchID: watchID})
|
|
}
|
|
|
|
// ResetReviewWatch is destructive: cascade-deletes every task previously
|
|
// created by the review watch (including archived), wipes the per-watch
|
|
// dedup rows, and then schedules the watch to re-run so currently-matching
|
|
// PRs are published for task creation. Returns the count of tasks deleted.
|
|
func (s *Service) ResetReviewWatch(ctx context.Context, watchID string) (int, error) {
|
|
if s.store == nil {
|
|
return 0, errStoreUnavailable
|
|
}
|
|
s.mu.Lock()
|
|
td := s.cascadeTaskDeleter
|
|
s.mu.Unlock()
|
|
if td == nil {
|
|
return 0, errors.New("github: cascade task deleter not wired; reset unavailable")
|
|
}
|
|
res, err := watchreset.Run(ctx,
|
|
&githubReviewWatchResetter{store: s.store, watchID: watchID},
|
|
td, s.logger)
|
|
if err != nil {
|
|
return res.TasksDeleted, err
|
|
}
|
|
go s.reimportReviewWatchAfterReset(context.Background(), watchID)
|
|
return res.TasksDeleted, nil
|
|
}
|
|
|
|
func (s *Service) reimportReviewWatchAfterReset(ctx context.Context, watchID string) {
|
|
watch, err := s.GetReviewWatch(ctx, watchID)
|
|
if err != nil {
|
|
s.logger.Warn("reset review watch: could not load watch for re-import",
|
|
zap.String("watch_id", watchID),
|
|
zap.Error(err))
|
|
return
|
|
}
|
|
if watch == nil || !watch.Enabled {
|
|
return
|
|
}
|
|
if _, err := s.TriggerReviewWatch(ctx, watch); err != nil {
|
|
s.logger.Warn("reset review watch: re-import failed",
|
|
zap.String("watch_id", watch.ID),
|
|
zap.Error(err))
|
|
}
|
|
}
|