@@ -30,6 +30,10 @@ export interface RestOptions {
30
30
* @default true
31
31
*/
32
32
retryAfterRatelimit ?: boolean ;
33
+ /**
34
+ * Overwrites the default for `{@link RequestOptions.cacheTime}`
35
+ */
36
+ cacheTime ?: number ;
33
37
}
34
38
35
39
export interface Rest {
@@ -119,13 +123,31 @@ export interface RequestOptions<D, Q> {
119
123
* Wether or not the library should internally set a timeout for the I/O call
120
124
*/
121
125
implicitAbortBehavior ?: boolean ;
126
+ /**
127
+ * Wether or not the library should cache the result of this call (ignored for non-GET requests)
128
+ */
129
+ cache ?: boolean ;
130
+ /**
131
+ * If `{@link RequestOptions.cache}` is set to `true`, how long should the cache live for?
132
+ * @default 10000
133
+ */
134
+ cacheTime ?: number ;
122
135
}
123
136
124
137
/**
125
138
* Base REST class used for making requests
126
139
* @noInheritDoc
127
140
*/
128
141
export class Rest extends EventEmitter {
142
+ /**
143
+ * @internal
144
+ */
145
+ private readonly cache = new Map < string , any > ( ) ;
146
+ /**
147
+ * @internal
148
+ */
149
+ private readonly cacheTimeouts = new Map < string , NodeJS . Timeout > ( ) ;
150
+
129
151
/**
130
152
* Current active rate limiting Buckets
131
153
*/
@@ -135,6 +157,7 @@ export class Rest extends EventEmitter {
135
157
public readonly abortAfter : number ;
136
158
public readonly mutex : Mutex ;
137
159
public readonly retryAfterRatelimit : boolean ;
160
+ public readonly cacheTime : number ;
138
161
139
162
/**
140
163
* @param auth Your bot's Discord token
@@ -149,13 +172,15 @@ export class Rest extends EventEmitter {
149
172
retries = 3 ,
150
173
abortAfter = 15e3 ,
151
174
mutex = new MemoryMutex ( ) ,
152
- retryAfterRatelimit = true
175
+ retryAfterRatelimit = true ,
176
+ cacheTime = 10000 ,
153
177
} = options ;
154
178
155
179
this . retries = retries ;
156
180
this . abortAfter = abortAfter ;
157
181
this . mutex = mutex ;
158
182
this . retryAfterRatelimit = retryAfterRatelimit ;
183
+ this . cacheTime = cacheTime ;
159
184
}
160
185
161
186
/**
@@ -183,11 +208,36 @@ export class Rest extends EventEmitter {
183
208
options . headers . set ( 'X-Audit-Log-Reason' , encodeURIComponent ( options . reason ) ) ;
184
209
}
185
210
211
+ options . cacheTime ??= this . cacheTime ;
212
+
186
213
let isRetryAfterRatelimit = false ;
187
214
215
+ const isGet = options . method . toLowerCase ( ) === 'get' ;
216
+ const shouldCache = options . cache && isGet ;
217
+
188
218
for ( let retries = 0 ; retries <= this . retries ; retries ++ ) {
189
219
try {
190
- return await bucket . make < T , D , Q > ( { ...options , isRetryAfterRatelimit } as DiscordFetchOptions < D , Q > ) ;
220
+ if ( shouldCache && this . cache . has ( options . path ) ) {
221
+ return this . cache . get ( options . path ) ;
222
+ }
223
+
224
+ const data = await bucket . make < T , D , Q > ( { ...options , isRetryAfterRatelimit } as DiscordFetchOptions < D , Q > ) ;
225
+
226
+ if ( shouldCache || ( isGet && this . cache . has ( options . path ) ) ) {
227
+ this . cache . set ( options . path , data ) ;
228
+
229
+ if ( this . cacheTimeouts . has ( options . path ) ) {
230
+ const timeout = this . cacheTimeouts . get ( options . path ) ! ;
231
+ timeout . refresh ( ) ;
232
+ } else {
233
+ this . cacheTimeouts . set ( options . path , setTimeout ( ( ) => {
234
+ this . cache . delete ( options . path ) ;
235
+ this . cacheTimeouts . delete ( options . path ) ;
236
+ } , options . cacheTime ) ) ;
237
+ }
238
+ }
239
+
240
+ return data ;
191
241
} catch ( e : any ) {
192
242
const isRatelimit = e instanceof CordisRestError && e . code === 'rateLimited' ;
193
243
isRetryAfterRatelimit = isRatelimit ;
@@ -215,7 +265,8 @@ export class Rest extends EventEmitter {
215
265
* @param options Other options for the request
216
266
*/
217
267
/* istanbul ignore next */
218
- public get < T , Q = StringRecord > ( path : string , options : { query ?: Q } = { } ) : Promise < T > {
268
+
269
+ public get < T , Q = StringRecord > ( path : string , options : { query ?: Q ; cache ?: boolean ; cacheTime ?: number } = { } ) : Promise < T > {
219
270
return this . make < T , never , Q > ( { path, method : 'get' , ...options } ) ;
220
271
}
221
272
0 commit comments