Browse Source

feat: revise cache logic

pull/5502/head
Wing-Kam Wong 2 years ago
parent
commit
672501d9ed
  1. 8
      packages/nocodb-nest/src/cache/CacheMgr.ts
  2. 11
      packages/nocodb-nest/src/cache/NocoCache.ts
  3. 36
      packages/nocodb-nest/src/cache/RedisCacheMgr.ts
  4. 38
      packages/nocodb-nest/src/cache/RedisMockCacheMgr.ts

8
packages/nocodb-nest/src/cache/CacheMgr.ts vendored

@ -4,7 +4,13 @@ export default abstract class CacheMgr {
public abstract del(key: string): Promise<any>;
public abstract getAll(pattern: string): Promise<any[]>;
public abstract delAll(scope: string, pattern: string): Promise<any[]>;
public abstract getList(scope: string, list: string[]): Promise<any[]>;
public abstract getList(
scope: string,
list: string[],
): Promise<{
list: any[];
isNoneList: boolean;
}>;
public abstract setList(
scope: string,
subListKeys: string[],

11
packages/nocodb-nest/src/cache/NocoCache.ts vendored

@ -56,8 +56,15 @@ export default class NocoCache {
public static async getList(
scope: string,
subKeys: string[],
): Promise<any[]> {
if (this.cacheDisabled) return Promise.resolve([]);
): Promise<{
list: any[];
isNoneList: boolean;
}> {
if (this.cacheDisabled)
return Promise.resolve({
list: [],
isNoneList: false,
});
return this.client.getList(scope, subKeys);
}

36
packages/nocodb-nest/src/cache/RedisCacheMgr.ts vendored

@ -114,7 +114,13 @@ export default class RedisCacheMgr extends CacheMgr {
);
}
async getList(scope: string, subKeys: string[]): Promise<any[]> {
async getList(
scope: string,
subKeys: string[],
): Promise<{
list: any[];
isNoneList: boolean;
}> {
// remove null from arrays
subKeys = subKeys.filter((k) => k);
// e.g. key = nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
@ -125,9 +131,21 @@ export default class RedisCacheMgr extends CacheMgr {
// e.g. arr = ["nc:<orgs>:<scope>:<model_id_1>", "nc:<orgs>:<scope>:<model_id_2>"]
const arr = (await this.get(key, CacheGetType.TYPE_ARRAY)) || [];
log(`RedisCacheMgr::getList: getting list with key ${key}`);
return Promise.all(
arr.map(async (k) => await this.get(k, CacheGetType.TYPE_OBJECT)),
);
const isNoneList = arr.length && arr[0] === 'NONE';
if (isNoneList) {
return Promise.resolve({
list: [],
isNoneList,
});
}
return {
list: await Promise.all(
arr.map(async (k) => await this.get(k, CacheGetType.TYPE_OBJECT)),
),
isNoneList,
};
}
async setList(
@ -144,8 +162,8 @@ export default class RedisCacheMgr extends CacheMgr {
? `${this.prefix}:${scope}:list`
: `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
if (!list.length) {
log(`RedisCacheMgr::setList: List is empty for ${listKey}. Skipping ...`);
return Promise.resolve(true);
// Set NONE here so that it won't hit the DB on each page load
return this.set(listKey, ['NONE']);
}
// fetch existing list
const listOfGetKeys =
@ -225,7 +243,11 @@ export default class RedisCacheMgr extends CacheMgr {
? `${this.prefix}:${scope}:list`
: `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
log(`RedisCacheMgr::appendToList: append key ${key} to ${listKey}`);
const list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
let list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
if (list.length && list[0] === 'NONE') {
list = [];
await this.del(listKey);
}
list.push(key);
return this.set(listKey, list);
}

38
packages/nocodb-nest/src/cache/RedisMockCacheMgr.ts vendored

@ -114,7 +114,13 @@ export default class RedisMockCacheMgr extends CacheMgr {
);
}
async getList(scope: string, subKeys: string[]): Promise<any[]> {
async getList(
scope: string,
subKeys: string[],
): Promise<{
list: any[];
isNoneList: boolean;
}> {
// remove null from arrays
subKeys = subKeys.filter((k) => k);
// e.g. key = nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
@ -125,9 +131,21 @@ export default class RedisMockCacheMgr extends CacheMgr {
// e.g. arr = ["nc:<orgs>:<scope>:<model_id_1>", "nc:<orgs>:<scope>:<model_id_2>"]
const arr = (await this.get(key, CacheGetType.TYPE_ARRAY)) || [];
log(`RedisMockCacheMgr::getList: getting list with key ${key}`);
return Promise.all(
arr.map(async (k) => await this.get(k, CacheGetType.TYPE_OBJECT)),
);
const isNoneList = arr.length && arr[0] === 'NONE';
if (isNoneList) {
return Promise.resolve({
list: [],
isNoneList,
});
}
return {
list: await Promise.all(
arr.map(async (k) => await this.get(k, CacheGetType.TYPE_OBJECT)),
),
isNoneList,
};
}
async setList(
@ -144,10 +162,8 @@ export default class RedisMockCacheMgr extends CacheMgr {
? `${this.prefix}:${scope}:list`
: `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
if (!list.length) {
log(
`RedisMockCacheMgr::setList: List is empty for ${listKey}. Skipping ...`,
);
return Promise.resolve(true);
// Set NONE here so that it won't hit the DB on each page load
return this.set(listKey, ['NONE']);
}
// fetch existing list
const listOfGetKeys =
@ -227,7 +243,11 @@ export default class RedisMockCacheMgr extends CacheMgr {
? `${this.prefix}:${scope}:list`
: `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
log(`RedisMockCacheMgr::appendToList: append key ${key} to ${listKey}`);
const list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
let list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
if (list.length && list[0] === 'NONE') {
list = [];
await this.del(listKey);
}
list.push(key);
return this.set(listKey, list);
}

Loading…
Cancel
Save