Persistence Operations
shelf provides four persistence operations to control how and when data moves between memory (ETS) and disk (DETS).
Overview
Section titled “Overview”| Function | Behavior |
|---|---|
save(table) | Snapshot ETS → DETS (replaces DETS contents) |
reload(table) | Discard ETS, reload from DETS |
sync(table) | Flush DETS write buffer to OS |
close(table) | Save + close DETS + delete ETS |
Atomically snapshots the entire ETS table into DETS, replacing all DETS contents with the current ETS state. Uses ets:to_dets/2 internally — the transfer happens efficiently inside the Erlang VM without materializing the table as a list.
// After a batch of writes...let assert Ok(Nil) = set.save(table)When to use: In WriteBack mode, call save() to persist changes to disk. Common strategies:
- On a periodic timer (e.g., every 30 seconds)
- After a batch of N writes
- At application shutdown
- After critical data changes
In WriteThrough mode, save() is called automatically after every write, so you rarely need to call it manually.
reload
Section titled “reload”Clears the ETS table and loads all DETS contents into it. Discards any unsaved changes in ETS.
// Undo unsaved changeslet assert Ok(Nil) = set.reload(table)When to use: In WriteBack mode, use reload() to discard in-memory changes and revert to the last saved state. In WriteThrough mode, ETS and DETS are always in sync, so reload() is rarely needed.
Flushes the DETS internal write buffer to the OS filesystem. DETS buffers writes for performance — sync() forces those buffers to disk.
let assert Ok(Nil) = set.sync(table)When to use: In WriteThrough mode, after a critical write when you need to guarantee the data has reached the filesystem. In WriteBack mode, sync() is less useful since you control persistence via save().
Performs a final save(), closes the DETS file, and deletes the ETS table. The table handle must not be used after closing.
let assert Ok(Nil) = set.close(table)For guaranteed cleanup, use with_table instead of manual open/close:
let assert Ok(Nil) = { use table <- set.with_table("cache", "data/cache.dets") set.insert(into: table, key: "key", value: "value")}// table is automatically closed herePersistence Flow
Section titled “Persistence Flow”flowchart LR
subgraph wb["WriteBack mode"]
direction LR
I1[insert] -->|write| E1[ETS]
E1 -->|"save()"| D1[DETS]
D1 -->|"sync()"| F1[filesystem]
end
subgraph wt["WriteThrough mode"]
direction LR
I2[insert] -->|write| E2[ETS]
E2 -->|"auto save()"| D2[DETS]
D2 -->|"sync()"| F2[filesystem]
end