Cache unseen message count

This commit is contained in:
Joscha 2022-08-09 00:28:11 +02:00
parent 888870b779
commit 453233be9c
2 changed files with 72 additions and 4 deletions

View file

@ -1224,10 +1224,9 @@ impl EuphRequest {
let amount = conn
.prepare(
"
SELECT COUNT(*)
FROM euph_msgs
SELECT amount
FROM euph_unseen_counts
WHERE room = ?
AND NOT seen
",
)?
.query_row(params![room], |row| row.get(0))?;

View file

@ -2,6 +2,7 @@ use rusqlite::Connection;
pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
println!("Opening vault");
// This temporary table has no foreign key constraint on euph_rooms since
// cross-schema constraints like that are not supported by SQLite.
conn.execute_batch(
@ -28,5 +29,73 @@ pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
AND parents.id = euph_msgs.parent
);
",
)
)?;
// Cache amount of unseen messages per room because counting them takes far
// too long. Uses triggers to move as much of the updating logic as possible
// into SQLite.
conn.execute_batch(
"
CREATE TEMPORARY TABLE euph_unseen_counts (
room TEXT NOT NULL,
amount INTEGER NOT NULL,
PRIMARY KEY (room)
) STRICT;
-- There must be an entry for every existing room.
INSERT INTO euph_unseen_counts (room, amount)
SELECT room, 0
FROM euph_rooms;
INSERT OR REPLACE INTO euph_unseen_counts (room, amount)
SELECT room, COUNT(*)
FROM euph_msgs
WHERE NOT seen
GROUP BY room;
CREATE TEMPORARY TRIGGER euc_insert_room
AFTER INSERT ON euph_rooms
BEGIN
INSERT INTO euph_unseen_counts (room, amount)
VALUES (new.room, 0);
END;
CREATE TEMPORARY TRIGGER euc_delete_room
AFTER DELETE ON euph_rooms
BEGIN
DELETE FROM euph_unseen_counts
WHERE room = old.room;
END;
CREATE TEMPORARY TRIGGER euc_insert_msg
AFTER INSERT ON euph_msgs
WHEN NOT new.seen
BEGIN
UPDATE euph_unseen_counts
SET amount = amount + 1
WHERE room = new.room;
END;
CREATE TEMPORARY TRIGGER euc_update_msg
AFTER UPDATE OF seen ON euph_msgs
WHEN old.seen != new.seen
BEGIN
UPDATE euph_unseen_counts
SET amount = CASE WHEN new.seen THEN amount - 1 ELSE amount + 1 END
WHERE room = new.room;
END;
CREATE TEMPORARY TRIGGER euc_delete_msg
AFTER DELETE ON euph_msgs
WHEN NOT old.seen
BEGIN
UPDATE euph_unseen_counts
SET amount = amount - 1
WHERE room = old.room;
END;
",
)?;
Ok(())
}