PostgresStore

class PostgresStore(dataSource: DataSource, table: String = "kmemo_cache", ttl: Duration? = null, clock: Clock = Clock.System) : CacheStore

A durable CacheStore backed by Postgres with the pgvector extension.

This is the "durable semantic cache as a one-dependency choice": point it at a Postgres you already run and cached answers survive a restart and are shared across processes. As with every kmemo store, the adapter reimplements no match logic — the nearest-neighbour search is pgvector's cosine-distance operator (<=>), and dev.kmemo.SemanticCache still owns threshold, guards and verification.

Schema. One table (created on first use, or provision it yourself from the shipped schema.sql): id primary key, scope, prompt, response, embedding vector, created_at, expires_at (nullable, where null never expires), metadata jsonb, tags text[], embedder text and chunk_lengths integer[]. A table created by an earlier version gains the last three by ALTER TABLE ... ADD COLUMN IF NOT EXISTS on the next start, and rows already in it read as dev.kmemo.Embedder.UNDECLARED with no chunk boundaries, which is the honest record of a row nothing captured an embedder for and nothing ever streamed. The embedding column is left dimension-unconstrained so mixed embedding sizes are a storage error at query time, not a schema wall. The search is an exact scan by default (correct, and matching the conformance suite); add an HNSW/IVFFlat index on embedding once your dimension is fixed to scale it.

Expiry. Every read filters on expires_at IS NULL OR expires_at > now, where now comes from the injected clock — so expiry is deterministic under a fixed clock in tests, and honest under the system clock in production. purgeExpired deletes the dead rows when you want the space back.

Parameters

dataSource

a pooled Postgres DataSource; the Postgres JDBC driver is the caller's dependency.

table

table name (validated as a plain identifier, since it is interpolated into SQL).

ttl

how long an entry stays valid, or null to keep it until removed.

clock

time source; substitute a fixed clock in tests instead of sleeping.

Constructors

Link copied to clipboard
constructor(dataSource: DataSource, table: String = "kmemo_cache", ttl: Duration? = null, clock: Clock = Clock.System)

Functions

Link copied to clipboard
open suspend override fun clear(scope: String?)
Link copied to clipboard
open suspend override fun invalidateByTag(tag: String, scope: String?): Int
Link copied to clipboard
suspend fun purgeExpired(): Int

Deletes every row already past its TTL and returns how many went.

Link copied to clipboard
open suspend override fun put(entry: CacheEntry)
Link copied to clipboard
open suspend override fun remove(id: String): Boolean
Link copied to clipboard
open suspend override fun search(scope: String, embedding: FloatArray, limit: Int): List<ScoredEntry>
Link copied to clipboard
open suspend override fun size(scope: String?): Int
Link copied to clipboard
open suspend fun touch(id: String)