Documentation
¶
Overview ¶
Package store provides database access for msgvault.
Index ¶
- Constants
- func IsSystemLabel(sourceLabelID string) bool
- type APIAttachment
- type APIMessage
- type Checkpoint
- type Label
- type LabelInfo
- type Message
- type MessageInspection
- type Participant
- type Source
- type Stats
- type Store
- func (s *Store) AddMessageLabels(messageID int64, labelIDs []int64) error
- func (s *Store) BackfillFTS(progress func(done, total int64)) (int64, error)
- func (s *Store) Close() error
- func (s *Store) CompleteSync(syncID int64, finalHistoryID string) error
- func (s *Store) CountMessagesForSource(sourceID int64) (int64, error)
- func (s *Store) CountMessagesWithRaw(sourceID int64) (int64, error)
- func (s *Store) DB() *sql.DB
- func (s *Store) EnsureConversation(sourceID int64, sourceConversationID, title string) (int64, error)
- func (s *Store) EnsureLabel(sourceID int64, sourceLabelID, name, labelType string) (int64, error)
- func (s *Store) EnsureLabelsBatch(sourceID int64, labels map[string]LabelInfo) (map[string]int64, error)
- func (s *Store) EnsureParticipant(email, displayName, domain string) (int64, error)
- func (s *Store) EnsureParticipantsBatch(addresses []mime.Address) (map[string]int64, error)
- func (s *Store) FTS5Available() bool
- func (s *Store) FailSync(syncID int64, errMsg string) error
- func (s *Store) GetActiveSync(sourceID int64) (*SyncRun, error)
- func (s *Store) GetLastSuccessfulSync(sourceID int64) (*SyncRun, error)
- func (s *Store) GetMessage(id int64) (*APIMessage, error)
- func (s *Store) GetMessageRaw(messageID int64) ([]byte, error)
- func (s *Store) GetOrCreateSource(sourceType, identifier string) (*Source, error)
- func (s *Store) GetRandomMessageIDs(sourceID int64, limit int) ([]int64, error)
- func (s *Store) GetSourceByIdentifier(identifier string) (*Source, error)
- func (s *Store) GetStats() (*Stats, error)
- func (s *Store) InitSchema() error
- func (s *Store) InspectAttachment(sourceMessageID string) (filename, mimeType string, err error)
- func (s *Store) InspectBodyText(sourceMessageID string) (string, error)
- func (s *Store) InspectDeletedFromSource(sourceMessageID string) (bool, error)
- func (s *Store) InspectDisplayName(sourceMessageID, recipientType, email string) (string, error)
- func (s *Store) InspectMessage(sourceMessageID string) (*MessageInspection, error)
- func (s *Store) InspectMessageDates(sourceMessageID string) (sentAt, internalDate string, err error)
- func (s *Store) InspectParticipantDisplayName(email string) (string, error)
- func (s *Store) InspectRawDataExists(sourceMessageID string) (bool, error)
- func (s *Store) InspectRecipientCount(sourceMessageID, recipientType string) (int, error)
- func (s *Store) InspectThreadSourceID(sourceMessageID string) (string, error)
- func (s *Store) ListMessages(offset, limit int) ([]APIMessage, int64, error)
- func (s *Store) ListSources(sourceType string) ([]*Source, error)
- func (s *Store) MarkMessageDeleted(sourceID int64, sourceMessageID string) error
- func (s *Store) MarkMessageDeletedByGmailID(permanent bool, gmailID string) error
- func (s *Store) MarkMessagesDeletedBatch(sourceID int64, sourceMessageIDs []string) error
- func (s *Store) MarkMessagesDeletedByGmailIDBatch(gmailIDs []string) error
- func (s *Store) MessageExistsBatch(sourceID int64, sourceMessageIDs []string) (map[string]int64, error)
- func (s *Store) NeedsFTSBackfill() bool
- func (s *Store) Rebind(query string) string
- func (s *Store) RemoveMessageLabels(messageID int64, labelIDs []int64) error
- func (s *Store) ReplaceMessageLabels(messageID int64, labelIDs []int64) error
- func (s *Store) ReplaceMessageRecipients(messageID int64, recipientType string, participantIDs []int64, ...) error
- func (s *Store) SearchMessages(query string, offset, limit int) ([]APIMessage, int64, error)
- func (s *Store) StartSync(sourceID int64, syncType string) (int64, error)
- func (s *Store) UpdateSourceDisplayName(sourceID int64, displayName string) error
- func (s *Store) UpdateSourceSyncCursor(sourceID int64, cursor string) error
- func (s *Store) UpdateSyncCheckpoint(syncID int64, cp *Checkpoint) error
- func (s *Store) UpsertAttachment(messageID int64, filename, mimeType, storagePath, contentHash string, size int) error
- func (s *Store) UpsertFTS(messageID int64, subject, bodyText, fromAddr, toAddrs, ccAddrs string) error
- func (s *Store) UpsertMessage(msg *Message) (int64, error)
- func (s *Store) UpsertMessageBody(messageID int64, bodyText, bodyHTML sql.NullString) error
- func (s *Store) UpsertMessageRaw(messageID int64, rawData []byte) error
- type SyncRun
Constants ¶
const ( SyncStatusRunning = "running" SyncStatusCompleted = "completed" SyncStatusFailed = "failed" )
Variables ¶
This section is empty.
Functions ¶
func IsSystemLabel ¶ added in v0.4.0
IsSystemLabel returns true if the given Gmail label ID represents a system label.
Types ¶
type APIAttachment ¶ added in v0.7.0
APIAttachment represents attachment metadata for API responses.
type APIMessage ¶ added in v0.7.0
type APIMessage struct {
ID int64
Subject string
From string
To []string
SentAt time.Time
Snippet string
Labels []string
HasAttachments bool
SizeEstimate int64
Body string
Headers map[string]string
Attachments []APIAttachment
}
APIMessage represents a message for API responses.
type Checkpoint ¶
type Checkpoint struct {
PageToken string
MessagesProcessed int64
MessagesAdded int64
MessagesUpdated int64
ErrorsCount int64
}
Checkpoint represents sync progress for resumption.
type Label ¶
type Label struct {
ID int64
SourceID sql.NullInt64
SourceLabelID sql.NullString
Name string
LabelType sql.NullString
}
Label represents a Gmail label.
type Message ¶
type Message struct {
ID int64
ConversationID int64
SourceID int64
SourceMessageID string
MessageType string // "email"
SentAt sql.NullTime
ReceivedAt sql.NullTime
InternalDate sql.NullTime
SenderID sql.NullInt64
IsFromMe bool
Subject sql.NullString
Snippet sql.NullString
SizeEstimate int64
HasAttachments bool
AttachmentCount int
DeletedAt sql.NullTime
ArchivedAt time.Time
}
Message represents a message in the database.
type MessageInspection ¶ added in v0.4.0
type MessageInspection struct {
SentAt string
InternalDate string
DeletedFromSourceAt sql.NullTime
ThreadSourceID string
BodyText string
RawDataExists bool
RecipientCounts map[string]int // recipient_type -> count
RecipientDisplayName map[string]string // "type:email" -> display_name
}
MessageInspection contains detailed message data for test assertions.
type Participant ¶
type Participant struct {
ID int64
EmailAddress sql.NullString
DisplayName sql.NullString
Domain sql.NullString
}
Participant represents a person in the participants table.
type Source ¶
type Source struct {
ID int64
SourceType string // "gmail"
Identifier string // email address
DisplayName sql.NullString
GoogleUserID sql.NullString
LastSyncAt sql.NullTime
SyncCursor sql.NullString // historyId for Gmail
CreatedAt time.Time
UpdatedAt time.Time
}
Source represents a Gmail account or other message source.
type Stats ¶
type Stats struct {
MessageCount int64
ThreadCount int64
AttachmentCount int64
LabelCount int64
SourceCount int64
DatabaseSize int64
}
Stats holds database statistics.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store provides database operations for msgvault.
func Open ¶
Open opens or creates the database at the given path. Currently only SQLite is supported. PostgreSQL URLs will return an error.
func (*Store) AddMessageLabels ¶ added in v0.7.0
AddMessageLabels adds labels to a message without removing existing ones. Uses INSERT OR IGNORE to skip labels that already exist.
func (*Store) BackfillFTS ¶ added in v0.6.4
BackfillFTS populates the FTS table from existing message data. Processes in batches to avoid blocking for minutes on large archives. The progress callback (if non-nil) is called after each batch with (position in ID range, total ID range). Each batch is committed independently so partial progress is preserved if interrupted. Returns the number of rows inserted. No-op if FTS5 is not available.
func (*Store) CompleteSync ¶
CompleteSync marks a sync as successfully completed.
func (*Store) CountMessagesForSource ¶
CountMessagesForSource returns the count of messages for a specific source (account).
func (*Store) CountMessagesWithRaw ¶
CountMessagesWithRaw returns the count of messages that have raw MIME stored.
func (*Store) EnsureConversation ¶
func (s *Store) EnsureConversation(sourceID int64, sourceConversationID, title string) (int64, error)
EnsureConversation gets or creates a conversation (thread) for a message.
func (*Store) EnsureLabel ¶
EnsureLabel gets or creates a label.
func (*Store) EnsureLabelsBatch ¶
func (s *Store) EnsureLabelsBatch(sourceID int64, labels map[string]LabelInfo) (map[string]int64, error)
EnsureLabelsBatch ensures all labels exist and returns a map of source_label_id -> internal ID.
func (*Store) EnsureParticipant ¶
EnsureParticipant gets or creates a participant by email.
func (*Store) EnsureParticipantsBatch ¶
EnsureParticipantsBatch gets or creates participants in batch. Returns a map of email -> participant ID.
func (*Store) FTS5Available ¶ added in v0.6.4
FTS5Available returns whether FTS5 full-text search is available.
func (*Store) GetActiveSync ¶
GetActiveSync returns the most recent running sync for a source, if any.
func (*Store) GetLastSuccessfulSync ¶
GetLastSuccessfulSync returns the most recent successful sync for a source.
func (*Store) GetMessage ¶ added in v0.7.0
func (s *Store) GetMessage(id int64) (*APIMessage, error)
GetMessage returns a single message with full details. Only this method accesses message_bodies (single PK lookup).
func (*Store) GetMessageRaw ¶
GetMessageRaw retrieves and decompresses the raw MIME data for a message.
func (*Store) GetOrCreateSource ¶
GetOrCreateSource gets or creates a source by type and identifier.
func (*Store) GetRandomMessageIDs ¶
GetRandomMessageIDs returns a random sample of message IDs for a source. Uses reservoir sampling with random offsets for O(limit) performance on large tables, falling back to ORDER BY RANDOM() for small tables where the overhead isn't significant.
func (*Store) GetSourceByIdentifier ¶
GetSourceByIdentifier returns a source by its identifier (email address).
func (*Store) InitSchema ¶
InitSchema initializes the database schema. This creates all tables if they don't exist.
func (*Store) InspectAttachment ¶ added in v0.6.5
InspectAttachment returns the filename and mime_type for the first attachment (by ID) of a message.
func (*Store) InspectBodyText ¶ added in v0.4.0
InspectBodyText returns the body_text for a message.
func (*Store) InspectDeletedFromSource ¶ added in v0.4.0
InspectDeletedFromSource checks whether a message has deleted_from_source_at set.
func (*Store) InspectDisplayName ¶ added in v0.4.0
InspectDisplayName returns the display name for a recipient of a message.
func (*Store) InspectMessage ¶ added in v0.4.0
func (s *Store) InspectMessage(sourceMessageID string) (*MessageInspection, error)
InspectMessage retrieves detailed message information for test assertions. This consolidates multiple schema-aware queries into a single method, keeping schema knowledge in the store package.
func (*Store) InspectMessageDates ¶ added in v0.4.0
func (s *Store) InspectMessageDates(sourceMessageID string) (sentAt, internalDate string, err error)
InspectMessageDates returns sent_at and internal_date for a message.
func (*Store) InspectParticipantDisplayName ¶ added in v0.6.5
InspectParticipantDisplayName returns the display_name from the participants table for an email.
func (*Store) InspectRawDataExists ¶ added in v0.4.0
InspectRawDataExists checks that raw MIME data exists for a message.
func (*Store) InspectRecipientCount ¶ added in v0.4.0
InspectRecipientCount returns the count of recipients of a given type for a message.
func (*Store) InspectThreadSourceID ¶ added in v0.4.0
InspectThreadSourceID returns the source_conversation_id for a message's thread.
func (*Store) ListMessages ¶ added in v0.7.0
func (s *Store) ListMessages(offset, limit int) ([]APIMessage, int64, error)
ListMessages returns a paginated list of messages with batch-loaded recipients and labels.
func (*Store) ListSources ¶ added in v0.3.0
ListSources returns all sources, optionally filtered by source type. Pass an empty string to return all sources.
func (*Store) MarkMessageDeleted ¶
MarkMessageDeleted marks a message as deleted from the source.
func (*Store) MarkMessageDeletedByGmailID ¶
MarkMessageDeletedByGmailID marks a message as deleted by its Gmail ID. This is used by the deletion executor which only has the Gmail message ID. The permanent flag indicates whether the message was permanently deleted or just trashed.
func (*Store) MarkMessagesDeletedBatch ¶ added in v0.7.0
MarkMessagesDeletedBatch marks multiple messages as deleted from the source in a single transaction.
func (*Store) MarkMessagesDeletedByGmailIDBatch ¶ added in v0.7.0
MarkMessagesDeletedByGmailIDBatch marks multiple messages as deleted by their Gmail IDs in batched UPDATE statements. Much faster than individual MarkMessageDeletedByGmailID calls because it issues one UPDATE per chunk instead of one per message.
Uses best-effort semantics: if a chunk fails, it falls back to individual updates for that chunk and continues with remaining chunks. Returns the first error encountered (if any) after processing all IDs.
func (*Store) MessageExistsBatch ¶
func (s *Store) MessageExistsBatch(sourceID int64, sourceMessageIDs []string) (map[string]int64, error)
MessageExistsBatch checks which message IDs already exist in the database. Returns a map of source_message_id -> internal message_id for existing messages.
func (*Store) NeedsFTSBackfill ¶ added in v0.6.4
NeedsFTSBackfill reports whether the FTS table needs to be populated. Uses MAX(id) comparisons (instant B-tree lookups) instead of COUNT(*) to avoid full table scans on large databases.
func (*Store) Rebind ¶
Rebind converts a query with ? placeholders to the appropriate format for the current database driver. Currently SQLite-only (no conversion needed). When PostgreSQL support is added, this will convert ? to $1, $2, etc.
func (*Store) RemoveMessageLabels ¶ added in v0.7.0
RemoveMessageLabels removes specific labels from a message.
func (*Store) ReplaceMessageLabels ¶
ReplaceMessageLabels replaces all labels for a message atomically.
func (*Store) ReplaceMessageRecipients ¶
func (s *Store) ReplaceMessageRecipients(messageID int64, recipientType string, participantIDs []int64, displayNames []string) error
ReplaceMessageRecipients replaces all recipients for a message atomically.
func (*Store) SearchMessages ¶ added in v0.7.0
SearchMessages searches messages using FTS5, with batch-loaded recipients and labels.
func (*Store) UpdateSourceDisplayName ¶ added in v0.5.0
UpdateSourceDisplayName updates the display name for a source.
func (*Store) UpdateSourceSyncCursor ¶
UpdateSourceSyncCursor updates the sync cursor (historyId) for a source.
func (*Store) UpdateSyncCheckpoint ¶
func (s *Store) UpdateSyncCheckpoint(syncID int64, cp *Checkpoint) error
UpdateSyncCheckpoint saves progress for resumption.
func (*Store) UpsertAttachment ¶
func (s *Store) UpsertAttachment(messageID int64, filename, mimeType, storagePath, contentHash string, size int) error
UpsertAttachment stores an attachment record.
func (*Store) UpsertFTS ¶ added in v0.6.4
func (s *Store) UpsertFTS(messageID int64, subject, bodyText, fromAddr, toAddrs, ccAddrs string) error
UpsertFTS inserts or replaces an FTS row for a message. No-op if FTS5 is not available.
func (*Store) UpsertMessage ¶
UpsertMessage inserts or updates a message.
func (*Store) UpsertMessageBody ¶
func (s *Store) UpsertMessageBody(messageID int64, bodyText, bodyHTML sql.NullString) error
UpsertMessageBody stores the body text and HTML for a message in the separate message_bodies table.
type SyncRun ¶
type SyncRun struct {
ID int64
SourceID int64
StartedAt time.Time
CompletedAt sql.NullTime
Status string // SyncStatusRunning, SyncStatusCompleted, SyncStatusFailed
MessagesProcessed int64
MessagesAdded int64
MessagesUpdated int64
ErrorsCount int64
ErrorMessage sql.NullString
CursorBefore sql.NullString // Page token for resumption
CursorAfter sql.NullString // Final history ID
}
SyncRun represents a sync operation in progress or completed.