ssb: Reduce redundant work in ssb.following.

This commit is contained in:
Cory McWilliams 2025-05-11 22:20:16 -04:00
parent 35656a5c34
commit 1f2664e5a8

View File

@ -1577,75 +1577,65 @@ static following_t* _make_following_node(const char* id, following_t*** followin
return entry; return entry;
} }
static void _populate_follows_and_blocks(tf_ssb_t* ssb, following_t* entry, following_t*** following, int* following_count, block_node_t* active_blocks, bool include_blocks) static void _populate_follows_and_blocks(
sqlite3* db, sqlite3_stmt* statement, following_t* entry, following_t*** following, int* following_count, block_node_t* active_blocks, bool include_blocks)
{ {
sqlite3* db = tf_ssb_acquire_db_reader(ssb); if (sqlite3_bind_text(statement, 1, entry->id, -1, NULL) == SQLITE_OK)
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db,
"SELECT content ->> '$.contact' AS contact, content ->> '$.following', content ->> '$.blocking' "
"FROM messages "
"WHERE contact IS NOT NULL AND author = ? AND content ->> '$.type' = 'contact' "
"ORDER BY sequence",
-1, &statement, NULL) == SQLITE_OK)
{ {
if (sqlite3_bind_text(statement, 1, entry->id, -1, NULL) == SQLITE_OK) while (sqlite3_step(statement) == SQLITE_ROW)
{ {
while (sqlite3_step(statement) == SQLITE_ROW) const char* contact = (const char*)sqlite3_column_text(statement, 0);
if (sqlite3_column_type(statement, 1) != SQLITE_NULL)
{ {
const char* contact = (const char*)sqlite3_column_text(statement, 0); bool is_following = sqlite3_column_int(statement, 1) != 0;
if (sqlite3_column_type(statement, 1) != SQLITE_NULL) following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks);
if (next)
{ {
bool is_following = sqlite3_column_int(statement, 1) != 0; if (is_following)
following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks);
if (next)
{ {
if (is_following) if (_add_following_entry(&entry->following, &entry->following_count, next))
{ {
if (_add_following_entry(&entry->following, &entry->following_count, next)) next->ref_count++;
{
next->ref_count++;
}
} }
else }
else
{
if (_remove_following_entry(&entry->following, &entry->following_count, next))
{ {
if (_remove_following_entry(&entry->following, &entry->following_count, next)) next->ref_count--;
{
next->ref_count--;
}
} }
} }
} }
if (sqlite3_column_type(statement, 2) != SQLITE_NULL) }
if (sqlite3_column_type(statement, 2) != SQLITE_NULL)
{
bool is_blocking = sqlite3_column_int(statement, 2) != 0;
following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks);
if (next)
{ {
bool is_blocking = sqlite3_column_int(statement, 2) != 0; if (is_blocking)
following_t* next = _make_following_node(contact, following, following_count, active_blocks, include_blocks);
if (next)
{ {
if (is_blocking) if (_add_following_entry(&entry->blocking, &entry->blocking_count, next))
{ {
if (_add_following_entry(&entry->blocking, &entry->blocking_count, next)) next->block_ref_count++;
{
next->block_ref_count++;
}
} }
else }
else
{
if (_remove_following_entry(&entry->blocking, &entry->blocking_count, next))
{ {
if (_remove_following_entry(&entry->blocking, &entry->blocking_count, next)) next->block_ref_count--;
{
next->block_ref_count--;
}
} }
} }
} }
} }
} }
sqlite3_finalize(statement);
} }
tf_ssb_release_db_reader(ssb, db); sqlite3_reset(statement);
} }
static void _get_following( static void _get_following(sqlite3* db, sqlite3_stmt* statement, following_t* entry, following_t*** following, int* following_count, int depth, int max_depth,
tf_ssb_t* ssb, following_t* entry, following_t*** following, int* following_count, int depth, int max_depth, block_node_t* active_blocks, bool include_blocks) block_node_t* active_blocks, bool include_blocks)
{ {
int old_depth = entry->depth; int old_depth = entry->depth;
entry->depth = tf_min(depth, entry->depth); entry->depth = tf_min(depth, entry->depth);
@ -1656,28 +1646,47 @@ static void _get_following(
if (!entry->populated) if (!entry->populated)
{ {
entry->populated = true; entry->populated = true;
_populate_follows_and_blocks(ssb, entry, following, following_count, active_blocks, include_blocks); _populate_follows_and_blocks(db, statement, entry, following, following_count, active_blocks, include_blocks);
} }
block_node_t blocks = { .entry = entry, .parent = active_blocks }; block_node_t blocks = { .entry = entry, .parent = active_blocks };
for (int i = 0; i < entry->following_count; i++) for (int i = 0; i < entry->following_count; i++)
{ {
_get_following(ssb, entry->following[i], following, following_count, depth + 1, max_depth, &blocks, include_blocks); _get_following(db, statement, entry->following[i], following, following_count, depth + 1, max_depth, &blocks, include_blocks);
} }
} }
} }
} }
static sqlite3_stmt* _make_following_statement(sqlite3* db)
{
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db,
"SELECT content ->> '$.contact' AS contact, content ->> '$.following', content ->> '$.blocking' "
"FROM messages "
"WHERE contact IS NOT NULL AND author = ? AND content ->> '$.type' = 'contact' "
"ORDER BY sequence",
-1, &statement, NULL) != SQLITE_OK)
{
tf_printf("prepare failed: %s", sqlite3_errmsg(db));
}
return statement;
}
tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth, bool include_blocks) tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth, bool include_blocks)
{ {
following_t** following = NULL; following_t** following = NULL;
int following_count = 0; int following_count = 0;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = _make_following_statement(db);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL, include_blocks); following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL, include_blocks);
_get_following(ssb, entry, &following, &following_count, 0, depth, NULL, include_blocks); _get_following(db, statement, entry, &following, &following_count, 0, depth, NULL, include_blocks);
entry->ref_count++; entry->ref_count++;
} }
sqlite3_finalize(statement);
tf_ssb_release_db_reader(ssb, db);
int actual_following_count = 0; int actual_following_count = 0;
for (int i = 0; i < following_count; i++) for (int i = 0; i < following_count; i++)
@ -1721,12 +1730,17 @@ const char** tf_ssb_db_following_deep_ids(tf_ssb_t* ssb, const char** ids, int c
{ {
following_t** following = NULL; following_t** following = NULL;
int following_count = 0; int following_count = 0;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = _make_following_statement(db);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL, false); following_t* entry = _make_following_node(ids[i], &following, &following_count, NULL, false);
_get_following(ssb, entry, &following, &following_count, 0, depth, NULL, false); _get_following(db, statement, entry, &following, &following_count, 0, depth, NULL, false);
entry->ref_count++; entry->ref_count++;
} }
sqlite3_finalize(statement);
tf_ssb_release_db_reader(ssb, db);
int actual_following_count = 0; int actual_following_count = 0;
for (int i = 0; i < following_count; i++) for (int i = 0; i < following_count; i++)