83 lines
3.2 KiB
Go
83 lines
3.2 KiB
Go
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
|
||
}
|