feat(Managers): add customizable caching for managers (#6013)

This commit is contained in:
1Computer1
2021-07-03 19:26:26 -04:00
committed by GitHub
parent ec06ba7ad0
commit 8c7cb0eff8
35 changed files with 498 additions and 316 deletions

View File

@@ -1,18 +1,18 @@
'use strict';
const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager');
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const ApplicationCommand = require('../structures/ApplicationCommand');
const Collection = require('../util/Collection');
/**
* Manages API methods for application commands and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class ApplicationCommandManager extends BaseManager {
class ApplicationCommandManager extends CachedManager {
constructor(client, iterable) {
super(client, iterable, ApplicationCommand);
super(client, ApplicationCommand, iterable);
/**
* The manager for permissions of arbitrary commands on arbitrary guilds

View File

@@ -1,14 +1,18 @@
'use strict';
const BaseManager = require('./BaseManager');
const { Error, TypeError } = require('../errors');
const Collection = require('../util/Collection');
const { ApplicationCommandPermissionTypes, APIErrors } = require('../util/Constants');
/**
* Manages API methods for permissions of Application Commands.
* @extends {BaseManager}
*/
class ApplicationCommandPermissionsManager {
class ApplicationCommandPermissionsManager extends BaseManager {
constructor(manager) {
super(manager.client);
/**
* The manager or command that this manager belongs to
* @type {ApplicationCommandManager|ApplicationCommand}
@@ -32,14 +36,6 @@ class ApplicationCommandPermissionsManager {
* @type {?Snowflake}
*/
this.commandID = manager.id ?? null;
/**
* The client that instantiated this Manager
* @name ApplicationCommandPermissionsManager#client
* @type {Client}
* @readonly
*/
Object.defineProperty(this, 'client', { value: manager.client });
}
/**

View File

@@ -1,17 +1,17 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const GuildEmoji = require('../structures/GuildEmoji');
const ReactionEmoji = require('../structures/ReactionEmoji');
const { parseEmoji } = require('../util/Util');
/**
* Holds methods to resolve GuildEmojis and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class BaseGuildEmojiManager extends BaseManager {
class BaseGuildEmojiManager extends CachedManager {
constructor(client, iterable) {
super(client, iterable, GuildEmoji);
super(client, GuildEmoji, iterable);
}
/**

View File

@@ -1,24 +1,11 @@
'use strict';
const Collection = require('../util/Collection');
let Structures;
/**
* Manages the API methods of a data model and holds its cache.
* Manages the API methods of a data model.
* @abstract
*/
class BaseManager {
constructor(client, iterable, holds, cacheType = Collection, ...cacheOptions) {
if (!Structures) Structures = require('../util/Structures');
/**
* The data structure belonging to this manager
* @name BaseManager#holds
* @type {Function}
* @private
* @readonly
*/
Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) ?? holds });
constructor(client) {
/**
* The client that instantiated this Manager
* @name BaseManager#client
@@ -26,55 +13,6 @@ class BaseManager {
* @readonly
*/
Object.defineProperty(this, 'client', { value: client });
/**
* The type of Collection of the Manager
* @type {Collection}
*/
this.cacheType = cacheType;
/**
* Holds the cache for the data model
* @type {Collection}
*/
this.cache = new cacheType(...cacheOptions);
if (iterable) for (const i of iterable) this.add(i);
}
add(data, cache = true, { id, extras = [] } = {}) {
const existing = this.cache.get(id ?? data.id);
if (cache) existing?._patch(data);
if (existing) return existing;
const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
if (cache) this.cache.set(id ?? entry.id, entry);
return entry;
}
/**
* Resolves a data entry to a data Object.
* @param {string|Object} idOrInstance The id or instance of something in this Manager
* @returns {?Object} An instance from this Manager
*/
resolve(idOrInstance) {
if (idOrInstance instanceof this.holds) return idOrInstance;
if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) ?? null;
return null;
}
/**
* Resolves a data entry to an instance ID.
* @param {string|Object} idOrInstance The id or instance of something in this Manager
* @returns {?Snowflake}
*/
resolveID(idOrInstance) {
if (idOrInstance instanceof this.holds) return idOrInstance.id;
if (typeof idOrInstance === 'string') return idOrInstance;
return null;
}
valueOf() {
return this.cache;
}
}

View File

@@ -0,0 +1,43 @@
'use strict';
const DataManager = require('./DataManager');
/**
* Manages the API methods of a data model with a mutable cache of instances.
* @extends {DataManager}
* @abstract
*/
class CachedManager extends DataManager {
constructor(client, holds, iterable) {
super(client, holds);
Object.defineProperty(this, '_cache', { value: this.client.options.makeCache(this.constructor, this.holds) });
if (iterable) {
for (const item of iterable) {
this.add(item);
}
}
}
/**
* The cache of items for this manager.
* @type {Collection}
* @abstract
*/
get cache() {
return this._cache;
}
add(data, cache = true, { id, extras = [] } = {}) {
const existing = this.cache.get(id ?? data.id);
if (cache) existing?._patch(data);
if (existing) return existing;
const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
if (cache) this.cache.set(id ?? entry.id, entry);
return entry;
}
}
module.exports = CachedManager;

View File

@@ -1,16 +1,16 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const Channel = require('../structures/Channel');
const { Events, ThreadChannelTypes } = require('../util/Constants');
/**
* A manager of channels belonging to a client
* @extends {BaseManager}
* @extends {CachedManager}
*/
class ChannelManager extends BaseManager {
class ChannelManager extends CachedManager {
constructor(client, iterable) {
super(client, iterable, Channel);
super(client, Channel, iterable);
}
/**

View File

@@ -0,0 +1,65 @@
'use strict';
const BaseManager = require('./BaseManager');
const { Error } = require('../errors');
let Structures;
/**
* Manages the API methods of a data model along with a collection of instances.
* @extends {BaseManager}
* @abstract
*/
class DataManager extends BaseManager {
constructor(client, holds) {
super(client);
if (!Structures) Structures = require('../util/Structures');
/**
* The data structure belonging to this manager.
* @name DataManager#holds
* @type {Function}
* @private
* @readonly
*/
Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) ?? holds });
}
/**
* The cache of items for this manager.
* @type {Collection}
* @abstract
*/
get cache() {
throw new Error('NOT_IMPLEMENTED', 'get cache', this.constructor.name);
}
/**
* Resolves a data entry to a data Object.
* @param {string|Object} idOrInstance The id or instance of something in this Manager
* @returns {?Object} An instance from this Manager
*/
resolve(idOrInstance) {
if (idOrInstance instanceof this.holds) return idOrInstance;
if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) ?? null;
return null;
}
/**
* Resolves a data entry to an instance ID.
* @param {string|Object} idOrInstance The id or instance of something in this Manager
* @returns {?Snowflake}
*/
resolveID(idOrInstance) {
if (idOrInstance instanceof this.holds) return idOrInstance.id;
if (typeof idOrInstance === 'string') return idOrInstance;
return null;
}
valueOf() {
return this.cache;
}
}
module.exports = DataManager;

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError, Error } = require('../errors');
const GuildBan = require('../structures/GuildBan');
const GuildMember = require('../structures/GuildMember');
@@ -8,11 +8,11 @@ const Collection = require('../util/Collection');
/**
* Manages API methods for GuildBans and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class GuildBanManager extends BaseManager {
class GuildBanManager extends CachedManager {
constructor(guild, iterable) {
super(guild.client, iterable, GuildBan);
super(guild.client, GuildBan, iterable);
/**
* The guild this Manager belongs to

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const GuildChannel = require('../structures/GuildChannel');
const PermissionOverwrites = require('../structures/PermissionOverwrites');
const ThreadChannel = require('../structures/ThreadChannel');
@@ -9,11 +9,11 @@ const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants');
/**
* Manages API methods for GuildChannels and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class GuildChannelManager extends BaseManager {
class GuildChannelManager extends CachedManager {
constructor(guild, iterable) {
super(guild.client, iterable, GuildChannel);
super(guild.client, GuildChannel, iterable);
/**
* The guild this Manager belongs to

View File

@@ -1,13 +1,18 @@
'use strict';
const DataManager = require('./DataManager');
const { TypeError } = require('../errors');
const Role = require('../structures/Role');
const Collection = require('../util/Collection');
/**
* Manages API methods for roles belonging to emojis and stores their cache.
* @extends {DataManager}
*/
class GuildEmojiRoleManager {
class GuildEmojiRoleManager extends DataManager {
constructor(emoji) {
super(emoji.client, Role);
/**
* The emoji belonging to this manager
* @type {GuildEmoji}
@@ -18,12 +23,6 @@ class GuildEmojiRoleManager {
* @type {Guild}
*/
this.guild = emoji.guild;
/**
* The client belonging to this manager
* @type {Client}
* @readonly
*/
Object.defineProperty(this, 'client', { value: emoji.client });
}
/**

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const Guild = require('../structures/Guild');
const GuildChannel = require('../structures/GuildChannel');
const GuildEmoji = require('../structures/GuildEmoji');
@@ -23,11 +23,11 @@ const { resolveColor } = require('../util/Util');
/**
* Manages API methods for Guilds and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class GuildManager extends BaseManager {
class GuildManager extends CachedManager {
constructor(client, iterable) {
super(client, iterable, Guild);
super(client, Guild, iterable);
}
/**

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { Error, TypeError, RangeError } = require('../errors');
const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
const GuildMember = require('../structures/GuildMember');
@@ -11,11 +11,12 @@ const SnowflakeUtil = require('../util/SnowflakeUtil');
/**
* Manages API methods for GuildMembers and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class GuildMemberManager extends BaseManager {
class GuildMemberManager extends CachedManager {
constructor(guild, iterable) {
super(guild.client, iterable, GuildMember);
super(guild.client, GuildMember, iterable);
/**
* The guild this manager belongs to
* @type {Guild}

View File

@@ -1,24 +1,29 @@
'use strict';
const DataManager = require('./DataManager');
const { TypeError } = require('../errors');
const Role = require('../structures/Role');
const Collection = require('../util/Collection');
/**
* Manages API methods for roles of a GuildMember and stores their cache.
* @extends {DataManager}
*/
class GuildMemberRoleManager {
class GuildMemberRoleManager extends DataManager {
constructor(member) {
super(member.client, Role);
/**
* The GuildMember this manager belongs to
* @type {GuildMember}
*/
this.member = member;
/**
* The Guild this manager belongs to
* @type {Guild}
*/
this.guild = member.guild;
Object.defineProperty(this, 'client', { value: member.client });
}
/**
@@ -170,10 +175,6 @@ class GuildMemberRoleManager {
clone.member._roles = [...this.cache.keyArray()];
return clone;
}
valueOf() {
return this.cache;
}
}
module.exports = GuildMemberRoleManager;

View File

@@ -1,19 +1,19 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const Message = require('../structures/Message');
const MessagePayload = require('../structures/MessagePayload');
const Collection = require('../util/Collection');
const LimitedCollection = require('../util/LimitedCollection');
/**
* Manages API methods for Messages and holds their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class MessageManager extends BaseManager {
class MessageManager extends CachedManager {
constructor(channel, iterable) {
super(channel.client, iterable, Message, LimitedCollection, channel.client.options.messageCacheMaxSize);
super(channel.client, Message, iterable);
/**
* The channel that the messages belong to
* @type {TextBasedChannel}

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const PermissionOverwrites = require('../structures/PermissionOverwrites');
const Role = require('../structures/Role');
@@ -9,11 +9,11 @@ const { OverwriteTypes } = require('../util/Constants');
/**
* Manages API methods for guild channel permission overwrites and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class PermissionOverwriteManager extends BaseManager {
class PermissionOverwriteManager extends CachedManager {
constructor(channel, iterable) {
super(channel.client, iterable, PermissionOverwrites);
super(channel.client, PermissionOverwrites, iterable);
/**
* The channel of the permission overwrite this manager belongs to

View File

@@ -1,15 +1,15 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { Presence } = require('../structures/Presence');
/**
* Manages API methods for Presences and holds their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class PresenceManager extends BaseManager {
class PresenceManager extends CachedManager {
constructor(client, iterable) {
super(client, iterable, Presence);
super(client, Presence, iterable);
}
/**

View File

@@ -1,15 +1,15 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const MessageReaction = require('../structures/MessageReaction');
/**
* Manages API methods for reactions and holds their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class ReactionManager extends BaseManager {
class ReactionManager extends CachedManager {
constructor(message, iterable) {
super(message.client, iterable, MessageReaction);
super(message.client, MessageReaction, iterable);
/**
* The message that this manager belongs to

View File

@@ -1,16 +1,18 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { Error } = require('../errors');
const User = require('../structures/User');
const Collection = require('../util/Collection');
/**
* Manages API methods for users who reacted to a reaction and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class ReactionUserManager extends BaseManager {
constructor(client, iterable, reaction) {
super(client, iterable, { name: 'User' });
class ReactionUserManager extends CachedManager {
constructor(reaction, iterable) {
super(reaction.client, User, iterable);
/**
* The reaction that this manager belongs to
* @type {MessageReaction}

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const Role = require('../structures/Role');
const Collection = require('../util/Collection');
@@ -9,11 +9,12 @@ const { resolveColor, setPosition } = require('../util/Util');
/**
* Manages API methods for roles and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class RoleManager extends BaseManager {
class RoleManager extends CachedManager {
constructor(guild, iterable) {
super(guild.client, iterable, Role);
super(guild.client, Role, iterable);
/**
* The guild belonging to this manager
* @type {Guild}

View File

@@ -1,17 +1,17 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError, Error } = require('../errors');
const StageInstance = require('../structures/StageInstance');
const { PrivacyLevels } = require('../util/Constants');
/**
* Manages API methods for {@link StageInstance} objects and holds their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class StageInstanceManager extends BaseManager {
class StageInstanceManager extends CachedManager {
constructor(guild, iterable) {
super(guild.client, iterable, StageInstance);
super(guild.client, StageInstance, iterable);
/**
* The guild this manager belongs to

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const ThreadChannel = require('../structures/ThreadChannel');
const Collection = require('../util/Collection');
@@ -8,11 +8,11 @@ const { ChannelTypes } = require('../util/Constants');
/**
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class ThreadManager extends BaseManager {
class ThreadManager extends CachedManager {
constructor(channel, iterable) {
super(channel.client, iterable, ThreadChannel);
super(channel.client, ThreadChannel, iterable);
/**
* The channel this Manager belongs to

View File

@@ -1,17 +1,18 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const ThreadMember = require('../structures/ThreadMember');
const Collection = require('../util/Collection');
/**
* Manages API methods for ThreadMembers and stores their cache.
* @extends {BaseManager}
* Manages API methods for GuildMembers and stores their cache.
* @extends {CachedManager}
*/
class ThreadMemberManager extends BaseManager {
class ThreadMemberManager extends CachedManager {
constructor(thread, iterable) {
super(thread.client, iterable, ThreadMember);
super(thread.client, ThreadMember, iterable);
/**
* The thread this manager belongs to
* @type {ThreadChannel}

View File

@@ -1,6 +1,6 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const GuildMember = require('../structures/GuildMember');
const Message = require('../structures/Message');
const ThreadMember = require('../structures/ThreadMember');
@@ -8,11 +8,11 @@ const User = require('../structures/User');
/**
* Manages API methods for users and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class UserManager extends BaseManager {
class UserManager extends CachedManager {
constructor(client, iterable) {
super(client, iterable, User);
super(client, User, iterable);
}
/**

View File

@@ -1,14 +1,16 @@
'use strict';
const BaseManager = require('./BaseManager');
const CachedManager = require('./CachedManager');
const VoiceState = require('../structures/VoiceState');
/**
* Manages API methods for VoiceStates and stores their cache.
* @extends {BaseManager}
* @extends {CachedManager}
*/
class VoiceStateManager extends BaseManager {
class VoiceStateManager extends CachedManager {
constructor(guild, iterable) {
super(guild.client, iterable, { name: 'VoiceState' });
super(guild.client, VoiceState, iterable);
/**
* The guild this manager belongs to
* @type {Guild}