perf(api): cache channel and guild reads for the request (#2220)

This commit is contained in:
Hampus authored and GitHub committed 2026-08-31 00:22:52 +02:00
1 parent ab08ed0d7c
commit c4b1471923
11 files changed
+226 -26

No files matched your search

@@ -4,6 +4,7 @@ import type {GuildID, UserID} from '../../BrandedTypes';
import {BatchBuilder, fetchMany, fetchOne} from '../../database/CassandraQueryExecution';
import {buildPatchFromData, executeVersionedUpdate} from '../../database/CassandraVersionedUpdate';
import {GUILD_COLUMNS, type GuildMemberByUserIdRow, type GuildRow} from '../../database/types/GuildTypes';
import type {RequestCache} from '../../middleware/RequestCacheMiddleware';
import {Guild} from '../../models/Guild';
import {GuildMembersByUserId, Guilds} from '../../Tables';
import {IGuildDataRepository} from './IGuildDataRepository';
@@ -26,7 +27,15 @@ function createFetchAllGuildsFirstPageQuery(limit: number) {
}
export class GuildDataRepository extends IGuildDataRepository {
constructor(private readonly requestCache?: RequestCache) {
super();
}
async findUnique(guildId: GuildID): Promise<Guild | null> {
const prefetched = this.requestCache?.takeGuild(guildId);
if (prefetched !== undefined) {
return prefetched;
}
const guild = await fetchOne<GuildRow>(FETCH_GUILD_BY_ID_QUERY, {
guild_id: guildId,
});
@@ -87,6 +96,7 @@ export class GuildDataRepository extends IGuildDataRepository {
async upsert(data: GuildRow, oldData?: GuildRow | null, _previousOwnerId?: UserID): Promise<Guild> {
const guildId = data.guild_id;
this.requestCache?.guilds.delete(guildId);
const result = await executeVersionedUpdate<GuildRow, 'guild_id'>(
async () => fetchOne<GuildRow>(FETCH_GUILD_BY_ID_QUERY, {guild_id: guildId}),
(current) => ({
@@ -105,6 +115,7 @@ export class GuildDataRepository extends IGuildDataRepository {
oldData?: GuildRow | null,
_previousOwnerId?: UserID,
): Promise<Guild> {
this.requestCache?.guilds.delete(guildId);
const result = await executeVersionedUpdate<GuildRow, 'guild_id'>(
async () => fetchOne<GuildRow>(FETCH_GUILD_BY_ID_QUERY, {guild_id: guildId}),
(current) => ({
@@ -122,6 +133,7 @@ export class GuildDataRepository extends IGuildDataRepository {
}
async delete(guildId: GuildID, _ownerId?: UserID): Promise<void> {
this.requestCache?.guilds.delete(guildId);
const guild = await fetchOne<GuildRow>(FETCH_GUILD_BY_ID_QUERY, {guild_id: guildId});
if (!guild) {
return;
@@ -13,6 +13,7 @@ import type {
GuildBanRow,
GuildRow,
} from '../../database/types/GuildTypes';
import type {RequestCache} from '../../middleware/RequestCacheMiddleware';
import {GuildAuditLog} from '../../models/GuildAuditLog';
import {GuildBan} from '../../models/GuildBan';
import {
@@ -55,6 +56,10 @@ const FETCH_GUILD_AUDIT_LOGS_BY_IDS_QUERY = GuildAuditLogs.selectCql({
});
export class GuildModerationRepository extends IGuildModerationRepository {
constructor(private readonly requestCache?: RequestCache) {
super();
}
async getBan(guildId: GuildID, userId: UserID): Promise<GuildBan | null> {
const ban = await fetchOne<GuildBanRow>(FETCH_GUILD_BAN_BY_GUILD_AND_USER_ID_QUERY, {
guild_id: guildId,
@@ -279,6 +284,7 @@ export class GuildModerationRepository extends IGuildModerationRepository {
}
async updateAuditLogsIndexedAt(guildId: GuildID, indexedAt: Date | null): Promise<void> {
this.requestCache?.guilds.delete(guildId);
await executeVersionedUpdate<GuildRow, 'guild_id'>(
() => fetchOne<GuildRow>(FETCH_GUILD_BY_ID_QUERY, {guild_id: guildId}),
(current) => {
@@ -12,6 +12,7 @@ import type {
GuildRow,
GuildStickerRow,
} from '../../database/types/GuildTypes';
import type {RequestCache} from '../../middleware/RequestCacheMiddleware';
import type {Guild} from '../../models/Guild';
import type {GuildAuditLog} from '../../models/GuildAuditLog';
import type {GuildBan} from '../../models/GuildBan';
@@ -33,11 +34,11 @@ export class GuildRepository implements IGuildRepositoryAggregate {
private moderationRepo: GuildModerationRepository;
private contentRepo: GuildContentRepository;
constructor() {
this.dataRepo = new GuildDataRepository();
constructor(requestCache?: RequestCache) {
this.dataRepo = new GuildDataRepository(requestCache);
this.memberRepo = new GuildMemberRepository();
this.roleRepo = new GuildRoleRepository();
this.moderationRepo = new GuildModerationRepository();
this.moderationRepo = new GuildModerationRepository(requestCache);
this.contentRepo = new GuildContentRepository();
}