You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Even once #36 makes loads instant, the feed is frozen at page-open time. A new PR, mention, or message won't show up until the user manually reloads. The user has $\geq$1 active background watcher (PR Watcher polls every 120s) — the Signal Feed should keep pace.
Goal
Backend background poller refreshes every user's signal-feed cache every 120s, mirroring the pr_watcher.py shape. Frontend setInterval re-polls on the same cadence and swaps in fresh data silently (no spinner, no loading flicker).
Per-(user, service) try/except so a Slack failure doesn't kill that user's Gmail/GitHub refresh
Lifespan wiring in backend/app/main.py mirrors the existing PR_WATCHER_ENABLED env gate: FEED_POLLER_ENABLED=true (added to backend/.env.example)
Frontend interval
In app/src/pages/Agents.tsx, add a second effect alongside the mount fetch:
useEffect(()=>{constid=setInterval(()=>{Promise.allSettled([fetchSlackMessages,fetchGmailMessages,fetchGithubActivity]).then(/* reuse mount-effect setters, no setFeedLoading */)},120_000)return()=>clearInterval(id)},[])
UX notes:
No spinner on tick — page must not flash loading state on the auto-refresh
React key stability — rows already keyed by item.id, swap is in-place
Gate the existing filter-reset effect (useEffect(() => { setGhCategory('all'); setGhRepo('all') }, [githubData])) so it only resets on initial population, not every tick — otherwise the user's pinned filter resets every 2 min
Problem
Even once #36 makes loads instant, the feed is frozen at page-open time. A new PR, mention, or message won't show up until the user manually reloads. The user has $\geq$1 active background watcher (PR Watcher polls every 120s) — the Signal Feed should keep pace.
Goal
Backend background poller refreshes every user's signal-feed cache every 120s, mirroring the
pr_watcher.pyshape. FrontendsetIntervalre-polls on the same cadence and swaps in fresh data silently (no spinner, no loading flicker).Approach
Backend poller (mirrors
backend/app/services/pr_watcher.py)backend/app/services/feed_poller.py(~100 lines)CredentialStorefeed_fetchers.py(from perf: cache Signal Feed for instant loads #36), write tosignal_feed_cachebackend/app/main.pymirrors the existingPR_WATCHER_ENABLEDenv gate:FEED_POLLER_ENABLED=true(added tobackend/.env.example)Frontend interval
In
app/src/pages/Agents.tsx, add a second effect alongside the mount fetch:UX notes:
item.id, swap is in-placeuseEffect(() => { setGhCategory('all'); setGhRepo('all') }, [githubData])) so it only resets on initial population, not every tick — otherwise the user's pinned filter resets every 2 minFiles
backend/app/services/feed_poller.pybackend/tests/test_feed_poller.py(mirrortest_pr_watcher.py)backend/app/main.py— lifespan wires the pollerbackend/.env.example— addFEED_POLLER_ENABLED=trueapp/src/pages/Agents.tsx— 120s interval effect + filter-reset gatingAcceptance
feed_poller: tick firedevery 120s/agents, a new PR opened in a watched repo appears within one poll cycle without manual reloadFEED_POLLER_ENABLED=falsedisables the poller cleanlyOut of scope
last_seen_atgating when user count grows past a handful)Related
Parent: #36 (caching layer)