diff --git a/src/models/database/guild-storage.ts b/src/models/database/guild-storage.ts index 1ed743d..9906d6e 100644 --- a/src/models/database/guild-storage.ts +++ b/src/models/database/guild-storage.ts @@ -12,7 +12,7 @@ export interface IGuildStorage extends Document { } export const GuildStorageSchema = new Schema({ - guildId: { type: Schema.Types.String, required: true }, + guildId: { type: Schema.Types.String, required: true, index: true }, majorImplements: { type: Map, diff --git a/src/models/database/user.ts b/src/models/database/user.ts index 0023736..0e7d5ac 100644 --- a/src/models/database/user.ts +++ b/src/models/database/user.ts @@ -24,8 +24,8 @@ export interface IUserCourseAssignment { } export const UserSchema = new Schema({ - discordUserId: { type: Schema.Types.String, required: true, unique: true }, - studentId: { type: Schema.Types.String, required: false }, + discordUserId: { type: Schema.Types.String, required: true, unique: true, index: true }, + studentId: { type: Schema.Types.String, required: false, index: true }, verificationStatus: { type: Schema.Types.Number, required: true, default: VerificationStatus.UNVERIFIED }, verificationCode: { type: Schema.Types.String, required: false }, diff --git a/src/services/database/guild-storage.ts b/src/services/database/guild-storage.ts index c617532..be226ee 100644 --- a/src/services/database/guild-storage.ts +++ b/src/services/database/guild-storage.ts @@ -1,5 +1,5 @@ import { GuildContext } from "guild-context"; -import { Course, PartialCourse } from "models/course"; +import { PartialCourse } from "models/course"; import { GuildStorage, IGuildStorage } from "models/database/guild-storage"; import { ICourseImplement } from "models/implement/course"; import { IMajorImplement } from "models/implement/major"; @@ -7,24 +7,42 @@ import { IVerificationImplement } from "models/implement/verification"; import { Major } from "models/major"; export class GuildStorageDatabaseService { + private static CACHE: {[guildId: string]: IGuildStorage} = {} + public static async findOrCreateGuildStorage(guildContext: GuildContext): Promise { + // Check cache. + let storage = this.CACHE[guildContext.guild.id]; + if(storage) { + return storage; + } + // Find existing storage. - let storage = await GuildStorage.findOne({ guildId: guildContext.guild.id }).exec(); + storage = await GuildStorage.findOne({ guildId: guildContext.guild.id }).exec(); if (storage) { + this.cache(guildContext, storage); return storage; } // Create a new storage. guildContext.guildLog("Creating Guild Storage"); let majorImplements = new Map(); - storage = await new GuildStorage({ + storage = new GuildStorage({ guildId: guildContext.guild.id, majorImplements, - }).save(); + }); + await this.saveAndCache(guildContext, storage); guildContext.guildLog("Storage created: " + storage.id); return storage; } + private static cache(guildContext: GuildContext, storage: IGuildStorage): void { + this.CACHE[guildContext.guild.id] = storage; + } + + private static async saveAndCache(guildContext: GuildContext, storage: IGuildStorage): Promise { + this.cache(guildContext, await storage.save()); + } + public static async getMajorImplement(guildContext: GuildContext, major: Major): Promise { const storage = await this.findOrCreateGuildStorage(guildContext); const majorData = storage.majorImplements.get(major.prefix); @@ -38,8 +56,9 @@ export class GuildStorageDatabaseService { storage.majorImplements.set(major.prefix, implement); else storage.majorImplements.delete(major.prefix); - - await storage.save(); + + storage.markModified("majorImplements"); + await this.saveAndCache(guildContext, storage); } public static async getCourseImplement(guildContext: GuildContext, course: PartialCourse): Promise { @@ -63,7 +82,8 @@ export class GuildStorageDatabaseService { else majorImplement.courseImplements.delete(course.key); - await storage.save(); + storage.markModified(`majorImplements.${course.major.prefix}.courseImplements`); + await this.saveAndCache(guildContext, storage); } public static async getVerificationImplement(guildContext: GuildContext): Promise { @@ -74,6 +94,6 @@ export class GuildStorageDatabaseService { public static async setVerificationImplement(guildContext: GuildContext, implement: IVerificationImplement): Promise { const storage = await this.findOrCreateGuildStorage(guildContext); storage.verificationImplement = implement; - await storage.save(); + await this.saveAndCache(guildContext, storage); } } \ No newline at end of file diff --git a/src/services/discord/role-assignment.ts b/src/services/discord/role-assignment.ts index cd3ee62..e0356be 100644 --- a/src/services/discord/role-assignment.ts +++ b/src/services/discord/role-assignment.ts @@ -53,7 +53,7 @@ export class DiscordRoleAssignmentService { } // Apply assignments. - guildContext.guildDebug(`+${rolesToAdd.length}/-${rolesToRemove.length} roles for ${DiscordUtils.describeUserForLogs(discordMember.user)}.`); + guildContext.guildLog(`+${rolesToAdd.length}/-${rolesToRemove.length} roles for ${DiscordUtils.describeUserForLogs(discordMember.user)}.`); if (rolesToAdd.length > 0) discordMember = await discordMember.roles.add(rolesToAdd, "StudyBot automatic role assignment."); if (rolesToRemove.length > 0) diff --git a/src/services/health-assurance.ts b/src/services/health-assurance.ts index 19044bd..b1a1c6f 100644 --- a/src/services/health-assurance.ts +++ b/src/services/health-assurance.ts @@ -51,10 +51,10 @@ export class HealthAssuranceService { } // Synchronize roles. - /* await MemberUpdateService.queueSynchronizeRolesManyMembers( + await MemberUpdateService.queueSynchronizeRolesManyMembers( this.guildContext, members.array().filter(m => m.user.id !== this.guildContext.guild.client.user.id) - ); */ + ); //const users = await UserDatabaseService.getAllUsers(); diff --git a/src/services/implement/course/implement.ts b/src/services/implement/course/implement.ts index 63b695a..2be60f6 100644 --- a/src/services/implement/course/implement.ts +++ b/src/services/implement/course/implement.ts @@ -81,15 +81,15 @@ export class CourseImplementService { // Main Role if(!await guildContext.guild.roles.fetch(implement.mainRoleId)) { + guildContext.guildLog(`Creating missing main role for course ${course.key}`); implement.mainRoleId = (await CourseRoleImplementService.createMainRole(guildContext, course)).id; - guildContext.guildLog(`Created missing main role for course ${course.key}`); update = true; } // TA Role if(!await guildContext.guild.roles.fetch(implement.taRoleId)) { + guildContext.guildLog(`Creating missing TA role for course ${course.key}`); implement.taRoleId = (await CourseRoleImplementService.createTARole(guildContext, course)).id; - guildContext.guildLog(`Created missing TA role for course ${course.key}`); update = true; } @@ -97,13 +97,13 @@ export class CourseImplementService { for(let type of CourseImplementChannelType.values()) { const channel = guildContext.guild.channels.resolve(implement.channelIds[type]); if(!channel) { + guildContext.guildLog(`Creating missing ${CourseImplementChannelType[type]} channel for course ${course.key}`); const majorCategoryId = await MajorImplementService.getCategoryIdForNewCourseImplement(guildContext, course.major, type); implement.channelIds[type] = (await CourseChannelImplementService.createChannelByType(guildContext, type, course, majorCategoryId, implement.mainRoleId, implement.taRoleId)).id; - guildContext.guildLog(`Created missing ${CourseImplementChannelType[type]} channel for course ${course.key}`); update = true; } else { + guildContext.guildLog(`Resetting ${CourseImplementChannelType[type]} channel permissions for course ${course.key}`); await CourseChannelImplementService.resetChannelPermissionsByType(guildContext, type, implement.mainRoleId, implement.taRoleId, channel); - guildContext.guildLog(`Reset ${CourseImplementChannelType[type]} channel permissions for course ${course.key}`); } } diff --git a/src/services/implement/major/implement.ts b/src/services/implement/major/implement.ts index 8e3dfdd..0790f29 100644 --- a/src/services/implement/major/implement.ts +++ b/src/services/implement/major/implement.ts @@ -201,8 +201,8 @@ export class MajorImplementService { } // Pre-sort roles - mainRoles = mainRoles.sort((roleA, roleB) => roleA.name.localeCompare(roleB.name)); - taRoles = taRoles.sort((roleA, roleB) => roleA.name.localeCompare(roleB.name)); + mainRoles = mainRoles.sort((roleA, roleB) => roleB.name.localeCompare(roleA.name)); + taRoles = taRoles.sort((roleA, roleB) => roleB.name.localeCompare(roleA.name)); // Calculate role positions const rolePositions: Discord.RolePosition[] = [];