storage
storage
Responsibility
The storage package (Go import path internal/storage, package name
storage) defines the persistence layer for ARES. It comprises a top-level
vector-store contract and a PostgreSQL subsystem under
internal/storage/postgres (package postgres) that provides connection
pooling, multi-tenant isolation, repository-pattern data access, write
batching, and retrieval protection.
Core responsibilities:
- Vector store contract - the
VectorStoreinterface (Search,AddEmbedding,CreateCollection) is the backend-agnostic contract for vector similarity search. PostgreSQL (pgvector), Qdrant, Milvus, SQLite-vec, or in-memory all plug in here. - Connection pooling -
Poolimplements the get / use / release pattern overdatabase/sqlwith configurableMaxOpenConns,MaxIdleConns,ConnMaxLifetime, andConnMaxIdleTime. - Tenant isolation -
TenantGuardenforces row-level isolation by settingapp.tenant_idviaSET LOCALsemantics on every tenant-scoped operation, preventing cross-tenant data leakage on pooled connections. - Repository pattern -
RepositoryaggregatesSessionRepository,RecommendRepository,ProfileRepository, and aVectorStore; sub-packagerepositoriesaddsConversationRepository,TaskResultRepository,ExperienceRepository,KnowledgeRepository,ToolRepository,StrategyRepository, andSecretRepository. A genericGetByID[T]/DeleteByID[T]helper enforces a table whitelist against SQL injection. - Write batching and retrieval protection -
WriteBufferbatches writes to reduce database and embedding load;RetrievalGuardapplies rate limiting, circuit breaking, and timeout protection to retrieval paths.
Architecture
flowchart TD
Caller["Production Memory Manager / Services"]
subgraph Pool["Connection Pool"]
Config["Config<br/>(MaxOpenConns, TTLs)"]
DB["*sql.DB (pgx)"]
TenantGuard["TenantGuard<br/>SET LOCAL app.tenant_id"]
end
subgraph Repo["Repository Pattern"]
Repository["Repository<br/>(Session / Recommend / Profile / Vector)"]
Repos["repositories/<br/>Conversation / TaskResult / Experience / Knowledge / Tool / Strategy / Secret"]
Generic["GetByID[T] / DeleteByID[T]<br/>(table whitelist)"]
end
subgraph Protect["Protection"]
WriteBuffer["WriteBuffer<br/>(batch flush)"]
RetrievalGuard["RetrievalGuard<br/>rate limit + circuit breaker"]
EmbedQueue["EmbeddingQueue"]
end
Vector["VectorStore<br/>(pgvector / memory)"]
Caller --> Pool
Pool --> Repo
Repository --> Repos
Repos --> Generic
Caller --> WriteBuffer
WriteBuffer --> EmbedQueue
WriteBuffer --> DB
Caller --> RetrievalGuard
RetrievalGuard --> DB
Repo --> Vector
Vector --> DB
External interfaces
Signatures are extracted verbatim from source.
// VectorStore (top-level contract) - all vector backends implement this.
type VectorStore interface {
Search(ctx context.Context, table string, embedding []float64, limit int) ([]*SearchResult, error)
AddEmbedding(ctx context.Context, table, id string, embedding []float64, metadata map[string]any) error
CreateCollection(ctx context.Context, name string, dimension int) error
}
// PostgreSQL pool and configuration.
type Pool struct { /* fields */ }
func NewPool(cfg *Config) (*Pool, error)
func (p *Pool) Get(ctx context.Context) (*sql.Conn, error)
func (p *Pool) Release(conn *sql.Conn)
func (p *Pool) WithConnection(ctx context.Context, fn func(*sql.Conn) error) error
func (p *Pool) GetDB() *sql.DB
type Config struct {
Host, User, Password, Database, SSLMode string
Port int
MaxOpenConns int
MaxIdleConns int
ConnMaxLifetime time.Duration
ConnMaxIdleTime time.Duration
QueryTimeout time.Duration
Embedding *EmbeddingConfig
}
func DefaultConfig() *Config
func (c *Config) DSN() string
func (c *Config) Validate() error
// Tenant isolation.
type TenantGuard struct { /* fields */ }
func NewTenantGuard(pool *Pool) *TenantGuard
func (g *TenantGuard) SetTenantContext(ctx context.Context, tenantID string) error
func (g *TenantGuard) MustSetTenantContext(ctx context.Context, tenantID string) error
// Repository aggregator.
type Repository struct {
Session *SessionRepository
Recommend *RecommendRepository
Profile *ProfileRepository
Vector storage.VectorStore
}
func NewRepository(pool *Pool) *Repository
func (r *Repository) Transaction(ctx context.Context, fn func(repo *Repository) error) error
// Generic helpers (table-whitelisted).
func GetByID[T any](ctx context.Context, db DBTX, table, id, tenantID string, scan func(Scannable) (*T, error)) (*T, error)
// Write batching and retrieval protection.
type WriteBuffer struct { /* fields */ }
func NewWriteBuffer(pool *Pool, queue *EmbeddingQueue, batchSize int, flushInterval time.Duration, embeddingConfig *EmbeddingConfig) *WriteBuffer
type RetrievalGuard struct { /* fields */ }
func NewRetrievalGuard(maxRequestsPerSec int, failureThreshold int, openTimeout, dbTimeout time.Duration) *RetrievalGuard
DefaultConfig returns the production-safe defaults: Host localhost,
Port 5432, SSLMode “require”, MaxOpenConns 25, MaxIdleConns 10,
ConnMaxLifetime 5m, ConnMaxIdleTime 1m, QueryTimeout 30s. Password is
intentionally empty; callers must supply credentials explicitly.
Key types and methods
| Type / Method | Kind | Purpose |
|---|---|---|
VectorStore | interface | 3-method backend-agnostic vector contract (Search, AddEmbedding, CreateCollection). |
SearchResult | struct | Single vector search result: ID, Score, Metadata. |
Pool | struct | Connection pool with get / use / release; tracks wait count and duration. |
Config | struct | Pool configuration: host, port, credentials, conn limits, timeouts, embedding config. |
DefaultConfig | function | Production-safe defaults (SSLMode require, 25 open / 10 idle conns, 30s timeout). |
TenantGuard | struct | Enforces app.tenant_id via SET LOCAL for row-level isolation. |
Repository | struct | Aggregates Session, Recommend, Profile, and Vector sub-repositories. |
Transaction | method | Runs a function in a transaction with transaction-scoped sub-repositories. |
GetByID[T] | function | Generic by-ID lookup; table must be on the allowedTables whitelist. |
WriteBuffer | struct | Batches writes with periodic flush to reduce DB and embedding load. |
EmbeddingQueue | struct | Async embedding processing queue. |
RetrievalGuard | struct | Rate limiting + circuit breaker + DB timeout for retrieval paths. |
CircuitBreaker | struct | Failure-threshold circuit breaker for embedding service. |
DBTX | interface | Satisfied by *sql.DB and *sql.Tx; enables transaction-aware repos. |
EmbeddingConfig | struct | Embedding defaults: model intfloat/e5-large, batch 32, retries 3. |
Module collaboration
- ares_memory -
ProductionMemoryManagerdepends onpostgres.Pool,TenantGuard,WriteBuffer,RetrievalGuard, and the conversation / task-result repositories for its persistent backend. - ares_events -
PostgresEventStoreis backed bypostgres.Pooland persists events in theeventstable with optimistic concurrency control. - knowledge - the
knowledge/store/postgresbackend uses a*sql.DBconnection (opened independently or sourced from the pool) for itsKnowledgeStoreimplementation. - retrievalservice - the production retrieval repository path uses the
pool and
TenantGuardfor tenant-scoped knowledge search. - storage/memory - an in-memory
VectorStoreimplementation used for testing and single-node deployments.
Extension points
- Add a new vector backend. Implement the 3-method
VectorStoreinterface (Search,AddEmbedding,CreateCollection) for your backend (e.g. Qdrant, Milvus). Wire it intoRepository.Vectoror use it directly via thecontext.VectorSearcherinterface inares_memory. - Add a domain repository. Create a new repository struct in
internal/storage/postgres/repositories/that takes aDBTX(so it works with both*sql.DBand*sql.Tx), mirroringExperienceRepository. If it needs generic by-ID access, add its table to theallowedTableswhitelist inbase_repository.gobefore usingGetByID[T]. - Tune the connection pool. Construct a
ConfigviaDefaultConfig, then adjustMaxOpenConns,MaxIdleConns,ConnMaxLifetime,ConnMaxIdleTime, andQueryTimeoutfor your workload before callingNewPool.Validatefills zero values with safe defaults. - Run multi-statement transactions. Use
Repository.Transactionto execute a function against a transaction-scopedRepository; the helper rolls back on error and commits on success, with all sub-repositories bound to the same*sql.Tx. - Enforce tenant isolation. Call
TenantGuard.SetTenantContext(ctx, tenantID)at the start of every tenant-scoped operation. The setting usesSET LOCALsemantics, so it is scoped to the current transaction and cannot leak across pooled connections. - Protect retrieval paths. Wrap retrieval calls with
RetrievalGuard:AllowRateLimitgates request rate,CheckEmbeddingCircuitBreakeropens on repeated embedding failures to fall back to keyword-only search, anddbTimeoutbounds each database operation.
Bilingual status
Source code, identifiers, type names, and code comments are in English. This
English page is the canonical reference. A Chinese translation with identical
structure and technical content is published alongside as storage.zh.md;
all code blocks, signatures, and identifiers remain in English in both pages.
Maturity
Production. The package is covered by storage_test.go, pool_test.go,
config_test.go, repository_test.go, tenant_guard usage across the
codebase, circuit_breaker_test.go, security_test.go, timeout_test.go,
comprehensive_test.go, coverage_test.go, and per-repository tests under
repositories/. It is integrated into the SDK via
ProductionMemoryManager, PostgresEventStore, and the production retrieval
path. No experimental markers remain; the table whitelist, SET LOCAL
tenant isolation, and SSL-by-default config are production hardening
features.