ExSQL.Registry (exsql v0.1.1)

Copy Markdown

An in-VM "commit version" per database path.

File-backed connections share a database through its file: each persists the whole file after a committed write, and (historically) re-parsed the whole file before each read so it could observe another connection's commits. That reparse is pure waste in the common single-writer case, where a connection's in-memory ExSQL.Database is already authoritative.

This registry lets a connection tell whether its snapshot is still current without touching the file: a monotonically increasing counter, keyed by database path, is bumped once per committed file write. A connection records the version it last synced to; when the registry version is unchanged, the reload can be skipped.

The counter lives in a :public ETS table owned by this process (started under ExSQL.Application) so it outlives any individual connection. Reads and bumps go straight to ETS — no GenServer round-trip on the hot path.

A file-stat fingerprint ({mtime, size}) is deliberately not used: a whole-file rewrite of a small change can keep the size identical, and POSIX mtime is second-resolution, so two writes plus a read within one second can look unchanged — skipping a reload that was actually required. An in-VM counter has neither problem (within one VM, the supported deployment).

If the table is absent (the :exsql application was not started), the functions return :no_registry and callers fall back to always reloading — the original, correct-but-slower behavior.

Summary

Functions

Atomically bumps and returns the commit version for path, or :no_registry if the registry is not running.

Returns a specification to start this module under a supervisor.

Returns the current commit version for path (0 if never written), or :no_registry if the registry is not running.

Starts the registry, creating its ETS table.

Functions

bump(path)

@spec bump(term()) :: non_neg_integer() | :no_registry

Atomically bumps and returns the commit version for path, or :no_registry if the registry is not running.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

current_version(path)

@spec current_version(term()) :: non_neg_integer() | :no_registry

Returns the current commit version for path (0 if never written), or :no_registry if the registry is not running.

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Starts the registry, creating its ETS table.