diff --git a/src/components/r4-app.js b/src/components/r4-app.js index 35f0590e..576a9f55 100644 --- a/src/components/r4-app.js +++ b/src/components/r4-app.js @@ -5,12 +5,14 @@ import {sdk, HCAPTCHA_SITE_KEY} from '../libs/sdk.js' import {UI_STATES} from '../libs/appearance.js' import page from 'page/page.mjs' import DatabaseListeners from '../libs/db-listeners' +import Cache from '../libs/cache.js' import '../pages/' import ROUTES_CMS from '../data/routes-cms.json' import ROUTES_SINGLE from '../data/routes-single.json' import {THEMES, prefersDark} from '../libs/appearance.js' import {createImage} from './r4-avatar.js' + export default class R4App extends LitElement { playerRef = createRef() @@ -61,6 +63,7 @@ export default class R4App extends LitElement { userChannels: this.userChannels, followers: this.followers, following: this.following, + cache: this.cache, selectedChannel: this.selectedChannel, } } @@ -109,6 +112,7 @@ export default class R4App extends LitElement { this.version = pkg.version // Set default theme. this.theme = THEMES[0] + this.cache = new Cache() } async connectedCallback() { diff --git a/src/libs/browse.js b/src/libs/browse.js index 27f5951e..2804cf14 100644 --- a/src/libs/browse.js +++ b/src/libs/browse.js @@ -111,6 +111,7 @@ export async function browse(props) { // And pagination. const {from, to, limit: l} = getBrowseParams({page, limit}) query = query.range(from, to).limit(l) + return query } diff --git a/src/libs/cache.js b/src/libs/cache.js new file mode 100644 index 00000000..95dc56fc --- /dev/null +++ b/src/libs/cache.js @@ -0,0 +1,33 @@ +export default class Cache { + constructor() { + this.data = new Map() + } + + async get(key, fetcher, ttl = 60000) { + const now = Date.now() + if (!this.data.has(key)) { + // If the key is not in the cache, fetch it and store the Promise. + return this.refresh(key, fetcher, ttl) + } else { + const {timestamp, dataPromise} = this.data.get(key) + // If the key is in the cache, but it is expired, refresh it in the background. + if (now - timestamp > ttl) { + this.refresh(key, fetcher, ttl) + } + // If the key is in the cache and it is not expired, return the cached data. + console.log('using cache', key, ttl) + return dataPromise + } + } + + async refresh(key, fetcher, ttl) { + console.log('cache refresh', key, ttl) + const dataPromise = fetcher().catch((err) => { + // If an error occurs, remove the Promise from the cache. + this.data.delete(key) + throw err + }) + this.data.set(key, {dataPromise, timestamp: Date.now()}) + return dataPromise + } +} diff --git a/src/pages/base-channel.js b/src/pages/base-channel.js index b9fc1b5c..2835c5b0 100644 --- a/src/pages/base-channel.js +++ b/src/pages/base-channel.js @@ -84,7 +84,7 @@ export default class BaseChannel extends R4Page { // No need to set again if channel the same channel is loaded. if (this.channel?.slug === slug) return - const {data, error} = await sdk.channels.readChannel(slug) + const {data, error} = await this.store.cache.get(`channel/${slug}`, () => sdk.channels.readChannel(slug)) this.canEdit = await sdk.channels.canEditChannel(slug) if (error) { diff --git a/src/pages/r4-page-channel-tracks.js b/src/pages/r4-page-channel-tracks.js index 4bd7719f..4c0311c3 100644 --- a/src/pages/r4-page-channel-tracks.js +++ b/src/pages/r4-page-channel-tracks.js @@ -23,7 +23,7 @@ export default class R4PageChannelTracks extends BaseChannel { href: {type: String}, origin: {type: String}, } - + constructor() { super() this.query = { @@ -32,6 +32,19 @@ export default class R4PageChannelTracks extends BaseChannel { limit: 15, } } + + async onQuery(event) { + if (!this.channel) return + const q = event.detail + urlUtils.updateSearchParams(q, ['table', 'select']) + const filtersWithDefaults = [...(q.filters || []), ...this.defaultFilters] + q.filters = filtersWithDefaults + const key = JSON.stringify(q) + const res = await this.store.cache.get(`tracks_${key}`, () => query(q)) + this.count = res.count + this.tracks = res.data + this.lastQuery = q + } handleData(event) { const {data: tracks, count} = event.detail diff --git a/src/pages/r4-page-channel.js b/src/pages/r4-page-channel.js index af2cd98b..184d22ce 100644 --- a/src/pages/r4-page-channel.js +++ b/src/pages/r4-page-channel.js @@ -31,6 +31,11 @@ export default class R4PageChannel extends BaseChannel { this.tracks = event.detail.data } + async onQuery({detail}) { + const res = await this.store.cache.get(`${this.params.slug}/latesttracks`, () => query(detail)) + this.tracks = res.data + } + renderAside() { return html`