Documentation
¶
Overview ¶
Package store provides the client-side data access layer for the Xyncra messaging system, backed by SQLite via GORM.
Architecture ¶
The package centers on ClientDB, which aggregates nine domain-specific sub-stores (Conversations, Messages, UserUpdates, SyncStates, Drafts, Queue, RPCLogs, NotificationLogs). Each sub-store encapsulates all CRUD and query operations for its domain model.
This package mirrors the server-side internal/store package but is placed under pkg/ so that external client applications can import it. The three shared models (Conversation, Message, UserUpdate) are copied from internal/store/model since Go's internal/ packages cannot be imported externally.
SQLite Configuration ¶
The database is opened with PRAGMAs optimized for single-writer WAL mode:
- journal_mode=WAL — concurrent reads during writes
- busy_timeout=5000 — wait up to 5s for lock acquisition
- cache_size=-8000 — 8 MB page cache
- synchronous=NORMAL — safe with WAL
- foreign_keys=ON — enforce referential integrity
MaxOpenConns is set to 1 because SQLite uses file-level locking; multiple write connections would cause "database is locked" errors. WAL mode allows concurrent reads via a separate reader path.
Auto-Migration ¶
AutoMigrate runs automatically during New() / NewInMemory() (D-023), ensuring the schema is always up to date when the client starts.
Package store provides the client-side data access layer for the Xyncra messaging system, backed by SQLite via GORM.
Index ¶
- Constants
- Variables
- type ClientDB
- type ConversationStore
- func (cs *ConversationStore) Create(ctx context.Context, conv *model.Conversation) error
- func (cs *ConversationStore) Delete(ctx context.Context, id string) error
- func (cs *ConversationStore) Get(ctx context.Context, id string) (*model.Conversation, error)
- func (cs *ConversationStore) GetByUser(ctx context.Context, userID string, offset, limit int) ([]*model.Conversation, error)
- func (cs *ConversationStore) GetByUsers(ctx context.Context, user1, user2 string) (*model.Conversation, error)
- func (cs *ConversationStore) GetUnscoped(ctx context.Context, id string) (*model.Conversation, error)
- func (cs *ConversationStore) Restore(ctx context.Context, id string) error
- func (cs *ConversationStore) RestoreTx(ctx context.Context, tx *gorm.DB, id string) error
- func (cs *ConversationStore) SearchByTitle(ctx context.Context, userID, title string, limit int) ([]*model.Conversation, error)
- func (cs *ConversationStore) SoftDeleteTx(ctx context.Context, tx *gorm.DB, id string) error
- func (cs *ConversationStore) Update(ctx context.Context, conv *model.Conversation) error
- func (cs *ConversationStore) UpdateLastMessage(ctx context.Context, convID string, lastMessageAt time.Time, ...) error
- func (cs *ConversationStore) UpdateLastMessageTx(ctx context.Context, tx *gorm.DB, convID string, lastMessageAt time.Time, ...) error
- func (cs *ConversationStore) UpdateLastRead(ctx context.Context, convID, userID string, messageID uint32) error
- func (cs *ConversationStore) UpdateLastReadTx(ctx context.Context, tx *gorm.DB, convID, userID string, messageID uint32) error
- func (cs *ConversationStore) Upsert(ctx context.Context, conv *model.Conversation) error
- func (cs *ConversationStore) UpsertTx(ctx context.Context, tx *gorm.DB, conv *model.Conversation) error
- type DraftStore
- func (ds *DraftStore) Delete(ctx context.Context, id string) error
- func (ds *DraftStore) DeleteByConversation(ctx context.Context, conversationID string) error
- func (ds *DraftStore) GetByConversation(ctx context.Context, conversationID string) (*model.Draft, error)
- func (ds *DraftStore) List(ctx context.Context) ([]*model.Draft, error)
- func (ds *DraftStore) Save(ctx context.Context, draft *model.Draft) error
- type MessageStore
- func (ms *MessageStore) CountUnread(ctx context.Context, convID string, afterMessageID uint32) (int64, error)
- func (ms *MessageStore) Create(ctx context.Context, msg *model.Message) error
- func (ms *MessageStore) CreateOrUpdateTx(ctx context.Context, tx *gorm.DB, msg *model.Message) error
- func (ms *MessageStore) CreateTx(ctx context.Context, tx *gorm.DB, msg *model.Message) error
- func (ms *MessageStore) Delete(ctx context.Context, id string) error
- func (ms *MessageStore) DeleteByConversation(ctx context.Context, convID string) error
- func (ms *MessageStore) Get(ctx context.Context, id string) (*model.Message, error)
- func (ms *MessageStore) GetByClientMessageID(ctx context.Context, clientMessageID, senderID string) (*model.Message, error)
- func (ms *MessageStore) GetLatestToolCallingMessage(ctx context.Context, convID string) (*model.Message, error)
- func (ms *MessageStore) ListByConversation(ctx context.Context, convID string, afterMessageID uint32, limit int) ([]*model.Message, error)
- func (ms *MessageStore) ListByTimeRange(ctx context.Context, convID string, startTime, endTime time.Time, limit int) ([]*model.Message, error)
- func (ms *MessageStore) ListRecentByConversation(ctx context.Context, convID string, limit int) ([]*model.Message, error)
- func (ms *MessageStore) Restore(ctx context.Context, id string) error
- func (ms *MessageStore) RestoreByConversation(ctx context.Context, convID string) (int64, error)
- func (ms *MessageStore) SearchByConversation(ctx context.Context, convID, content string, afterMessageID uint32, limit int) ([]*model.Message, error)
- func (ms *MessageStore) SoftDeleteTx(ctx context.Context, tx *gorm.DB, id string) error
- func (ms *MessageStore) Upsert(ctx context.Context, msg *model.Message) error
- type NotificationLogFilter
- type NotificationLogStore
- func (ns *NotificationLogStore) CleanupBefore(ctx context.Context, before time.Time) (int64, error)
- func (ns *NotificationLogStore) CountBefore(ctx context.Context, before time.Time) (int64, error)
- func (ns *NotificationLogStore) ExportCSV(ctx context.Context, w io.Writer, filter NotificationLogFilter) error
- func (ns *NotificationLogStore) ExportJSON(ctx context.Context, w io.Writer, filter NotificationLogFilter) error
- func (ns *NotificationLogStore) GetLatestSeq(ctx context.Context) (uint32, error)
- func (ns *NotificationLogStore) List(ctx context.Context, filter NotificationLogFilter) ([]*model.NotificationLog, error)
- func (ns *NotificationLogStore) ListBySeqRange(ctx context.Context, startSeq, endSeq uint32) ([]*model.NotificationLog, error)
- func (ns *NotificationLogStore) Save(ctx context.Context, log *model.NotificationLog) error
- func (ns *NotificationLogStore) SaveTx(ctx context.Context, tx *gorm.DB, log *model.NotificationLog) error
- type QueueStore
- func (qs *QueueStore) Count(ctx context.Context, status string) (int64, error)
- func (qs *QueueStore) Delete(ctx context.Context, id string) error
- func (qs *QueueStore) ListPending(ctx context.Context, limit int) ([]*model.RetryTask, error)
- func (qs *QueueStore) MarkFailed(ctx context.Context, id string, lastError string) error
- func (qs *QueueStore) Save(ctx context.Context, task *model.RetryTask) error
- func (qs *QueueStore) Update(ctx context.Context, task *model.RetryTask) error
- type RPCAggregateRow
- type RPCIntervalRow
- type RPCLogFilter
- type RPCLogStore
- func (rs *RPCLogStore) Aggregate(ctx context.Context, startTime, endTime time.Time) ([]RPCAggregateRow, error)
- func (rs *RPCLogStore) AggregateByInterval(ctx context.Context, startTime, endTime time.Time, interval string) ([]RPCIntervalRow, error)
- func (rs *RPCLogStore) CleanupBefore(ctx context.Context, before time.Time) (int64, error)
- func (rs *RPCLogStore) CleanupOlderThan(ctx context.Context, retention time.Duration) (int64, error)
- func (rs *RPCLogStore) CountBefore(ctx context.Context, before time.Time) (int64, error)
- func (rs *RPCLogStore) ExportCSV(ctx context.Context, w io.Writer, filter RPCLogFilter) error
- func (rs *RPCLogStore) ExportJSON(ctx context.Context, w io.Writer, filter RPCLogFilter) error
- func (rs *RPCLogStore) GetByRequestID(ctx context.Context, requestID string) (*model.RPCLog, error)
- func (rs *RPCLogStore) List(ctx context.Context, filter RPCLogFilter) ([]*model.RPCLog, error)
- func (rs *RPCLogStore) Save(ctx context.Context, log *model.RPCLog) error
- func (rs *RPCLogStore) Update(ctx context.Context, log *model.RPCLog) error
- type RemoteCallingStore
- func (s *RemoteCallingStore) DeleteByConversation(ctx context.Context, conversationID string) error
- func (s *RemoteCallingStore) DeleteByConversationTx(tx *gorm.DB, conversationID string) error
- func (s *RemoteCallingStore) GetByConversation(ctx context.Context, conversationID string) ([]*model.RemoteCalling, error)
- func (s *RemoteCallingStore) GetPendingByConversation(ctx context.Context, conversationID string) ([]*model.RemoteCalling, error)
- func (s *RemoteCallingStore) Upsert(ctx context.Context, rc *model.RemoteCalling) error
- type SyncStateStore
- func (ss *SyncStateStore) Get(ctx context.Context, key string) (string, error)
- func (ss *SyncStateStore) GetLatestSeq(ctx context.Context) (uint32, error)
- func (ss *SyncStateStore) GetLocalMaxSeq(ctx context.Context) (uint32, error)
- func (ss *SyncStateStore) Set(ctx context.Context, key, value string) error
- func (ss *SyncStateStore) SetLatestSeq(ctx context.Context, seq uint32) error
- func (ss *SyncStateStore) SetLocalMaxSeq(ctx context.Context, seq uint32) error
- func (ss *SyncStateStore) SetLocalMaxSeqTx(ctx context.Context, tx *gorm.DB, seq uint32) error
- type UserUpdateStore
- func (us *UserUpdateStore) CleanupExpired(ctx context.Context) (int64, error)
- func (us *UserUpdateStore) CleanupExpiredBefore(ctx context.Context, before time.Time) (int64, error)
- func (us *UserUpdateStore) Create(ctx context.Context, updates []model.UserUpdate) error
- func (us *UserUpdateStore) GetLatestSeq(ctx context.Context, userID string) (uint32, error)
- func (us *UserUpdateStore) ListByUser(ctx context.Context, userID string, afterSeq uint32, limit int) ([]*model.UserUpdate, error)
- func (us *UserUpdateStore) ListByUserRange(ctx context.Context, userID string, afterSeq, maxSeq uint32) ([]*model.UserUpdate, error)
Constants ¶
const DefaultCleanupRetention = 30 * 24 * time.Hour // 30 days
DefaultCleanupRetention is the default retention period for user updates.
Variables ¶
var ( // ErrNotFound indicates that the requested record does not exist. ErrNotFound = errors.New("store: record not found") // ErrDuplicateKey indicates a unique constraint violation. ErrDuplicateKey = errors.New("store: duplicate key") // ErrForeignKeyViolation indicates a foreign key constraint violation. ErrForeignKeyViolation = errors.New("store: foreign key violation") // ErrConnectionFailed indicates a database connection failure. ErrConnectionFailed = errors.New("store: connection failed") // ErrContextDeadlineExceeded indicates the context deadline was exceeded. ErrContextDeadlineExceeded = errors.New("store: context deadline exceeded") // ErrDatabaseLocked indicates the SQLite database is locked by another writer. ErrDatabaseLocked = errors.New("store: database is locked") )
Standard errors returned by store operations.
Functions ¶
This section is empty.
Types ¶
type ClientDB ¶
type ClientDB struct {
// Conversations provides conversation-related operations.
Conversations *ConversationStore
// Messages provides message-related operations.
Messages *MessageStore
// UserUpdates provides user-update related operations.
UserUpdates *UserUpdateStore
// SyncStates provides sync state key-value operations.
SyncStates *SyncStateStore
// Drafts provides message draft operations.
Drafts *DraftStore
// Queue provides retry task queue operations.
Queue *QueueStore
// RPCLogs provides RPC log operations.
RPCLogs *RPCLogStore
// NotificationLogs provides notification log operations.
NotificationLogs *NotificationLogStore
// RemoteCallings provides remote calling operations (D-137).
RemoteCallings *RemoteCallingStore
// contains filtered or unexported fields
}
ClientDB is the top-level data access entry point for the Xyncra client. It aggregates the individual domain stores and provides SQLite-specific initialization with appropriate PRAGMAs for single-writer access.
func New ¶
New opens a SQLite database at the given path, configures PRAGMAs for single-writer WAL mode, initializes all sub-stores, and runs AutoMigrate. This is the primary constructor for production use (D-001, D-023).
func NewInMemory ¶
NewInMemory creates an in-memory SQLite database for testing. The name parameter is used to create a named shared memory database.
func (*ClientDB) AutoMigrate ¶
AutoMigrate runs GORM's auto-migration for all known models, creating or updating tables and indexes as needed.
type ConversationStore ¶
type ConversationStore struct {
// contains filtered or unexported fields
}
ConversationStore provides data access operations for the Conversation model.
func (*ConversationStore) Create ¶
func (cs *ConversationStore) Create(ctx context.Context, conv *model.Conversation) error
Create inserts a new conversation record into the database.
func (*ConversationStore) Delete ¶
func (cs *ConversationStore) Delete(ctx context.Context, id string) error
Delete performs a cascading soft delete: the conversation and all its messages are soft-deleted within a single transaction (D-013).
func (*ConversationStore) Get ¶
func (cs *ConversationStore) Get(ctx context.Context, id string) (*model.Conversation, error)
Get retrieves a conversation by its primary key. Returns ErrNotFound if no record exists.
func (*ConversationStore) GetByUser ¶
func (cs *ConversationStore) GetByUser(ctx context.Context, userID string, offset, limit int) ([]*model.Conversation, error)
GetByUser returns conversations where the given user is either UserID1 or UserID2, ordered by LastMessageAt descending, with offset/limit pagination. Soft-deleted records are excluded automatically by GORM's soft-delete plugin.
func (*ConversationStore) GetByUsers ¶
func (cs *ConversationStore) GetByUsers(ctx context.Context, user1, user2 string) (*model.Conversation, error)
GetByUsers returns the 1-on-1 conversation between user1 and user2. It checks both (user1, user2) and (user2, user1) orderings. Returns ErrNotFound if no matching conversation exists.
func (*ConversationStore) GetUnscoped ¶
func (cs *ConversationStore) GetUnscoped(ctx context.Context, id string) (*model.Conversation, error)
GetUnscoped retrieves a conversation including soft-deleted records. Returns ErrNotFound if no record exists.
func (*ConversationStore) Restore ¶
func (cs *ConversationStore) Restore(ctx context.Context, id string) error
Restore undeletes a soft-deleted conversation and cascades the restore to all its messages within a single transaction (D-015). Calling Restore on a conversation that already exists but is not soft-deleted is idempotent — it returns nil without error (D-015). Returns ErrNotFound only if the conversation does not exist at all.
func (*ConversationStore) RestoreTx ¶
RestoreTx performs cascading restore within the given transaction (D-015).
func (*ConversationStore) SearchByTitle ¶
func (cs *ConversationStore) SearchByTitle(ctx context.Context, userID, title string, limit int) ([]*model.Conversation, error)
SearchByTitle searches conversations for the given user that contain the specified title substring (case-insensitive via LIKE), ordered by LastMessageAt descending.
func (*ConversationStore) SoftDeleteTx ¶
SoftDeleteTx performs cascading soft delete within the given transaction (D-013).
func (*ConversationStore) Update ¶
func (cs *ConversationStore) Update(ctx context.Context, conv *model.Conversation) error
Update saves all fields of the conversation back to the database. It uses Unscoped() so that soft-deleted records can be updated (including clearing deleted_at to NULL when restoring a conversation).
func (*ConversationStore) UpdateLastMessage ¶
func (cs *ConversationStore) UpdateLastMessage(ctx context.Context, convID string, lastMessageAt time.Time, lastProcessedMessageID uint32) error
UpdateLastMessage updates the LastMessageAt and LastProcessedMessageID fields of the conversation identified by convID.
func (*ConversationStore) UpdateLastMessageTx ¶
func (cs *ConversationStore) UpdateLastMessageTx(ctx context.Context, tx *gorm.DB, convID string, lastMessageAt time.Time, lastProcessedMessageID uint32) error
UpdateLastMessageTx updates last message fields within the given transaction.
func (*ConversationStore) UpdateLastRead ¶
func (cs *ConversationStore) UpdateLastRead(ctx context.Context, convID, userID string, messageID uint32) error
UpdateLastRead updates the last-read message ID for the specified user. Uses MAX semantics: only advances forward, never backward (D-012). Uses a single SQL statement to avoid TOCTOU races.
func (*ConversationStore) UpdateLastReadTx ¶
func (cs *ConversationStore) UpdateLastReadTx(ctx context.Context, tx *gorm.DB, convID, userID string, messageID uint32) error
UpdateLastReadTx updates read cursor within the given transaction. Uses MAX semantics: only advances forward (D-012).
func (*ConversationStore) Upsert ¶
func (cs *ConversationStore) Upsert(ctx context.Context, conv *model.Conversation) error
Upsert creates the conversation if it does not exist, or saves (overwrites) it if it already exists. This is used by the client sync pipeline to apply conversation create events idempotently (D-045). It uses Unscoped() to also find soft-deleted records, so that restoring a previously deleted conversation correctly transitions it back to active. If a concurrent insert causes a duplicate key error, the operation retries as an update to handle the TOCTOU race between SELECT and INSERT.
func (*ConversationStore) UpsertTx ¶
func (cs *ConversationStore) UpsertTx(ctx context.Context, tx *gorm.DB, conv *model.Conversation) error
UpsertTx creates or updates a conversation within the given transaction. It uses Unscoped() to also find soft-deleted records, so that restoring a previously deleted conversation correctly transitions it back to active. If a concurrent insert causes a duplicate key error, the operation retries as an update to handle the TOCTOU race between SELECT and INSERT.
type DraftStore ¶
type DraftStore struct {
// contains filtered or unexported fields
}
DraftStore provides data access operations for message drafts. Each conversation can have at most one draft (one-draft-per-conversation).
func (*DraftStore) Delete ¶
func (ds *DraftStore) Delete(ctx context.Context, id string) error
Delete removes a draft by its primary key. Returns ErrNotFound if not found.
func (*DraftStore) DeleteByConversation ¶
func (ds *DraftStore) DeleteByConversation(ctx context.Context, conversationID string) error
DeleteByConversation removes the draft for the given conversation. Returns ErrNotFound if no draft exists.
func (*DraftStore) GetByConversation ¶
func (ds *DraftStore) GetByConversation(ctx context.Context, conversationID string) (*model.Draft, error)
GetByConversation retrieves the draft for the given conversation. Returns ErrNotFound if no draft exists.
type MessageStore ¶
type MessageStore struct {
// contains filtered or unexported fields
}
MessageStore provides data access operations for the Message model.
func (*MessageStore) CountUnread ¶
func (ms *MessageStore) CountUnread(ctx context.Context, convID string, afterMessageID uint32) (int64, error)
CountUnread returns the number of messages in the given conversation with MessageID greater than afterMessageID. Soft-deleted messages are excluded automatically by GORM's soft-delete plugin.
func (*MessageStore) CreateOrUpdateTx ¶
func (ms *MessageStore) CreateOrUpdateTx(ctx context.Context, tx *gorm.DB, msg *model.Message) error
CreateOrUpdateTx implements upsert semantics within the given transaction. If a message with the same id exists, it updates content, type, and status. Otherwise, it creates a new record. This is used by the client SDK to handle tool_calling message updates (D-141).
func (*MessageStore) Delete ¶
func (ms *MessageStore) Delete(ctx context.Context, id string) error
Delete performs a soft delete on the message identified by id.
func (*MessageStore) DeleteByConversation ¶
func (ms *MessageStore) DeleteByConversation(ctx context.Context, convID string) error
DeleteByConversation performs a soft delete on all messages belonging to the given conversation.
func (*MessageStore) Get ¶
Get retrieves a message by its primary key. Returns ErrNotFound if no record exists.
func (*MessageStore) GetByClientMessageID ¶
func (ms *MessageStore) GetByClientMessageID(ctx context.Context, clientMessageID, senderID string) (*model.Message, error)
GetByClientMessageID retrieves a message by its client-generated unique ID and sender ID (composite uniqueness). Returns ErrNotFound if no matching record exists.
func (*MessageStore) GetLatestToolCallingMessage ¶
func (ms *MessageStore) GetLatestToolCallingMessage(ctx context.Context, convID string) (*model.Message, error)
GetLatestToolCallingMessage returns the most recent tool_calling message for a conversation that is in "executing" status. This is used to associate with RemoteCalling without relying on in-memory tracker (which would be lost on server restart). Returns nil, ErrNotFound if no executing tool_calling message exists.
func (*MessageStore) ListByConversation ¶
func (ms *MessageStore) ListByConversation(ctx context.Context, convID string, afterMessageID uint32, limit int) ([]*model.Message, error)
ListByConversation returns messages for the given conversation with MessageID greater than afterMessageID, ordered by MessageID ascending.
func (*MessageStore) ListByTimeRange ¶
func (ms *MessageStore) ListByTimeRange(ctx context.Context, convID string, startTime, endTime time.Time, limit int) ([]*model.Message, error)
ListByTimeRange returns messages for the given conversation within the specified time range (inclusive), ordered by MessageID ascending.
func (*MessageStore) ListRecentByConversation ¶
func (ms *MessageStore) ListRecentByConversation(ctx context.Context, convID string, limit int) ([]*model.Message, error)
ListRecentByConversation returns the most recent messages for a conversation, ordered by MessageID descending (newest first), limited to at most limit rows. Soft-deleted messages are excluded automatically by GORM's soft-delete plugin. This is used by the Agent context manager to load conversation history.
func (*MessageStore) Restore ¶
func (ms *MessageStore) Restore(ctx context.Context, id string) error
Restore undeletes a soft-deleted message identified by id.
func (*MessageStore) RestoreByConversation ¶
RestoreByConversation restores all soft-deleted messages belonging to the given conversation. Returns the number of restored rows.
func (*MessageStore) SearchByConversation ¶
func (ms *MessageStore) SearchByConversation(ctx context.Context, convID, content string, afterMessageID uint32, limit int) ([]*model.Message, error)
SearchByConversation returns messages for the given conversation that contain the specified content substring (case-insensitive via LIKE), ordered by MessageID descending (newest first).
func (*MessageStore) SoftDeleteTx ¶
SoftDeleteTx performs a soft delete within the given transaction.
func (*MessageStore) Upsert ¶
Upsert creates the message if it does not exist, or updates it if it does. Uniqueness is determined by the composite index (client_message_id, sender_id). If a concurrent insert causes a duplicate key error, the operation retries as an update to handle the TOCTOU race between SELECT and INSERT.
type NotificationLogFilter ¶
NotificationLogFilter defines optional filters for listing notification logs.
type NotificationLogStore ¶
type NotificationLogStore struct {
// contains filtered or unexported fields
}
NotificationLogStore provides data access operations for push notification logging and deduplication.
func (*NotificationLogStore) CleanupBefore ¶
CleanupBefore hard-deletes notification logs with CreatedAt strictly before the given time. Returns the number of deleted rows.
func (*NotificationLogStore) CountBefore ¶
CountBefore returns the number of notification logs with CreatedAt strictly before the given time without deleting them.
func (*NotificationLogStore) ExportCSV ¶
func (ns *NotificationLogStore) ExportCSV(ctx context.Context, w io.Writer, filter NotificationLogFilter) error
ExportCSV writes notification logs matching the filter as CSV to the given writer.
func (*NotificationLogStore) ExportJSON ¶
func (ns *NotificationLogStore) ExportJSON(ctx context.Context, w io.Writer, filter NotificationLogFilter) error
ExportJSON writes notification logs matching the filter as JSON to the given writer.
func (*NotificationLogStore) GetLatestSeq ¶
func (ns *NotificationLogStore) GetLatestSeq(ctx context.Context) (uint32, error)
GetLatestSeq returns the highest Seq value in the notification log. Returns 0 if the log is empty.
func (*NotificationLogStore) List ¶
func (ns *NotificationLogStore) List(ctx context.Context, filter NotificationLogFilter) ([]*model.NotificationLog, error)
List returns notification logs matching the given filters, ordered by CreatedAt descending (newest first).
func (*NotificationLogStore) ListBySeqRange ¶
func (ns *NotificationLogStore) ListBySeqRange(ctx context.Context, startSeq, endSeq uint32) ([]*model.NotificationLog, error)
ListBySeqRange returns notification logs with Seq in the range [startSeq, endSeq] (inclusive), ordered by Seq ascending.
func (*NotificationLogStore) Save ¶
func (ns *NotificationLogStore) Save(ctx context.Context, log *model.NotificationLog) error
Save inserts a new notification log record.
func (*NotificationLogStore) SaveTx ¶
func (ns *NotificationLogStore) SaveTx(ctx context.Context, tx *gorm.DB, log *model.NotificationLog) error
SaveTx inserts a notification log record within the given transaction.
type QueueStore ¶
type QueueStore struct {
// contains filtered or unexported fields
}
QueueStore provides data access operations for the retry task queue.
func (*QueueStore) Delete ¶
func (qs *QueueStore) Delete(ctx context.Context, id string) error
Delete removes a retry task by its primary key.
func (*QueueStore) ListPending ¶
ListPending returns retry tasks with status "pending" and NextRetry <= now, ordered by NextRetry ascending (soonest first).
func (*QueueStore) MarkFailed ¶
MarkFailed sets the task's status to "failed" so it no longer appears in ListPending results.
type RPCAggregateRow ¶
type RPCAggregateRow struct {
Method string `json:"method"`
Count int64 `json:"count"`
Success int64 `json:"success"`
ErrorCount int64 `json:"error_count"`
AvgMs float64 `json:"avg_ms"`
}
RPCAggregateRow represents a single row in an aggregate report.
type RPCIntervalRow ¶
type RPCIntervalRow struct {
Interval string `json:"interval"` // e.g. "2026-07-09 10:00"
Method string `json:"method"`
Count int64 `json:"count"`
Success int64 `json:"success"`
ErrorCount int64 `json:"error_count"`
AvgMs float64 `json:"avg_ms"`
}
RPCIntervalRow represents aggregated RPC log statistics for a time interval.
type RPCLogFilter ¶
type RPCLogFilter struct {
StartTime *time.Time
EndTime *time.Time
Method string
StatusCode *int
StatusCodeLessThan *int // StatusCodeLessThan filters logs where status_code < value.
ConversationID string
Limit int
}
RPCLogFilter defines optional filters for listing RPC logs.
type RPCLogStore ¶
type RPCLogStore struct {
// contains filtered or unexported fields
}
RPCLogStore provides data access operations for RPC call logging.
func (*RPCLogStore) Aggregate ¶
func (rs *RPCLogStore) Aggregate(ctx context.Context, startTime, endTime time.Time) ([]RPCAggregateRow, error)
Aggregate returns per-method RPC statistics for the given time range.
func (*RPCLogStore) AggregateByInterval ¶
func (rs *RPCLogStore) AggregateByInterval(ctx context.Context, startTime, endTime time.Time, interval string) ([]RPCIntervalRow, error)
AggregateByInterval returns per-interval, per-method RPC statistics for the given time range [startTime, endTime). Supported intervals: "1m", "5m", "15m", "1h", "1d". Results are ordered by interval ASC, method ASC.
func (*RPCLogStore) CleanupBefore ¶
CleanupBefore hard-deletes RPC logs with CreatedAt strictly before the given time. Returns the number of deleted rows.
func (*RPCLogStore) CleanupOlderThan ¶
func (rs *RPCLogStore) CleanupOlderThan(ctx context.Context, retention time.Duration) (int64, error)
CleanupOlderThan hard-deletes RPC logs older than the given duration.
func (*RPCLogStore) CountBefore ¶
CountBefore returns the number of RPC logs with CreatedAt strictly before the given time without deleting them.
func (*RPCLogStore) ExportCSV ¶
func (rs *RPCLogStore) ExportCSV(ctx context.Context, w io.Writer, filter RPCLogFilter) error
ExportCSV writes RPC logs matching the filter as CSV to the given writer.
func (*RPCLogStore) ExportJSON ¶
func (rs *RPCLogStore) ExportJSON(ctx context.Context, w io.Writer, filter RPCLogFilter) error
ExportJSON writes RPC logs matching the filter as JSON to the given writer.
func (*RPCLogStore) GetByRequestID ¶
GetByRequestID retrieves an RPC log by its request ID. Returns ErrNotFound if no matching record exists.
func (*RPCLogStore) List ¶
func (rs *RPCLogStore) List(ctx context.Context, filter RPCLogFilter) ([]*model.RPCLog, error)
List returns RPC logs matching the given filters, ordered by CreatedAt descending (newest first).
type RemoteCallingStore ¶
type RemoteCallingStore struct {
// contains filtered or unexported fields
}
RemoteCallingStore handles RemoteCalling persistence for the client (D-137).
func NewRemoteCallingStore ¶
func NewRemoteCallingStore(db *gorm.DB) *RemoteCallingStore
NewRemoteCallingStore creates a new RemoteCallingStore.
func (*RemoteCallingStore) DeleteByConversation ¶
func (s *RemoteCallingStore) DeleteByConversation(ctx context.Context, conversationID string) error
DeleteByConversation deletes all RemoteCallings for a conversation.
func (*RemoteCallingStore) DeleteByConversationTx ¶
func (s *RemoteCallingStore) DeleteByConversationTx(tx *gorm.DB, conversationID string) error
DeleteByConversationTx deletes all RemoteCallings for a conversation within a transaction.
func (*RemoteCallingStore) GetByConversation ¶
func (s *RemoteCallingStore) GetByConversation(ctx context.Context, conversationID string) ([]*model.RemoteCalling, error)
GetByConversation returns all RemoteCallings for a conversation.
func (*RemoteCallingStore) GetPendingByConversation ¶
func (s *RemoteCallingStore) GetPendingByConversation(ctx context.Context, conversationID string) ([]*model.RemoteCalling, error)
GetPendingByConversation returns all pending RemoteCallings for a conversation.
func (*RemoteCallingStore) Upsert ¶
func (s *RemoteCallingStore) Upsert(ctx context.Context, rc *model.RemoteCalling) error
Upsert creates or updates a RemoteCalling (idempotent by ID).
type SyncStateStore ¶
type SyncStateStore struct {
// contains filtered or unexported fields
}
SyncStateStore provides key-value data access for client-side synchronization state tracking (e.g. local_max_seq, latest_seq).
func (*SyncStateStore) Get ¶
Get retrieves the value for the given key. Returns ErrNotFound if the key does not exist.
func (*SyncStateStore) GetLatestSeq ¶
func (ss *SyncStateStore) GetLatestSeq(ctx context.Context) (uint32, error)
GetLatestSeq returns the latest_seq value. Returns 0 if not set.
func (*SyncStateStore) GetLocalMaxSeq ¶
func (ss *SyncStateStore) GetLocalMaxSeq(ctx context.Context) (uint32, error)
GetLocalMaxSeq returns the local_max_seq value. Returns 0 if not set.
func (*SyncStateStore) Set ¶
func (ss *SyncStateStore) Set(ctx context.Context, key, value string) error
Set performs an UPSERT for the given key-value pair. If the key already exists, the value is updated; otherwise a new record is inserted.
func (*SyncStateStore) SetLatestSeq ¶
func (ss *SyncStateStore) SetLatestSeq(ctx context.Context, seq uint32) error
SetLatestSeq sets the latest_seq value.
func (*SyncStateStore) SetLocalMaxSeq ¶
func (ss *SyncStateStore) SetLocalMaxSeq(ctx context.Context, seq uint32) error
SetLocalMaxSeq sets the local_max_seq value.
func (*SyncStateStore) SetLocalMaxSeqTx ¶
SetLocalMaxSeqTx sets local_max_seq within the given transaction.
type UserUpdateStore ¶
type UserUpdateStore struct {
// contains filtered or unexported fields
}
UserUpdateStore provides data access operations for the UserUpdate model.
func (*UserUpdateStore) CleanupExpired ¶
func (us *UserUpdateStore) CleanupExpired(ctx context.Context) (int64, error)
CleanupExpired hard-deletes all user updates older than DefaultCleanupRetention (30 days). Convenience wrapper around CleanupExpiredBefore.
func (*UserUpdateStore) CleanupExpiredBefore ¶
func (us *UserUpdateStore) CleanupExpiredBefore(ctx context.Context, before time.Time) (int64, error)
CleanupExpiredBefore hard-deletes all user updates with CreatedAt strictly before the given time. Returns the number of deleted rows.
func (*UserUpdateStore) Create ¶
func (us *UserUpdateStore) Create(ctx context.Context, updates []model.UserUpdate) error
Create inserts a batch of user update records using CreateInBatches (batch size 100) for efficient bulk insertion.
func (*UserUpdateStore) GetLatestSeq ¶
GetLatestSeq returns the highest Seq value for the given user. Returns 0 if the user has no update records.
func (*UserUpdateStore) ListByUser ¶
func (us *UserUpdateStore) ListByUser(ctx context.Context, userID string, afterSeq uint32, limit int) ([]*model.UserUpdate, error)
ListByUser returns user updates for the given userID with Seq greater than afterSeq, ordered by Seq ascending, limited to at most limit rows.
func (*UserUpdateStore) ListByUserRange ¶
func (us *UserUpdateStore) ListByUserRange(ctx context.Context, userID string, afterSeq, maxSeq uint32) ([]*model.UserUpdate, error)
ListByUserRange returns user updates for the given userID with Seq in the range (afterSeq, maxSeq] (exclusive start, inclusive end), ordered by Seq ascending.