MCPcopy
hub / github.com/kenn-io/msgvault / Engine

Interface Engine

internal/query/engine.go:14–84  ·  view source on GitHub ↗

Engine provides query operations for msgvault data. This interface can be implemented by different backends: - SQLiteEngine: Direct SQLite queries (flexible, moderate performance) - ParquetEngine: Arrow/Parquet queries (fast aggregates, read-only).

Source from the content-addressed store, hash-verified

12// - SQLiteEngine: Direct SQLite queries (flexible, moderate performance)
13// - ParquetEngine: Arrow/Parquet queries (fast aggregates, read-only).
14type Engine interface {
15 // Aggregate performs grouping based on the provided ViewType (Sender, Domain, etc.)
16 Aggregate(ctx context.Context, groupBy ViewType, opts AggregateOptions) ([]AggregateRow, error)
17
18 // SubAggregate performs aggregation on a filtered subset of messages.
19 // This is used for sub-grouping after drill-down, e.g., drilling into
20 // "Sender: foo@example.com" and then sub-grouping by Recipients or Labels.
21 // The filter specifies the parent context (sender, domain, etc.) and
22 // groupBy specifies what dimension to aggregate by.
23 SubAggregate(ctx context.Context, filter MessageFilter, groupBy ViewType, opts AggregateOptions) ([]AggregateRow, error)
24
25 // Message queries
26 ListMessages(ctx context.Context, filter MessageFilter) ([]MessageSummary, error)
27 GetMessage(ctx context.Context, id int64) (*MessageDetail, error)
28 GetMessageBySourceID(ctx context.Context, sourceMessageID string) (*MessageDetail, error)
29 GetAttachment(ctx context.Context, id int64) (*AttachmentInfo, error)
30
31 // GetMessageRaw returns the decompressed raw MIME data for a message.
32 // Returns nil, nil if no raw data is stored for the given ID.
33 GetMessageRaw(ctx context.Context, id int64) ([]byte, error)
34
35 // GetMessageSummariesByIDs returns summary-level rows (no body, no
36 // raw MIME) for the supplied IDs in the same order as ids. Missing
37 // IDs are silently dropped — callers loop over IDs from a search
38 // hit list and treat absent rows as "deleted/retired, skip". This
39 // is the bulk hydration path search handlers should use to avoid
40 // the per-hit GetMessage N+1 (body + recipients + labels +
41 // attachments per message).
42 GetMessageSummariesByIDs(ctx context.Context, ids []int64) ([]MessageSummary, error)
43
44 // Search - full-text search using FTS5 (includes message body)
45 Search(ctx context.Context, query *search.Query, limit, offset int) ([]MessageSummary, error)
46
47 // SearchFast searches message metadata only (no body text).
48 // This is much faster for large archives as it queries Parquet files directly.
49 // Searches: subject, sender email/name (case-insensitive).
50 // The filter parameter allows contextual search within a drill-down.
51 SearchFast(ctx context.Context, query *search.Query, filter MessageFilter, limit, offset int) ([]MessageSummary, error)
52
53 // SearchFastCount returns the total count of messages matching a search query.
54 // This is used for pagination UI to show "N of M results".
55 SearchFastCount(ctx context.Context, query *search.Query, filter MessageFilter) (int64, error)
56
57 // SearchFastWithStats performs a fast metadata search and returns paginated
58 // results, total count, and aggregate stats in a single operation. The DuckDB
59 // implementation materializes matching IDs into a temp table with one Parquet
60 // scan, then reuses it for count, pagination, and stats — replacing 3-4
61 // separate scans with one.
62 //
63 // queryStr is the raw search string (needed for stats; search.Query doesn't store it).
64 // statsGroupBy controls which view's key columns are used for stats search filtering.
65 SearchFastWithStats(ctx context.Context, query *search.Query, queryStr string,
66 filter MessageFilter, statsGroupBy ViewType, limit, offset int) (*SearchFastResult, error)
67
68 // GetGmailIDsByFilter returns Gmail message IDs (source_message_id) matching a filter.
69 // This is useful for batch operations like staging messages for deletion.
70 GetGmailIDsByFilter(ctx context.Context, filter MessageFilter) ([]string, error)
71

Implementers 4

Engineinternal/remote/engine.go
SQLiteEngineinternal/query/sqlite.go
DuckDBEngineinternal/query/duckdb.go
MockEngineinternal/query/querytest/mock_engine.g

Calls

no outgoing calls

Tested by

no test coverage detected