mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-04 08:15:41 +00:00
Review of the offline drafts found these. - Every new message gets new part ids and old ones die with it, so an open composer failed with `blobNotFound` after a flush. The client and the flush re-read the draft and re-point parts once. The fake now gives new part ids, which is why `drafts.test.ts` and `drafts-client.test.ts` compare file contents instead of blob ids. - A Message-ID alone could destroy another client's message. A copy now has to be solely in Drafts, with `$draft`, close to the attempt, with the same subject and size, and what the lookup saw is the destroy's base. Ghosts ride on the replacing row and only queue once it's up. `drafts.created` no longer queues a copy that arrived for a replaced row, so its test now expects the next flush to do it. - Turning offline off asks about device-only drafts too. - A kept file can't read back empty: chunks of a kept file are left alone, and `keptBlob` and `heldFile` refuse pieces that don't add up. - A flush stopped by a passing failure tries again, the banner shows waiting drafts, and under the flush lock a `sending` row counts as left by a dead tab at once. A lookup refused for good no longer stops the outbox. - `FetchTransport` streams downloads and reports a broken transfer as interrupted, so one bad file doesn't end the pass. - Raw messages come after every file, only into free room, and a file needing room pushes them out first. - An old version in another login stays until the new one is up. An online send of an unflushed stand-in still removes its submission.
78 lines
2.7 KiB
TypeScript
78 lines
2.7 KiB
TypeScript
import type { Migration } from '../storage';
|
|
|
|
export const DRAFT_MIGRATIONS: readonly Migration[] = [
|
|
{
|
|
id: 400,
|
|
name: 'drafts',
|
|
sql: `
|
|
-- A draft saved on this device and not on the server yet. One row per
|
|
-- draft: a later save takes over from the row before it.
|
|
CREATE TABLE draft_pending (
|
|
local_id TEXT PRIMARY KEY,
|
|
jmap TEXT NOT NULL,
|
|
seq INTEGER NOT NULL,
|
|
subject TEXT,
|
|
-- The create as the client wrote it, with its fixed Message-ID.
|
|
create_json TEXT NOT NULL,
|
|
message_id TEXT NOT NULL,
|
|
-- Versions on the server this one replaces: destroyed after it's there.
|
|
replaces TEXT NOT NULL DEFAULT '[]',
|
|
status TEXT NOT NULL DEFAULT 'waiting',
|
|
sending_since INTEGER,
|
|
-- Set once it may have reached the server: then it's looked up first.
|
|
first_attempt_at INTEGER,
|
|
last_attempt_at INTEGER,
|
|
-- What this version should look like on the server.
|
|
size INTEGER NOT NULL DEFAULT 0,
|
|
-- Earlier versions that may have reached the server. Only removed once
|
|
-- this one is there, and only if they still look like those versions.
|
|
ghosts TEXT NOT NULL DEFAULT '[]',
|
|
error TEXT,
|
|
created_at INTEGER NOT NULL
|
|
) WITHOUT ROWID;
|
|
-- What a stand-in id became. The page may hold one for a long time.
|
|
CREATE TABLE draft_id_map (
|
|
local_id TEXT PRIMARY KEY,
|
|
jmap TEXT NOT NULL,
|
|
server_id TEXT NOT NULL,
|
|
at INTEGER NOT NULL
|
|
) WITHOUT ROWID;
|
|
-- A version that may have reached the server, of a draft discarded here
|
|
-- since. Looked up and removed when the server is back.
|
|
CREATE TABLE draft_ghost (
|
|
jmap TEXT NOT NULL,
|
|
message_id TEXT NOT NULL,
|
|
first_at INTEGER NOT NULL,
|
|
last_at INTEGER NOT NULL,
|
|
subject TEXT NOT NULL,
|
|
size INTEGER NOT NULL,
|
|
PRIMARY KEY (jmap, message_id)
|
|
) WITHOUT ROWID;
|
|
-- An old version in another login: this store can't queue it. Removed
|
|
-- through that login once local_id is NULL: the new version is up, or the
|
|
-- draft was discarded or sent.
|
|
CREATE TABLE draft_elsewhere (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
local_id TEXT,
|
|
login TEXT NOT NULL,
|
|
jmap TEXT,
|
|
record_id TEXT NOT NULL
|
|
);
|
|
`,
|
|
},
|
|
{
|
|
id: 401,
|
|
name: 'held files in chunks',
|
|
sql: `
|
|
ALTER TABLE upload ADD COLUMN complete INTEGER NOT NULL DEFAULT 1;
|
|
-- Binding a whole file grows the WASM heap by its size, and that never shrinks.
|
|
CREATE TABLE upload_chunk (
|
|
local_id TEXT NOT NULL,
|
|
seq INTEGER NOT NULL,
|
|
data BLOB NOT NULL,
|
|
PRIMARY KEY (local_id, seq)
|
|
);
|
|
`,
|
|
},
|
|
];
|