Files
sqlite/CHANGELOG.md
Rene Nochebuena 237cba9bad feat(sqlite): initial stable release v0.9.0
Pure-Go CGO-free SQLite client with launcher lifecycle, write-mutex serialisation, health check, unit-of-work via context injection, and structured error mapping.

What's included:
- Executor / Tx / Client / Component interfaces using database/sql native types
- Tx.Commit() / Tx.Rollback() without ctx, matching the honest database/sql contract
- New(logger, cfg) constructor; database opened in OnInit
- Config struct with env-tag support; default Pragmas: WAL + 5s busy timeout + FK enforcement
- PRAGMA foreign_keys = ON enforced explicitly in OnInit
- writeMu sync.Mutex acquired by UnitOfWork.Do to serialise writes and prevent SQLITE_BUSY
- UnitOfWork via context injection; GetExecutor(ctx) returns active Tx or *sql.DB
- HandleError mapping SQLite extended error codes to xerrors codes (unique/primary-key → AlreadyExists, foreign-key → InvalidInput, ErrNoRows → NotFound)
- health.Checkable at LevelCritical; pure-Go modernc.org/sqlite driver (CGO_ENABLED=0 compatible)

Tested-via: todo-api POC integration
Reviewed-against: docs/adr/
2026-03-19 13:25:31 +00:00

3.3 KiB

Changelog

All notable changes to this module will be documented in this file.

The format is based on Keep a Changelog, and this module adheres to Semantic Versioning.

0.9.0 - 2026-03-18

Added

  • Executor interface: ExecContext, QueryContext, QueryRowContext using database/sql types (sql.Result, *sql.Rows, *sql.Row).
  • Tx interface: embeds Executor and adds Commit() error and Rollback() error (no context argument, matching database/sql semantics).
  • Client interface: GetExecutor(ctx context.Context) Executor, Begin(ctx context.Context) (Tx, error), Ping(ctx context.Context) error, HandleError(err error) error.
  • Component interface: composes launcher.Component, health.Checkable, and Client.
  • UnitOfWork interface: Do(ctx context.Context, fn func(ctx context.Context) error) error.
  • Config struct: fields Path (SQLITE_PATH), MaxOpenConns (default 1), MaxIdleConns (default 1), Pragmas (default ?_journal=WAL&_timeout=5000&_fk=true); settable via SQLITE_* environment variables.
  • New(logger logz.Logger, cfg Config) Component: returns a pure-Go SQLite component backed by modernc.org/sqlite; no CGO required.
  • Lifecycle hooks: OnInit opens the database, sets connection limits, and enforces PRAGMA foreign_keys = ON; startup fails if the pragma cannot be set. OnStart pings with a 5-second timeout. OnStop closes the connection.
  • health.Checkable implementation: HealthCheck delegates to Ping; Name() returns "sqlite"; Priority() returns health.LevelCritical.
  • NewUnitOfWork(logger logz.Logger, client Client) UnitOfWork: wraps a Client to provide transactional Do semantics. When the client is the concrete *sqliteComponent, the write mutex is acquired for the duration of Do to serialise concurrent write transactions and prevent SQLITE_BUSY.
  • HandleError(err error) error (package-level function): maps SQLite extended error codes via a duck-typed coder interface — code 2067 (unique constraint) and 1555 (primary key constraint) → ErrAlreadyExists; code 787 (foreign key constraint) → ErrInvalidInput; sql.ErrNoRowsErrNotFound; all others → ErrInternal.
  • Transaction context injection: the active *sql.Tx is stored under an unexported ctxTxKey{} context key; GetExecutor returns it when found, otherwise returns *sql.DB.
  • WAL journal mode, 5-second busy timeout, and foreign key enforcement enabled by default via the Pragmas DSN suffix.
  • Support for in-memory databases via Config{Path: ":memory:"} for test isolation.

Design Notes

  • modernc.org/sqlite (pure Go, no CGO) is used instead of mattn/go-sqlite3, enabling cross-compilation with CGO_ENABLED=0 and no system library dependency.
  • A sync.Mutex (writeMu) on the component serialises all UnitOfWork.Do calls, preventing SQLITE_BUSY errors that arise from SQLite's single-writer constraint without requiring callers to manage locking.
  • Foreign key enforcement is applied both via the _fk=true DSN pragma and an explicit PRAGMA foreign_keys = ON statement in OnInit, ensuring enforcement is active regardless of driver-level pragma handling.