Database Persistence
Relevant source files
The following files were used as context for generating this wiki page:
Database Persistence in Augenblick is centered around a SQLite-based storage engine that manages note metadata, application state, and user settings. The system is designed to provide a hybrid storage model where note content lives in the filesystem (either as internal drafts or external files), while the database maintains the structural relationships, search metadata (titles/previews), and lifecycle states (pinning, trashing, and expiry).
The persistence layer is managed by a Rust backend using rusqlite for the production application, with a fallback Web Shim implementation for browser-based environments that mimics the database behavior using localStorage.
Sources: plans/migration.inventory.md:16-36, src-tauri/src/app_state.rs:43-44
Data Schema and Storage
The primary database file is named augenblick.db and is located in the application's data directory. The schema utilizes a user_version = 1 and consists of three main tables: notes, app_state, and settings.
The notes Table
This table is the core of the persistence layer, tracking every note managed by the application. It stores metadata and pointers to the physical file locations.
| Field | Type | Description |
|---|---|---|
id | TEXT | Primary Key (UUID). |
title | TEXT | Derived title (max 80 chars). |
preview | TEXT | Derived content preview (max 140 chars). |
file_path | TEXT | Absolute path to the content file. |
storage | TEXT | Storage mode: "draft" or "saved". |
bookmark | BLOB | macOS security-scoped bookmark (nullable). |
is_pinned | INTEGER | Boolean flag (0/1) for pinned status. |
is_trashed | INTEGER | Boolean flag (0/1) for trash status. |
sort_order | INTEGER | Numeric order for list display. |
created_at | INTEGER | Millisecond epoch timestamp of creation. |
last_interaction | INTEGER | Millisecond epoch of last edit/activity. |
trashed_at | INTEGER | Millisecond epoch of trashing (nullable). |
Sources: plans/migration.inventory.md:17-31, src-tauri/src/notes/write.rs:20-35
Relationship Diagram
The following entity relationship diagram illustrates the logical structure of the persistence layer:
The application uses two separate key-value tables for configuration: settings for user-defined preferences (like theme or expiry) and app_state for UI session state (like sidebar width).
Sources: plans/migration.inventory.md:32-33, src/lib/tauri/shim.ts:4-8
Core Persistence Logic
Initialization and Connection Management
The application state is initialized within the AppState struct, which wraps a thread-safe SQLite connection (Arc<Mutex<Connection>>). During startup, the application ensures the presence of internal directories for drafts and trash.
A specific environment variable, AUGENBLICK_LOG_PATH, is set to point to debug.log within the same persistence directory.
Sources: src-tauri/src/app_state.rs:1-50
Note Lifecycle Transitions
When a note is created or updated, the persistence layer handles the file-to-database synchronization. Drafts are automatically written to the internal drafts/ directory, while "Saved" notes are written to user-specified paths.
- Draft Creation: A new UUID is generated, an empty file is created in the drafts folder, and a corresponding row is inserted into the
notestable withstorage="draft". - Metadata Derivation: Titles and previews are not stored in the markdown files but are derived by the backend during writes and stored in the database for fast list rendering.
- Promotion (Save As): When a draft is saved to a permanent location, the database record is updated:
file_pathchanges,storagebecomes"saved", and the internal draft file is deleted.
Sources: src-tauri/src/notes/write.rs:13-57, src-tauri/src/notes/import.rs:90-110
Note Retrieval Flow
Retrieving a note involves a multi-step process to ensure file access permissions, especially on macOS via security-scoped bookmarks.
Web Persistence Shim
For browser-based environments where SQLite is unavailable, the system provides a shim.ts implementation. This shim implements the same command interface (e.g., notes_list, note_create) using localStorage as the backing store.
- Storage Key:
augenblick:webdb:v1 - Data Structure: The entire database state is serialized into a single JSON object containing
notes,appState, andsettings. - Logic Parity: The shim includes JavaScript implementations of the Rust-based title/preview derivation and sorting logic to ensure consistent behavior across platforms.
Sources: src/lib/tauri/shim.ts:1-25, src/lib/tauri/shim.ts:80-100
Database Maintenance and Expiry
Persistence is not permanent by design. A background sweeper thread runs every 60 seconds to enforce data retention policies stored in the settings table.
- Auto-Trash: Unpinned notes with a
last_interactionolder than the configuredexpiry_daysare updated tois_trashed = 1. - Auto-Delete: Notes in the trash for longer than
trash_retention_dayshave their database rows removed and, if they are drafts, their physical files deleted.
Sources: plans/migration.inventory.md:144-154, src/lib/tauri/shim.ts:285-300