Skip to content

Home reads sys_inbox_message twice — the bell's poll and useHomeInbox each issue their own query #4225

Description

@yinlianghui

Found while implementing #4197 (PR #4223). Not fixed there — out of scope for that card, which covers the approvals and sys_activity feeds.

What

On /home two consumers mount in one tree and each issues its own sys_inbox_message read:

consumer query cadence
bell poll — layout/AppHeader.tsx $filter: {user_id}, $orderby: {created_at: desc}, $top: 20, joined with sys_notification_receipt ($top: 200) for read-state every 10s
hooks/useHomeInbox.ts → Home's To-do card $filter: {user_id}, $orderby: {created_at: desc}, $top: limit (default 5) once on mount

So a Home page load issues both, and the bell's copy repeats every 10 seconds.

Why it exists

Pre-existing, and a side effect of the fix sequence rather than of any one change. #4199 un-gated the bell's inbox poll so the Notifications tab would fill in off-app — correctly — but did not merge it with Home's existing read. #4197 then shared the other two feeds (approvals and sys_activity) through hooks/sharedUserFeeds.ts; the inbox read was deliberately left out because the two consumers ask genuinely different questions there, unlike the other two feeds where the queries were byte-identical.

Observation-class, not a defect

Both consumers show correct data today. Nothing is stale, nothing disagrees — the badge's unread arithmetic lives entirely on the bell's side, and Home's card only lists titles. The cost is one extra round trip per Home load plus a 10s poll that partly overlaps it. Filing it so the duplication is recorded rather than rediscovered, not because a user is currently hitting a bug.

Why it is not a trivial merge

Home's rows are a strict prefix of the bell's superset (same object, same filter, same ordering, smaller $top), so one read could serve both. But:

  • the bell additionally reads sys_notification_receipt and joins it for is_read; Home needs none of that;
  • the bell maps to a row shape carrying notification_id / receipt_id for mark-read, Home to {id, title, actionUrl, createdAt} with a title-dedupe pass;
  • $top differs (20 vs limit), so a shared store would have to hold the superset and let Home slice — which is exactly the shape sharedUserFeeds already uses for activity, where Home filters the bell's rows at its own call site.

That last point is the suggested route: extend sharedUserFeeds with an inbox feed holding the bell's 20 merged rows, have Home derive its five from them. The merge is mechanical but it touches mark-read, so it deserves its own change and its own tests rather than riding along.

Pointers

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions