minimost.common
minimost.common
Shared path helpers and per-user database initialisation.
This module provides two things:
Path resolution — a single
DB_DIRconstant anduser_db_path()so every other module refers to the same on-disk location without duplicating the path logic.Schema bootstrap —
init_user_db()creates (or opens) a user’s SQLite database and ensures themessagestable exists with the full column set.
Module-level attributes
- DB_DIRpathlib.Path
Absolute path to the
users/directory that stores all per-user SQLite database files. The directory is created lazily byinit_user_db()the first time it is called.
- minimost.common.user_db_path(username: str) Path[source]
Return the absolute filesystem path for a user’s SQLite database.
The path follows the pattern
<project_root>/users/<username>.db. This function does not create the file or its parent directory — useinit_user_db()for that.- Parameters:
username (str) – The account username. Must be a valid filename component (alphanumeric, hyphens, and underscores).
- Returns:
Absolute path to the user’s
.dbfile.- Return type:
Example:
path = user_db_path("alice") # e.g. PosixPath('/srv/minimost/users/alice.db')
- minimost.common._ensure_search_index(cur) None[source]
Create the trigram full-text index over
messages.content.Message search is a case-insensitive substring match. A plain
content LIKE '%q%'cannot use an index (leading wildcard) and so scans the wholemessagestable on every keystroke — cost grows linearly with history. An FTS5 virtual table with the trigram tokenizer indexes every 3-character substring, so the identical substring query is answered from the index in well under a millisecond no matter how large the history grows.The table is external-content (
content='messages'): it stores only the trigram postings, not a second copy of the message text, and is kept in sync withmessagesby the three triggers created here.tokenize='trigram'needs SQLite ≥ 3.34 (2020), which ships with every supported CPython.Idempotent — safe to call from every
init_user_db(). The first time it runs on a database that already holds messages, it indexes the existing rows with a one-off'rebuild'.
Return the absolute path of the single shared message database.
MiniMost stores every message exactly once in a single shared database (
users/messages.db) rather than copying it into a per-user file. The path is resolved from the liveDB_DIRon each call so the test suite’s monkeypatched directory is honoured.- Returns:
Absolute path to
messages.db.- Return type:
- minimost.common.init_user_db(username: str | None = None)[source]
Backwards-compatible alias for
init_messages_db().Historically each account had its own database, initialised here. The data model is now a single shared database, so username is ignored and this simply ensures the shared schema exists. Kept as a named entry point because the signup and account-recovery flows still call it per account.
- Parameters:
username – Ignored. Retained for call-site compatibility.
- Returns:
None
- minimost.common.init_messages_db()[source]
Create the shared message database and ensure its schema is current.
Idempotent — every table uses
CREATE TABLE IF NOT EXISTS, so repeated calls are safe and cheap. Creates:messages— one canonical row per message (referenced everywhere by its auto-incrementid; there are no per-user copies, so edits/deletes/ reactions act on a single row).messages_fts— the trigram substring search index (see_ensure_search_index()).reactions— one row per (message, emoji, reactor), keyed by the realmessage_idrather than a timestamp.read_state— a per-(user, channel) read watermark (last_read_ts). Unread counts and read receipts are both derived from it, so read state costs O(users × channels) rows instead of O(messages × users).dm_hidden— per-(user, channel) hidden-DM markers.
WAL keeps readers (the 500 ms pollers) from blocking the single writer;
auto_vacuum = INCREMENTALreclaims space from retention/edits without the long global lock that FULL would take on a shared file.- Returns:
None
Messages Table Schema
The messages table created by minimost.common.init_user_db()
has the following columns:
Column |
Type |
Description |
|---|---|---|
|
INTEGER PK |
Auto-increment primary key (differs across per-user databases). |
|
TEXT NOT NULL |
Public channel name or DM identifier ( |
|
TEXT NOT NULL |
Username of the message author. |
|
TEXT |
Message text body. |
|
TEXT |
Always |
|
TEXT |
UUID-based image filename. |
|
REAL NOT NULL |
Unix timestamp (seconds, floating-point). Shared across all user copies of the same message. |
|
INTEGER (0/1) |
Whether this message has been edited. |
|
REAL |
Timestamp of the most recent edit. |
|
INTEGER (0/1) |
Per-user read flag. Sender’s copy is inserted as |
|
INTEGER (0/1) |
Soft-delete flag. |
|
REAL |
Timestamp of deletion. |
|
INTEGER FK |
Foreign key to |
|
TEXT |
Legacy column (unused). Reactions are in |
|
REAL |
Updated when a reaction is toggled; triggers polling pickup. |
|
TEXT |
Reserved for future |
|
TEXT |
Reserved for future structured metadata. |
|
TEXT |
Client-generated deduplication token. |
|
REAL |
Expiry timestamp for the associated upload file. |