fix(guild): single-pass bucket filter in GuildRepository.SearchAsync

Replace double-correlated COUNT subqueries in the member-bucket switch
with a project-filter-project pattern that computes the count once per
row.  Add SearchAsync_bucket_2_matches_guilds_with_11_to_25_members to
cover the previously untested medium-bucket range.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-27 11:21:32 -04:00
parent 3fdc20d21f
commit 45947053c8
2 changed files with 34 additions and 9 deletions

View File

@@ -68,4 +68,29 @@ public class GuildRepositoryTests
var small = await repo.SearchAsync("", 0, 0, 1, 30, 50);
Assert.That(small.Select(x => x.GuildId), Has.No.Member(bigId));
}
[Test]
public async Task SearchAsync_bucket_2_matches_guilds_with_11_to_25_members()
{
await using var db = Db();
var repo = new GuildRepository(db);
// Guild with 15 members — should appear in bucket 2
var midId = 10;
await repo.AddAsync(new GuildEntity { GuildId = midId, Name = "Mid", Activity = GuildActivity.All, JoinCondition = GuildJoinCondition.Free, CreatedAt = DateTime.UtcNow });
for (int i = 0; i < 15; i++)
db.GuildMembers.Add(new GuildMember { GuildId = midId, ViewerId = 2000 + i, Role = GuildRole.Regular, JoinedAt = DateTime.UtcNow });
// Guild with 5 members — should appear in bucket 1 only
var smallId = 11;
await repo.AddAsync(new GuildEntity { GuildId = smallId, Name = "Small", Activity = GuildActivity.All, JoinCondition = GuildJoinCondition.Free, CreatedAt = DateTime.UtcNow });
for (int i = 0; i < 5; i++)
db.GuildMembers.Add(new GuildMember { GuildId = smallId, ViewerId = 3000 + i, Role = GuildRole.Regular, JoinedAt = DateTime.UtcNow });
await db.SaveChangesAsync();
var bucket2 = await repo.SearchAsync("", 0, 0, 2, 30, 50);
Assert.That(bucket2.Select(x => x.GuildId), Has.Member(midId), "15-member guild should be in bucket 2");
Assert.That(bucket2.Select(x => x.GuildId), Has.No.Member(smallId), "5-member guild must not appear in bucket 2");
}
}