Skip to content

Unread notification count cannot be made accurate from the current API #181

Description

@aquie00t

Raised from the client side while fixing a badge bug (tdn-client#99). That PR stops the count from being corrupted, but it cannot make it correct — the API does not expose enough for that.

Where the count comes from today

There is no unread-count endpoint, so the client derives one:

  1. GET /notifications?page=1&limit=20 on boot → count the entries with isRead: false
  2. +1 for each realtime frame on /realtime/ws
  3. 0 after mark-all-read

Two consequences

1. More than 20 unread undercounts. The badge only ever sees the first page, so a user with 35 unread sees at most 20. Paginating cannot fix it: the client now deliberately ignores appended pages, because recounting across them was destroying the realtime increments (that was the bug in the linked PR).

2. Realtime notifications cannot enter the list. The socket frame is:

{ type, issuerId, postId? }

but rendering a notification needs username, avatarUrl, createdAt, isRead, referenceId, recipientId. So an arriving notification can only move a counter — it cannot be shown until the list is refetched. The client has an unused addNotification action sitting there waiting for a payload it can actually use.

Either of these would resolve it

Option A — an unread-count endpoint. GET /notifications/unread-count{ count: number }. Smallest change. Given that notifications are only ever marked read in bulk, this should be a single count of rows newer than the user's last mark-all-read timestamp. The client would call it on boot and after mark-all-read, and stop deriving the number from a page of results.

Option B — a full notification in the realtime frame. Send the same shape GET /notifications returns. The client can then insert it into the list and derive the count honestly, and the badge stays right without polling. More useful long term, since it also makes new notifications appear live instead of only after a refetch.

A gets the badge correct; B gets the badge correct and makes the feed live. If only one is worth doing, A is the cheaper fix and B is the better one.

Not urgent

The client-side corruption is fixed, so the badge is stable and correct for the common case (≤20 unread). This is about the remaining inaccuracy — no rush, just recording it so it is not rediscovered later.

Context: notifications currently support bulk mark-as-read only, which was a deliberate scope decision — this issue assumes that stays.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions