Packages
howdy_cache
1.0.0
An application cache for Howdy apps: fetch-or-compute with expiry and tag invalidation, kept in memory or in the database
Current section
Files
Jump to
Current section
Files
howdy_cache
README.md
README.md
# howdy_cache
An application cache for [howdy](https://github.com/howdy-gleam/howdy/blob/v1.0.0/README.md) apps: keep the result of
expensive work for a while, and throw it away when the data it came from
changes. Entries live in this node's memory or in the app's database,
PostgreSQL or SQLite, or anywhere a store can reach.
Add it to your project:
```sh
gleam add howdy_cache@1
```
## Fetch or compute
```gleam
import howdy/cache
import howdy/cache/memory
import howdy/codec
// In main, once:
let app_cache = cache.new(memory.new(max_entries: 50_000))
// Anywhere:
pub fn find(id: Int) -> service.Result(Note) {
let entry =
cache.entry("note:" <> int.to_string(id), ttl: 300)
|> cache.tags(["note:" <> int.to_string(id)])
use <- cache.fetch(app_cache, entry, note_codec())
notes.find(db, id)
}
// When the note changes, inside its transaction or not:
cache.invalidate(app_cache, ["note:" <> int.to_string(id)])
```
- `fetch` stores `Ok` results only, so a failed query is retried.
- Values are JSON, through a `howdy/codec` codec, in every store. One that
no longer decodes after a deploy counts as missing.
- Tags have versions, read before the value is computed, so a value built
from data that changed meanwhile is never served.
- Inside a `howdy/database` transaction, `invalidate` and `delete` wait for
it to end, `put` deletes the key then instead of storing, and `fetch`
skips the cache.
- A store that fails makes `fetch` compute instead, with a warning.
- Concurrent misses on one node compute once and share the result or
error.
## Stores
- `howdy/cache/memory`: ETS on this node, bounded by `max_entries`. Each
node has its own entries and invalidations.
- `howdy/cache/database`: shared by every node using the database, one
query per read, `UNLOGGED` tables on PostgreSQL. Run
`cache_database.schema()` with `howdy/migration` first.
- Your own: `cache.store` from seven functions.
See the [caching docs](https://github.com/howdy-gleam/howdy/blob/v1.0.0/docs/cache/overview.djot) for the details, and
`howdy/conditional` in the core package for answering `304 Not Modified`.
## Development
The tests run against the memory store and a SQLite database. Set
`HOWDY_CACHE_TEST_POSTGRES_URL` to run the database store against
PostgreSQL too; the tests drop and recreate the package's tables there.
```sh
HOWDY_CACHE_TEST_POSTGRES_URL=postgres://howdy_cache_test@localhost/postgres gleam test
```