Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
88
plugins/document-navigator/docs/persistence/database/db-sqlite/src/cache/cache.md
vendored
Normal file
88
plugins/document-navigator/docs/persistence/database/db-sqlite/src/cache/cache.md
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
# cache
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`PreparedStatementCache` is an LRU-bounded cache for `bun:sqlite` prepared statement objects, keyed by SQL text. Reusing prepared statements avoids the overhead of repeated SQL parsing and optimisation — a significant win for hot query paths. The cache is bounded to prevent unbounded memory growth in applications that generate many distinct SQL strings.
|
||||
|
||||
The cache integrates with OpenTelemetry to surface hit/miss/eviction counters at `sqlite.cache.hits`, `sqlite.cache.misses`, and `sqlite.cache.evictions`. These are no-ops when no OTel provider is registered, keeping the module safe for use in zero-dependency environments.
|
||||
|
||||
## Features
|
||||
|
||||
- LRU eviction when `size >= maxSize` (default `128`)
|
||||
- `get(sql)` — returns cached statement or `undefined`; updates LRU order
|
||||
- `set(sql, stmt)` — inserts or updates; evicts LRU entry when at capacity, calling `stmt.finalize()` on the evicted statement
|
||||
- `invalidate()` — clears all entries and calls `finalize()` on each held statement; called by `SqliteAdapter.migrate()` to prevent stale plan reuse after schema changes
|
||||
- `size` / `maxSize` read-only getters
|
||||
- OTel counters: `sqlite.cache.hits`, `sqlite.cache.misses`, `sqlite.cache.evictions`
|
||||
- `static resetInstruments()` — clears the OTel lazy singleton for test isolation
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { PreparedStatementCache } from "@suaveplan/db-sqlite/cache/cache";
|
||||
|
||||
const cache = new PreparedStatementCache();
|
||||
const stmt = sqlite.prepare("SELECT * FROM users WHERE id = ?");
|
||||
cache.set("SELECT * FROM users WHERE id = ?", stmt);
|
||||
|
||||
const hit = cache.get("SELECT * FROM users WHERE id = ?");
|
||||
// hit === stmt
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { PreparedStatementCache } from "@suaveplan/db-sqlite/cache/cache";
|
||||
|
||||
// Small cache for testing eviction
|
||||
const cache = new PreparedStatementCache(3);
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const sql = `SELECT ${i} FROM t`;
|
||||
cache.set(sql, { finalize: () => undefined }); // mock statement
|
||||
}
|
||||
|
||||
console.log(cache.size); // 3 — first entry evicted
|
||||
|
||||
cache.invalidate();
|
||||
console.log(cache.size); // 0 — all entries cleared
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `new PreparedStatementCache(maxSize?: number)`
|
||||
|
||||
Constructs a new cache. `maxSize` defaults to `128`.
|
||||
|
||||
### `get(sql: string): Statement | undefined`
|
||||
|
||||
Returns the cached statement for `sql`, or `undefined` on miss. Increments `sqlite.cache.hits` or `sqlite.cache.misses`. Updates LRU order on hit.
|
||||
|
||||
### `set(sql: string, stmt: Statement): void`
|
||||
|
||||
Inserts or updates the cache entry for `sql`. On capacity overflow, evicts the least-recently-used entry, calling `stmt.finalize()` on it, and increments `sqlite.cache.evictions`.
|
||||
|
||||
### `invalidate(): void`
|
||||
|
||||
Clears all entries. Calls `stmt.finalize()` on each held statement before clearing. Called automatically by `SqliteAdapter.migrate()`.
|
||||
|
||||
### `size: number`
|
||||
|
||||
Current number of cached entries.
|
||||
|
||||
### `maxSize: number`
|
||||
|
||||
Maximum capacity as set at construction.
|
||||
|
||||
### `static resetInstruments(): void`
|
||||
|
||||
Clears the lazy OTel instruments singleton. Use in tests to ensure each test suite starts with a fresh counter baseline.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
LRU ordering is maintained with a parallel `string[]` array (`#lruOrder`) rather than a doubly-linked list. This is simpler and sufficient for cache sizes up to a few hundred entries — `Array.indexOf` and `splice` on an array of at most 128 strings add negligible overhead compared to a SQLite query round-trip. For much larger caches a linked-list implementation would be preferable.
|
||||
|
||||
`finalize()` is called defensively with a try/catch because `bun:sqlite` statements may already be finalised if the underlying database was closed before the cache was cleared.
|
||||
Reference in New Issue
Block a user