boostorg / boostorg/website-v2

Task: Historical achievement backfill (Trigger)

Open
#2,541 0 comments 0 reactions 0 assignees View on GitHub
Phase 2
Dominant language
HTML
Stars
18
Forks
28
Avg merge
2d 12h
Merged PRs (30d)
77

Description

## Context

Automatic achievements are derived from data that already exists in the platform (library authorship,
maintenance, versioning, commits, reviews, published news posts, and future sources). Ingestion is
batch-based rather than real-time: there are no live per-row signals for automatic sources, so a
backfill process is needed to create `UserAchievement` rows from historical data and reconcile the
derived `UserBadge` state.

The backfill runs as a management command (invoked ad hoc, from an admin action, and after the weekly
release tasks), so it must be safe to re-run repeatedly without double-counting or doing unnecessary
work.

## Scope

- **`backfill_achievements` management command** that iterates each wired source
(`badges/sources.py` `BACKFILL_ITERATORS`), yielding `(user, source_object)` pairs and inserting
one `UserAchievement` per pair.
- Options: `--source ` to limit to one source, `--batch-size` for the bulk insert size, and
`--async` to queue recalculations on Celery instead of running inline.
- Insert in batches with `bulk_create(ignore_conflicts=True)`, relying on the automatic-source
unique constraint (`user`, `achievement`, `source_content_type`, `source_object_id`) for
idempotency. Do not fire per-row signals during bulk insert.
- Track only the `(user, achievement)` pairs that actually gained rows, and recalculate badges only
for those pairs, so repeated runs do not re-reconcile the whole system.
- **`recalculate_badges` management command** that rebuilds `UserBadge` state for all users/achievements
(used to reconcile after catalogue/threshold changes).
- **Celery task wrappers** for both commands and for a single `(user, achievement)` recalculation, so
long-running work runs off-request (`badges/tasks.py`).
- **Scheduling / triggers**: run the backfill after the weekly `release_tasks` and after
`update_commits`, and expose admin buttons to queue a backfill or a full recalculation (debounced so
a double click does not queue duplicate work).
- **No notifications on bulk paths**: recalculations triggered by backfill/rebuild must not send
badge-awarded emails (`notify=False`).

## Out of Scope

- Any user-facing communication about newly awarded badges (tracked separately).
- Sources that are not yet wired (they are added by their own source tickets and picked up here
automatically once registered).

## Acceptance Criteria

- [ ] `backfill_achievements` creates `UserAchievement` rows for every wired source and is idempotent -
a second run reports zero new rows and recalculates nothing
- [ ] `--source`, `--batch-size`, and `--async` options work as described
- [ ] Only `(user, achievement)` pairs that gained rows are recalculated
- [ ] Bulk insert does not trigger per-row signals and does not send emails
- [ ] `recalculate_badges` rebuilds `UserBadge` state and is idempotent
- [ ] Celery wrappers exist for backfill, full recalculation, and per-pair recalculation
- [ ] Backfill runs after `release_tasks` and `update_commits`; admin buttons queue the work and are
debounced against duplicate submissions
- [ ] Tests cover: first-run inserts and awards, second-run no-ops, per-pair recalculation selection,
and the no-email guarantee on bulk paths

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the wired source iterators in badges/sources.py, then inspect the management-command entry points and task wrappers in badges/tasks.py. Trace release_tasks, update_commits, and the admin actions to understand each trigger. Done means the listed commands, batching, recalculation selection, async paths, triggers, debouncing, and acceptance tests all work without duplicate rows or emails.

Written by the indexing model from the issue text.

Assessment

Domain
backend, database, devops
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.