package repository import ( "backend/pkg/notification/domain/entity" "context" "github.com/gocql/gocql" ) type NotificationRepository interface { NotificationEventRepository UserNotificationRepository NotificationCursorRepository } // ---- 1. Event ---- // 專心管「事件本體」,fan-out 前先寫這張。 // 通常由上游 domain event consumer 呼叫 Create。 type QueryNotificationEventParam struct { ObjectID *string ObjectType *string Limit *int } type NotificationEventRepository interface { // Create 建立一筆新的 NotificationEvent。 Create(ctx context.Context, e *entity.NotificationEvent) error // GetByID 依 EventID 取得事件。 GetByID(ctx context.Context, id string) (*entity.NotificationEvent, error) // ListByObject 依 object_type + object_id 查詢相關事件(選用,debug / 後台用)。 ListByObject(ctx context.Context, param QueryNotificationEventParam) ([]*entity.NotificationEvent, error) } // ---- 2. 使用者通知:user_notification ---- // 管使用者的小鈴鐺 row,fan-out 之後用這個寫入。 // ListLatestOptions 查列表用的參數 type ListLatestOptions struct { UserID string Buckets []string // e.g. []string{"202511", "202510"} Limit int // 建議在 service 層限制最大值,例如 <= 100 } type UserNotificationRepository interface { // CreateUserNotification 建立單一通知(針對某一個 user)。 // 由呼叫端決定 bucket 與 TTL 秒數。 CreateUserNotification(ctx context.Context, n *entity.UserNotification, ttlSeconds int) error // BulkCreate 批次建立多筆通知(fan-out worker 使用)。 // 一般期望要嘛全部成功要嘛全部失敗。 BulkCreate(ctx context.Context, list []*entity.UserNotification, ttlSeconds int) error // ListLatest 取得某 user 最新的通知列表(小鈴鐺拉下來用)。 ListLatest(ctx context.Context, opt ListLatestOptions) ([]*entity.UserNotification, error) // MarkRead 將單一通知設為已讀。 // 用 (user_id, bucket, ts) 精準定位那一筆資料。 MarkRead(ctx context.Context, userID, bucket string, ts gocql.UUID) error // MarkAllRead 將指定 buckets 範圍內的通知設為已讀。 // 常見用法:最近幾個 bucket(例如最近 30 天)全部標為已讀。 // Cassandra 不適合全表掃描,實作時可分批 select 再 update。 MarkAllRead(ctx context.Context, userID string, buckets []string) error // CountUnreadApprox 回傳未讀數(允許是近似值)。 // 實作方式可以是: // - 掃少量 buckets 中 status='UNREAD' 的 row,然後在應用端計算 // - 或讀取外部 counter(Redis / 另一張 counter table) CountUnreadApprox(ctx context.Context, userID string, buckets []string) (int64, error) } // ---- 3. NotificationCursorRepository ---- // 管 last_seen 光標,用來減少大量「每一筆更新已讀」的成本。 type NotificationCursorRepository interface { // GetCursor 取得某 user 的光標,如果不存在可以回傳 (nil, nil)。 GetCursor(ctx context.Context, userID string) (*entity.NotificationCursor, error) // UpsertCursor 新增或更新光標。 // 一般在使用者打開通知列表、或捲到最上面時更新。 UpsertCursor(ctx context.Context, cursor *entity.NotificationCursor) error }