Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

18 Commits

Repository files navigation

sqlatom

sqlatom is a Clojure and Babashka library that stores atoms in a SQLite database:

;; deps.edn
{:deps {io.github.filipesilva/sqlatom {:git/tag"v1.2.0":git/sha"dd30a20"}}}

Usage

(nsapp
(:require [filipesilva.sqlatom :as sqlatom]))
(defoncestate (sqlatom/atom:state {}))

This will create a sqlatom/atoms.db in the project root if there isn't one yet, then initialize :state as {} if there is no value for it yet, or read the existing value for :state.

All atom operations are supported, with the following semantics:

  • swap!, compare-and-set!, swap-vals! have transaction semantics and are safe to use between atoms/threads/processes/dialects
  • deref will read from the database if the value has been updated since last read
  • add-watch watchers see updates from other atoms only when reading/updating, and will not be called for unseen updates

Values are stored as edn, and use the readers for the current process. You should add sqlatom/ to your .gitignore unless you want to commit the state.

Options

sqlatom supports the existing :meta and :validatoratom options.

You can also pass in a :dir option after the value to change it from the sqlatom default:

(sqlatom/atom:tmp-state {} :dir"/tmp/sqlatom")

Helpers

Use sqlatom/keys to get the set of all saved keys. This is useful for instrospection and maintenance (e.g. unit test fixtures). You can then use sqlatom/atom to get their values, or sqlatom/remove to remove keys.

@(sqlatom/atom:state {}) ;=> {}
(sqlatom/keys) ;=> #{:state}
(sqlatom/remove:state) ;=> nil
(sqlatom/keys) ;=> #{}

Both sqlatom/keys and sqlatom/remove support the :dir option. sqlatom/list is a deprecated alias for sqlatom/keys that returns a vector instead of a set. Using an existing sqlatom that was removed will throw an an error, but resume working normally if you recreate it using the same key.

Comparison with duratom

duratom is a more established library for durable atoms. Here's how the two differ:

sqlatomduratom
Cross-process swap safetyYes, uses SQL compare-and-set with versioned rowsNo, uses an in-memory lock, so concurrent processes can clobber each other
Storage backendsSQLite onlyPostgreSQL, SQLite, S3, Redis, filesystem, file.io
ConsistencyStrong, every read/write goes through the databaseEventual by default (async writes), optional sync mode
ScopeMinimal, atoms only, no configuration beyond :dirFeature-rich, custom serializers, error handlers, sync/async modes, duragent

Choose sqlatom if you need safe cross-process swaps with a simple API. Choose duratom if you need multiple storage backends or its additional features.

Babashka

The following operations are not supported in Babashka:

  • add-watch, remove-watch
  • set-validator!, get-validator
  • meta, alter-meta!, reset-meta!

This is being tracked in babashka/babashka#1931

In Babashka the following limits apply:

  • ~20mb printed edn size
  • 1000 number length
  • 1000 nesting limit

Performance

On my machine, criterium measured 76ms (±1ms) for a reset! and 140ms (±9ms) for a swap! of 20mb worth of EDN from a Datascript backup.

About

Clojure library that stores atoms in a SQLite database

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages