From c728e05032852704c09cb18ed35d47c3135a6367 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Wed, 22 Jan 2025 19:19:50 -0500 Subject: [PATCH] ssb: Add a lookup table of max sequence and timestamp per account.f --- apps/ssb.json | 2 +- apps/ssb/tf-app.js | 5 ++--- apps/ssb/tf-tab-news-feed.js | 23 +++++++---------------- src/ssb.db.c | 19 +++++++++++++++++-- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/apps/ssb.json b/apps/ssb.json index 53ef165c..3b4adc9e 100644 --- a/apps/ssb.json +++ b/apps/ssb.json @@ -1,5 +1,5 @@ { "type": "tildefriends-app", "emoji": "🦀", - "previous": "&cnc92v8+8JMxSIvs6vZ6j01rUzyVtKg6zkITqwQ02Lc=.sha256" + "previous": "&dQu+yQ4/be0vcgIZSMKtesQCbH8lVhHcZAEv9+dNknY=.sha256" } diff --git a/apps/ssb/tf-app.js b/apps/ssb/tf-app.js index d96f3038..04746bea 100644 --- a/apps/ssb/tf-app.js +++ b/apps/ssb/tf-app.js @@ -402,10 +402,9 @@ class TfElement extends LitElement { async fetch_user_info(users) { let info = await tfrpc.rpc.query( ` - SELECT messages.author, MAX(messages.sequence) AS max_seq, MAX(timestamp) AS max_ts FROM messages + SELECT messages_stats.author, messages_stats.max_sequence, messages_stats.max_timestamp AS max_ts FROM messages_stats JOIN json_each(?) AS following - ON messages.author = following.value - GROUP BY messages.author + ON messages_stats.author = following.value `, [JSON.stringify(Object.keys(users))] ); diff --git a/apps/ssb/tf-tab-news-feed.js b/apps/ssb/tf-tab-news-feed.js index 367842ce..5576299f 100644 --- a/apps/ssb/tf-tab-news-feed.js +++ b/apps/ssb/tf-tab-news-feed.js @@ -190,11 +190,7 @@ class TfTabNewsFeedElement extends LitElement { UNION SELECT TRUE AS is_primary, news.* FROM news `, - [ - JSON.stringify(this.following), - start_time, - end_time, - ] + [JSON.stringify(this.following), start_time, end_time] ); } this.time_loading = undefined; @@ -223,9 +219,7 @@ class TfTabNewsFeedElement extends LitElement { let last_start_time = this.time_range[0]; more = await this.fetch_messages(null, last_start_time); this.update_time_range_from_messages( - more.filter( - (x) => x.timestamp < last_start_time - ) + more.filter((x) => x.timestamp < last_start_time) ); this.messages = await this.decrypt([...more, ...this.messages]); } finally { @@ -315,14 +309,9 @@ class TfTabNewsFeedElement extends LitElement { let start_time = now - 24 * 60 * 60 * 1000; this.start_time = start_time; this.time_range = [this.start_time, now + 24 * 60 * 60 * 1000]; - messages = await this.fetch_messages( - null, - this.time_range[1] - ); + messages = await this.fetch_messages(null, this.time_range[1]); this.update_time_range_from_messages( - messages.filter( - (x) => x.timestamp < this.time_range[1] - ) + messages.filter((x) => x.timestamp < this.time_range[1]) ); messages = await this.decrypt(messages); } finally { @@ -330,7 +319,9 @@ class TfTabNewsFeedElement extends LitElement { } this.messages = this.merge_messages(this.messages, messages); this.time_loading = undefined; - console.log(`loading messages done for ${self.whoami} in ${(new Date() - start_time) / 1000}s`); + console.log( + `loading messages done for ${self.whoami} in ${(new Date() - start_time) / 1000}s` + ); } mark_all_read() { diff --git a/src/ssb.db.c b/src/ssb.db.c index 867cd521..3d311ec0 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -108,6 +108,20 @@ void tf_ssb_db_init(tf_ssb_t* ssb) " flags INTEGER," " UNIQUE(author, sequence)" ")"); + _tf_ssb_db_exec(db, + "CREATE TABLE IF NOT EXISTS messages_stats (" + " author TEXT PRIMARY KEY," + " max_sequence INTEGER," + " max_timestamp READ" + ")"); + _tf_ssb_db_exec(db, + "CREATE TRIGGER IF NOT EXISTS messages_ai_stats AFTER INSERT ON messages BEGIN INSERT INTO messages_stats(author, max_sequence, max_timestamp) VALUES (new.author, " + "new.sequence, new.timestamp) ON CONFLICT DO UPDATE SET max_sequence = MAX(max_sequence, excluded.max_sequence), max_timestamp = MAX(max_timestamp, " + "excluded.max_timestamp); END"); + _tf_ssb_db_exec(db, + "CREATE TRIGGER IF NOT EXISTS messages_ad_stats AFTER DELETE ON messages BEGIN UPDATE messages_stats SET max_sequence = (SELECT MAX(messages.sequence) FROM messages WHERE " + "messages.author = old.author), max_timestamp = (SELECT MAX(messages.timestamp) FROM messages WHERE messages.author = old.author); END"); + _tf_ssb_db_exec(db, "INSERT OR REPLACE INTO messages_stats (author, max_sequence, max_timestamp) SELECT author, MAX(sequence), MAX(timestamp) FROM messages GROUP BY author"); if (_tf_ssb_db_has_rows(db, "SELECT name FROM pragma_table_info('messages') WHERE name = 'content' AND type == 'TEXT'")) { @@ -987,8 +1001,9 @@ int tf_ssb_sqlite_authorizer(void* user_data, int action_code, const char* arg0, break; case SQLITE_READ: result = (strcmp(arg0, "blob_wants_view") == 0 || strcmp(arg0, "json_each") == 0 || strcmp(arg0, "json_tree") == 0 || strcmp(arg0, "messages") == 0 || - strcmp(arg0, "messages_fts") == 0 || strcmp(arg0, "messages_fts_idx") == 0 || strcmp(arg0, "messages_fts_config") == 0 || strcmp(arg0, "messages_refs") == 0 || - strcmp(arg0, "messages_refs_message_idx") == 0 || strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "sqlite_master") == 0 || false) + strcmp(arg0, "messages_stats") == 0 || strcmp(arg0, "messages_fts") == 0 || strcmp(arg0, "messages_fts_idx") == 0 || + strcmp(arg0, "messages_fts_config") == 0 || strcmp(arg0, "messages_refs") == 0 || strcmp(arg0, "messages_refs_message_idx") == 0 || + strcmp(arg0, "messages_refs_ref_idx") == 0 || strcmp(arg0, "sqlite_master") == 0 || false) ? SQLITE_OK : SQLITE_DENY; break;