mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 11:37:58 +00:00
feat: IndexedDB based caching for labels, inboxes and teams [CW-50] (#6710)
* feat: allow caching of labels in the account scope * feat: send cache keys in account json response * feat: kickstart web worker * feat: setup basic architecture for workers * feat: install idb * feat: add datamanger * fix: typos * refactor: rename method * feat: make init db a manual step * refactor: separate accountIdFromRoute * feat: cache enabled API client * feat: enable caching for inboxes and labels * feat: enable cache for team * feat: manage exceptions for team * feat: add team to data manager * feat: add a generic listener * refactor: send only cache keys * refactor: separate validate method * feat: add listeners * feat: add event for revalidate * feat: add cache keys endpoint * refactor: fetch cache keys instead of full account data * fix: key pattern * feat: don't fetch account for cache_keys * fix: cache key base class * refactor: cache keys helper * feat: add helper * fix: cache-key update logic * feat: delete indexeddb on logout * feat: remove worker.js * refactor: move data-manager * refactor: name of file * feat: add test for DataManager * refactor: add fake idb to jest setup * test: cache keys helper * test: cache keys helper * test: cache_keys in accounts controller * refactor: remove cache_keys context * feat: add policy for cache-keys
This commit is contained in:
82
app/javascript/dashboard/api/CacheEnabledApiClient.js
Normal file
82
app/javascript/dashboard/api/CacheEnabledApiClient.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/* global axios */
|
||||
import { DataManager } from '../helper/CacheHelper/DataManager';
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class CacheEnabledApiClient extends ApiClient {
|
||||
constructor(resource, options = {}) {
|
||||
super(resource, options);
|
||||
this.dataManager = new DataManager(this.accountIdFromRoute);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
get cacheModelName() {
|
||||
throw new Error('cacheModelName is not defined');
|
||||
}
|
||||
|
||||
get(cache = false) {
|
||||
if (cache) {
|
||||
return this.getFromCache();
|
||||
}
|
||||
|
||||
return axios.get(this.url);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
extractDataFromResponse(response) {
|
||||
return response.data.payload;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
marshallData(dataToParse) {
|
||||
return { data: { payload: dataToParse } };
|
||||
}
|
||||
|
||||
async getFromCache() {
|
||||
await this.dataManager.initDb();
|
||||
|
||||
const { data } = await axios.get(
|
||||
`/api/v1/accounts/${this.accountIdFromRoute}/cache_keys`
|
||||
);
|
||||
const cacheKeyFromApi = data.cache_keys[this.cacheModelName];
|
||||
const isCacheValid = await this.validateCacheKey(cacheKeyFromApi);
|
||||
|
||||
let localData = [];
|
||||
if (isCacheValid) {
|
||||
localData = await this.dataManager.get({
|
||||
modelName: this.cacheModelName,
|
||||
});
|
||||
}
|
||||
|
||||
if (localData.length === 0) {
|
||||
return this.refetchAndCommit(cacheKeyFromApi);
|
||||
}
|
||||
|
||||
return this.marshallData(localData);
|
||||
}
|
||||
|
||||
async refetchAndCommit(newKey = null) {
|
||||
await this.dataManager.initDb();
|
||||
const response = await axios.get(this.url);
|
||||
this.dataManager.replace({
|
||||
modelName: this.cacheModelName,
|
||||
data: this.extractDataFromResponse(response),
|
||||
});
|
||||
|
||||
await this.dataManager.setCacheKeys({
|
||||
[this.cacheModelName]: newKey,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async validateCacheKey(cacheKeyFromApi) {
|
||||
if (!this.dataManager.db) {
|
||||
await this.dataManager.initDb();
|
||||
}
|
||||
|
||||
const cachekey = await this.dataManager.getCacheKey(this.cacheModelName);
|
||||
return cacheKeyFromApi === cachekey;
|
||||
}
|
||||
}
|
||||
|
||||
export default CacheEnabledApiClient;
|
||||
Reference in New Issue
Block a user