Class NotificationStore

java.lang.Object
su.onno.ui.notifications.NotificationStore

public class NotificationStore extends Object
Persistence for onno_notifications: the framework-owned, per-user notification timeline behind the /api/notifications endpoint. Like CommentService's onno_comments, it is infrastructure — created with a plain CREATE TABLE IF NOT EXISTS at startup rather than through the metadata diff engine, and never modelled, navigated, or served by the generic REST catalog API.

Rows are keyed for reading by _recipient and ordered newest-first. The feed is keyset-paginated on (_created_at DESC, _id DESC) with an opaque cursor, so a client scrolls the history with no offset arithmetic. "Read" is a nullable _read_at timestamp; unread rows are those with _read_at IS NULL.

Timestamps are Instants carried through plain TIMESTAMP columns via Timestamp on write and getTimestamp().toInstant() on read, the same zone-symmetric round-trip the comments store uses (#177).

  • Constructor Details

    • NotificationStore

      public NotificationStore(org.jdbi.v3.core.Jdbi jdbi)
  • Method Details

    • insert

      public Notification insert(String recipientId, String type, String title, String body, String link, String actorId, String actorName, String actorAvatar)
      Persist a new notification and return it as stored.
    • list

      public NotificationStore.Page list(String recipientId, boolean unreadOnly, String cursor, int limit)
      One newest-first window of a recipient's timeline. unreadOnly restricts to unread rows; cursor (from a previous NotificationStore.Page.nextCursor()) resumes after the last row returned; limit caps the window. Never returns another user's rows.
    • unreadCount

      public int unreadCount(String recipientId)
      How many of a recipient's notifications are still unread — the badge count.
    • distinctTypes

      public List<String> distinctTypes(String recipientId)
      The distinct notification types this recipient actually has, most-recent-first. Drives the panel's filter tabs: a tab exists for a type only once the user has a notification of it, so the tab set is fully modular — a custom producer's type gets a tab with no config, and a disabled built-in source (its type no longer produced) drops out as its old notifications age out.
    • markRead

      public boolean markRead(UUID id, String recipientId)
      Mark one notification read, but only if it belongs to recipientId (a user can't read another's). Returns false when it doesn't exist, isn't theirs, or was already read.
    • markAllRead

      public int markAllRead(String recipientId)
      Mark every unread notification of a recipient read; returns how many were flipped.
    • pruneReadBefore

      public int pruneReadBefore(Instant cutoff)
      Delete read notifications older than the cutoff — the retention sweep. Returns rows removed.