v2.0.10 — snappier boot + non-blocking relay push on save
DB - Six indices on the cards table (position+created_at, bucket_id, parent_id, updated_at, caldav_uid, relay_uid). The /api/cards ORDER BY position was a full-table scan + sort on every board reload; now it's an index walk. - PRAGMA synchronous=NORMAL (safe under WAL) + temp_store=MEMORY. Save path - pushCardToRelayRead and deleteCardFromRelayRead now run AFTER the response is flushed via fastcgi_finish_request (falls back to ignore_user_abort + flush on non-FPM setups). The user's save no longer blocks on the relay round-trip. - cURL timeouts dropped from 10s/30s to 5s/10s, plus a 2s connect-timeout. Worst-case on a dead relay goes from ~160s down to ~15s — and now that worst case is in the background anyway. Client - loadCards phase-2 batches bumped from 25 to 500 cards per fetch. For 300 cards that's 1 HTTP trip instead of 12 — spinner wall time drops from ~3s to ~0.25s. - renderBoard() is now requestAnimationFrame-coalesced. The boot sequence calls renderBoard from cache paint, meta paint, body paint, and the cards.reloaded plugin hook; they used to each trigger an innerHTML swap + layout pass. Now they collapse into one actual render per frame. Callers that really need a sync render (rare) can use the new renderBoardSync(). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
87ebcd156b
commit
2d58cd993e
7 files changed
+124
-28
No files matched your search
@@ -19,6 +19,14 @@ class Database
|
||||
|
||||
self::$pdo->exec('PRAGMA journal_mode = WAL');
|
||||
self::$pdo->exec('PRAGMA foreign_keys = ON');
|
||||
// Safe speedups under WAL. synchronous=NORMAL trades a tiny
|
||||
// durability window on power-loss (WAL checkpoint hasn't
|
||||
// flushed) for noticeably quicker write-heavy flows — fine for
|
||||
// a single-user local-first app. temp_store=MEMORY keeps
|
||||
// transient sort / group scratch in RAM instead of touching
|
||||
// disk for every ORDER BY.
|
||||
self::$pdo->exec('PRAGMA synchronous = NORMAL');
|
||||
self::$pdo->exec('PRAGMA temp_store = MEMORY');
|
||||
|
||||
self::migrate();
|
||||
}
|
||||
@@ -188,5 +196,17 @@ class Database
|
||||
)
|
||||
');
|
||||
self::$pdo->exec('CREATE INDEX IF NOT EXISTS idx_login_attempts_ip_ep ON login_attempts(ip, endpoint, attempted_at)');
|
||||
|
||||
// Hot-path indices for the board. /api/cards is called on every
|
||||
// reload and runs `SELECT … FROM cards LEFT JOIN buckets ORDER BY
|
||||
// position, created_at`. Without an index on position this is a
|
||||
// full-table sort on every call — fine at 10 cards, noticeable at
|
||||
// 300+.
|
||||
self::$pdo->exec('CREATE INDEX IF NOT EXISTS idx_cards_position ON cards(position, created_at)');
|
||||
self::$pdo->exec('CREATE INDEX IF NOT EXISTS idx_cards_bucket_id ON cards(bucket_id)');
|
||||
self::$pdo->exec('CREATE INDEX IF NOT EXISTS idx_cards_parent_id ON cards(parent_id)');
|
||||
self::$pdo->exec('CREATE INDEX IF NOT EXISTS idx_cards_updated_at ON cards(updated_at DESC)');
|
||||
self::$pdo->exec('CREATE INDEX IF NOT EXISTS idx_cards_caldav_uid ON cards(caldav_uid) WHERE caldav_uid IS NOT NULL');
|
||||
self::$pdo->exec('CREATE INDEX IF NOT EXISTS idx_cards_relay_uid ON cards(relay_uid) WHERE relay_uid IS NOT NULL');
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,24 @@ function hyprcrdRelayDecrypt(string $envelope, string $secret): string {
|
||||
return $envelope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise the HTTP response (headers + body already echoed) and let
|
||||
* PHP continue working in the background without blocking the client.
|
||||
* Under php-fpm this uses fastcgi_finish_request. Under mod_php / the
|
||||
* built-in dev server we fall back to ignore_user_abort + flush — the
|
||||
* client may still see the connection hold open, but at least it
|
||||
* doesn't error on disconnect and the response is already buffered.
|
||||
*/
|
||||
function hyprcrdFinishRequest(): void {
|
||||
if (function_exists('fastcgi_finish_request')) {
|
||||
fastcgi_finish_request();
|
||||
return;
|
||||
}
|
||||
@ignore_user_abort(true);
|
||||
if (ob_get_level() > 0) { @ob_end_flush(); }
|
||||
@flush();
|
||||
}
|
||||
|
||||
function hyprcrdUrlHostIsPublic(string $url): bool {
|
||||
$host = parse_url($url, PHP_URL_HOST);
|
||||
if (!$host) return false;
|
||||
|
||||
Reference in new issue
Block a user