- Consolidated duplicate UndoManagers to single instance - Fixed connection promise to only resolve on 'connected' status - Fixed WebSocketProvider import (WebsocketProvider) - Added proper doc.destroy() cleanup - Renamed isPresenceInitialized property to avoid conflict Co-Authored-By: Paperclip <noreply@paperclip.ing>
82 lines
2.2 KiB
TypeScript
82 lines
2.2 KiB
TypeScript
import type { ErrorType } from '../../errors/utils.js'
|
|
|
|
/** @internal */
|
|
export const promiseCache = /*#__PURE__*/ new Map()
|
|
/** @internal */
|
|
export const responseCache = /*#__PURE__*/ new Map()
|
|
|
|
export type GetCacheErrorType = ErrorType
|
|
|
|
export function getCache<data>(cacheKey: string) {
|
|
const buildCache = <data>(cacheKey: string, cache: Map<string, data>) => ({
|
|
clear: () => cache.delete(cacheKey),
|
|
get: () => cache.get(cacheKey),
|
|
set: (data: data) => cache.set(cacheKey, data),
|
|
})
|
|
|
|
const promise = buildCache<Promise<data>>(cacheKey, promiseCache)
|
|
const response = buildCache<{ created: Date; data: data }>(
|
|
cacheKey,
|
|
responseCache,
|
|
)
|
|
|
|
return {
|
|
clear: () => {
|
|
promise.clear()
|
|
response.clear()
|
|
},
|
|
promise,
|
|
response,
|
|
}
|
|
}
|
|
|
|
type WithCacheParameters = {
|
|
/** The key to cache the data against. */
|
|
cacheKey: string
|
|
/** The time that cached data will remain in memory. Default: Infinity (no expiry) */
|
|
cacheTime?: number | undefined
|
|
}
|
|
|
|
/**
|
|
* @description Returns the result of a given promise, and caches the result for
|
|
* subsequent invocations against a provided cache key.
|
|
*/
|
|
export async function withCache<data>(
|
|
fn: () => Promise<data>,
|
|
{ cacheKey, cacheTime = Number.POSITIVE_INFINITY }: WithCacheParameters,
|
|
) {
|
|
const cache = getCache<data>(cacheKey)
|
|
|
|
// If a response exists in the cache, and it's not expired, return it
|
|
// and do not invoke the promise.
|
|
// If the max age is 0, the cache is disabled.
|
|
const response = cache.response.get()
|
|
if (response && cacheTime > 0) {
|
|
const age = Date.now() - response.created.getTime()
|
|
if (age < cacheTime) return response.data
|
|
}
|
|
|
|
let promise = cache.promise.get()
|
|
if (!promise) {
|
|
promise = fn()
|
|
|
|
// Store the promise in the cache so that subsequent invocations
|
|
// will wait for the same promise to resolve (deduping).
|
|
cache.promise.set(promise)
|
|
}
|
|
|
|
try {
|
|
const data = await promise
|
|
|
|
// Store the response in the cache so that subsequent invocations
|
|
// will return the same response.
|
|
cache.response.set({ created: new Date(), data })
|
|
|
|
return data
|
|
} finally {
|
|
// Clear the promise cache so that subsequent invocations will
|
|
// invoke the promise again.
|
|
cache.promise.clear()
|
|
}
|
|
}
|