fix(feed): repair 2 bugs found in the Phase 2 #2 review
BUG-1 (search.py, high): the scrape search source logged one VIDEOS_SEARCH quota event PER continuation page inside the paging loop, but actions_today counts events — so a single user search that pages N times consumed N against search_daily_limit_per_user (its docstring even warns it only works for once-per-action logging). Log exactly once per request after the loop instead; the API source already logs once via record_usage (it never auto-pages). BUG-2 (Feed.tsx, medium): the optimistic-override reset effect keyed on query.dataUpdatedAt also fired on fetchNextPage (infinite scroll bumps dataUpdatedAt while page 1 is unchanged), so a just-hidden card flashed back mid-scroll. Guard with a page-count ref: only reset on a real refetch, not an append. The two override-reset effects legitimately differ now (resolves the would-be C-F1 "identical effects" cleanup). tsc green, ruff clean, localdev boots healthy.
This commit is contained in:
parent
3cbb420ece
commit
94417ada72
2 changed files with 19 additions and 4 deletions
|
|
@ -253,8 +253,6 @@ def search_youtube(
|
|||
page = yt.search_videos(term, page_token=next_cursor)
|
||||
else:
|
||||
page = search_scrape.search(term, continuation=next_cursor)
|
||||
# Zero-cost, but logged so the per-user daily cap above keeps counting it.
|
||||
quota.log_action(db, user.id, quota.QuotaAction.VIDEOS_SEARCH)
|
||||
except (YouTubeError, search_scrape.ScrapeError) as exc:
|
||||
if collected:
|
||||
break # keep what we already gathered
|
||||
|
|
@ -274,6 +272,14 @@ def search_youtube(
|
|||
if source == "api" or len(collected) >= limit or not next_cursor:
|
||||
break
|
||||
|
||||
# Count this as ONE per-user search against the daily cap. The scrape source spends no
|
||||
# quota, so it never logs an event on its own; the API source already logged exactly one
|
||||
# (via record_usage — it never auto-pages). Logging once here, after a search that produced
|
||||
# at least one page (a total failure raises 502 above and never reaches this), keeps the cap
|
||||
# counting user searches instead of internal continuation pages.
|
||||
if source != "api":
|
||||
quota.log_action(db, user.id, quota.QuotaAction.VIDEOS_SEARCH)
|
||||
|
||||
ordered = collected[:limit]
|
||||
|
||||
if ordered:
|
||||
|
|
|
|||
|
|
@ -184,9 +184,18 @@ export default function Feed({
|
|||
setOverrides({});
|
||||
setSavedOverrides({});
|
||||
}, [filters]);
|
||||
// ...but NOT on infinite-scroll appends: fetchNextPage also bumps dataUpdatedAt while page 1's
|
||||
// rows are unchanged, so clearing overrides there would make a just-hidden card flash back.
|
||||
// Only a real refetch (page count doesn't grow) is authoritative.
|
||||
const pagesLenRef = useRef(0);
|
||||
useEffect(() => {
|
||||
const len = query.data?.pages?.length ?? 0;
|
||||
const appended = len > pagesLenRef.current;
|
||||
pagesLenRef.current = len;
|
||||
if (!appended) {
|
||||
setOverrides({});
|
||||
setSavedOverrides({});
|
||||
}
|
||||
}, [query.dataUpdatedAt]);
|
||||
|
||||
const countQuery = useQuery({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue