async get(key, fetchData) {
        const internalKey = this._buildKey(key);
        try {
            const result = await this._get(internalKey);
            debug(`get ${internalKey}: Cache ${result ? 'HIT' : 'MISS'}`);
            if (!fetchData) {
                return result;
            }
            if (result) {
                const shouldRefresh = await this.shouldRefresh(internalKey);
                const isRefreshing = this.currentlyExecutingBackgroundRefreshes.has(internalKey);
                if (isRefreshing) {
                    debug(`Background refresh already happening for ${internalKey}`);
                }
                if (!isRefreshing && shouldRefresh) {
                    debug(`Doing background refresh for ${internalKey}`);
                    this.currentlyExecutingBackgroundRefreshes.add(internalKey);
                    fetchData().then(async (data) => {
                        await this.set(key, data); // We don't use `internalKey` here because `set` handles it
                        this.currentlyExecutingBackgroundRefreshes.delete(internalKey);
                    }).catch((error) => {
                        this.currentlyExecutingBackgroundRefreshes.delete(internalKey);
                        logging.error({
                            message: 'There was an error refreshing cache data in the background',
                            error: error
                        });
                    });
                }
                return result;
            } else {
                const data = await fetchData();
                await this.set(key, data); // We don't use `internalKey` here because `set` handles it
                return data;
            }
        } catch (err) {
            logging.error(err);
        }
    }
@param {string} key
@param {() => Promise<any>} [fetchData] An optional function to fetch the data, which will be used in the case of a cache MISS or a background refresh