Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ All notable changes to Atlas Insight are documented here.

## Unreleased

- Changes land here before release tagging.
### Fixed

- **Spotlight gap on selection failure** — `sync_spotlight_watches` now falls back to the most recent pick when no current-week record exists, preventing the daily safety-net task from clearing watches when the weekly selection task fails or hasn't run yet. Previously this left the site with no spotlight until manual intervention.
- `select_repo_of_week` Celery task now retries up to 3 times (5 min apart) on transient failures before giving up.
2 changes: 1 addition & 1 deletion backend/apps/analysis/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ def _dir_size(path: str) -> int:
logger.info('Clone eviction complete: %d clones removed', evicted)


@shared_task
@shared_task(autoretry_for=(Exception,), max_retries=3, default_retry_delay=300)
Comment thread
LunarVagabond marked this conversation as resolved.
def select_repo_of_week():
"""Weekly task: pick a public repo for the spotlight using a fair-rotation, weighted algorithm.

Expand Down
33 changes: 33 additions & 0 deletions backend/apps/analysis/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,39 @@ def test_preserves_manual_watch_on_unrelated_repo(self, public_repo, completed_r
assert manual.is_watched is True


# ---------------------------------------------------------------------------
# sync_spotlight_watches — fallback behaviour
# ---------------------------------------------------------------------------

@pytest.mark.django_db
class TestSyncSpotlightWatches:
def test_preserves_previous_spotlight_when_no_current_week_pick(self, db):
"""Daily sync must not clear the old spotlight when weekly selection hasn't run yet."""
from datetime import date, timedelta

from apps.repositories.models import AnalysisRun, RepoOfTheWeek, Repository
from apps.repositories.spotlight import sync_spotlight_watches

repo = Repository.objects.create(
url='https://github.com/test/prev',
owner='test',
name='prev',
is_watched=True,
watch_reason='spotlight',
)
AnalysisRun.objects.create(repo=repo, status='completed')
today = date.today()
prev_week = today - timedelta(days=today.weekday() + 7)
RepoOfTheWeek.objects.create(repo=repo, week_start=prev_week, pick_number=1)

# No current-week record exists — simulates failed weekly selection
sync_spotlight_watches()

repo.refresh_from_db()
assert repo.is_watched is True
assert repo.watch_reason == 'spotlight'


# ---------------------------------------------------------------------------
# reanalyze_watched_repos
# ---------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions backend/apps/repositories/spotlight.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ def sync_spotlight_watches(week_start: date | None = None) -> None:
.select_related('repo')
.first()
)
if current is None:
# No pick yet for this week — fall back to most recent so daily sync
# doesn't clear watches when weekly selection hasn't run or failed.
current = RepoOfTheWeek.objects.select_related('repo').first()
current_repo_id = current.repo_id if current else None

Repository.objects.filter(watch_reason='spotlight').exclude(pk=current_repo_id).update(
Expand Down