Browse Source

Merge branch 'develop' into fix/backblaze

pull/4189/head
Wing-Kam Wong 2 years ago
parent
commit
451b6b2a19
  1. 8
      .github/workflows/release-docker.yml
  2. 4
      .github/workflows/release-draft.yml
  3. 2
      .github/workflows/release-executables.yml
  4. 6
      .github/workflows/release-nightly-dev.yml
  5. 9
      .github/workflows/release-nocodb.yml
  6. 4
      .github/workflows/release-pr.yml
  7. 4
      packages/nc-cli/package-lock.json
  8. 9
      packages/nc-cli/package.json
  9. 4
      packages/nc-cli/src/lib/mgr/NewMgr.ts
  10. 1
      packages/nc-gui/components.d.ts
  11. 102
      packages/nc-gui/components/api-client/Headers.vue
  12. 3
      packages/nc-gui/package-lock.json
  13. 11307
      packages/nocodb-sdk/package-lock.json
  14. 9
      packages/nocodb-sdk/package.json
  15. 3
      packages/nocodb/package-lock.json
  16. 20
      packages/nocodb/src/lib/cache/NocoCache.ts
  17. 40
      packages/nocodb/src/lib/cache/RedisCacheMgr.ts
  18. 40
      packages/nocodb/src/lib/cache/RedisMockCacheMgr.ts

8
.github/workflows/release-docker.yml

@ -60,10 +60,10 @@ jobs:
DOCKER_REPOSITORY=${DOCKER_REPOSITORY}-timely DOCKER_REPOSITORY=${DOCKER_REPOSITORY}-timely
fi fi
fi fi
echo "::set-output name=DOCKER_REPOSITORY::${DOCKER_REPOSITORY}" echo "DOCKER_REPOSITORY=${DOCKER_REPOSITORY}" >> $GITHUB_OUTPUT
echo "::set-output name=DOCKER_BUILD_TAG::${DOCKER_BUILD_TAG}" echo "DOCKER_BUILD_TAG=${DOCKER_BUILD_TAG}" >> $GITHUB_OUTPUT
echo ${DOCKER_REPOSITORY} echo DOCKER_REPOSITORY: ${DOCKER_REPOSITORY}
echo ${DOCKER_BUILD_TAG} echo DOCKER_BUILD_TAG: ${DOCKER_BUILD_TAG}
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3

4
.github/workflows/release-draft.yml

@ -53,7 +53,7 @@ jobs:
if [[ ${{ github.event.inputs.tagHeadSHA || inputs.tagHeadSHA }} == "Y" ]]; then if [[ ${{ github.event.inputs.tagHeadSHA || inputs.tagHeadSHA }} == "Y" ]]; then
TARGET_SHA=$(git rev-list -n 1 HEAD | tail -1) TARGET_SHA=$(git rev-list -n 1 HEAD | tail -1)
fi fi
echo "::set-output name=TARGET_SHA::${TARGET_SHA}" echo "TARGET_SHA=${TARGET_SHA}" >> $GITHUB_OUTPUT
echo "Setting TARGET_SHA: ${TARGET_SHA}" echo "Setting TARGET_SHA: ${TARGET_SHA}"
- name: Create tag - name: Create tag
uses: actions/github-script@v3 uses: actions/github-script@v3
@ -66,7 +66,7 @@ jobs:
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
ref: "refs/tags/${{ github.event.inputs.tag || inputs.tag }}", ref: "refs/tags/${{ github.event.inputs.tag || inputs.tag }}",
sha: "${{steps.get-sha.outputs.TARGET_SHA}}" sha: "${{ steps.get-sha.outputs.TARGET_SHA }}"
}) })
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:

2
.github/workflows/release-executables.yml

@ -194,7 +194,7 @@ jobs:
cp ./mac-dist/Noco-macos-x64 ./mac-dist/nocodb cp ./mac-dist/Noco-macos-x64 ./mac-dist/nocodb
tar -czf ./mac-dist/nocodb.tar.gz ./mac-dist/nocodb tar -czf ./mac-dist/nocodb.tar.gz ./mac-dist/nocodb
rm ./mac-dist/nocodb rm ./mac-dist/nocodb
echo "::set-output name=CHECKSUM::$(shasum -a 256 ./mac-dist/nocodb.tar.gz | awk '{print $1}')" echo "CHECKSUM=$(shasum -a 256 ./mac-dist/nocodb.tar.gz | awk '{print $1}')" >> $GITHUB_OUTPUT
id: compress id: compress

6
.github/workflows/release-nightly-dev.yml

@ -26,9 +26,9 @@ jobs:
if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then
IS_DAILY='N' IS_DAILY='N'
fi fi
echo "::set-output name=NIGHTLY_BUILD_TAG::${TAG_NAME}" echo "NIGHTLY_BUILD_TAG=${TAG_NAME}" >> $GITHUB_OUTPUT
echo "::set-output name=IS_DAILY::${IS_DAILY}" echo "IS_DAILY=${IS_DAILY}" >> $GITHUB_OUTPUT
echo "::set-output name=CURRENT_VERSION::${CURRENT_VERSION}" echo "CURRENT_VERSION=${CURRENT_VERSION}" >> $GITHUB_OUTPUT
- name: verify-tag - name: verify-tag
run: | run: |
echo ${{ steps.tag-step.outputs.NIGHTLY_BUILD_TAG }} echo ${{ steps.tag-step.outputs.NIGHTLY_BUILD_TAG }}

9
.github/workflows/release-nocodb.yml

@ -45,13 +45,12 @@ jobs:
TARGET_TAG=$(echo ${PREV_TAG} | awk -F. -v OFS=. '{$NF += 1 ; print}') TARGET_TAG=$(echo ${PREV_TAG} | awk -F. -v OFS=. '{$NF += 1 ; print}')
fi fi
echo target version: ${TARGET_TAG} echo "TARGET_TAG=${TARGET_TAG}" >> $GITHUB_OUTPUT
echo previous version: ${PREV_TAG} echo "PREV_TAG=${PREV_TAG}" >> $GITHUB_OUTPUT
echo "::set-output name=target_tag::${TARGET_TAG}"
echo "::set-output name=prev_tag::${PREV_TAG}"
- name: Verify - name: Verify
run : | run : |
echo ${{ steps.process-input.outputs.target_tag }} echo TARGET_TAG: ${{ steps.process-input.outputs.target_tag }}
echo PREV_TAG: ${{ steps.process-input.outputs.prev_tag }}
# Merge develop to master # Merge develop to master
pr-to-master: pr-to-master:

4
.github/workflows/release-pr.yml

@ -35,8 +35,8 @@ jobs:
CURRENT_VERSION=$(basename $(curl -fs -o/dev/null -w %{redirect_url} https://github.com/nocodb/nocodb/releases/latest)) CURRENT_VERSION=$(basename $(curl -fs -o/dev/null -w %{redirect_url} https://github.com/nocodb/nocodb/releases/latest))
# Construct tag name # Construct tag name
TAG_NAME=pr-${PR_NUMBER}-${CURRENT_DATE}-${CURRENT_TIME} TAG_NAME=pr-${PR_NUMBER}-${CURRENT_DATE}-${CURRENT_TIME}
echo "::set-output name=TARGET_TAG::${TAG_NAME}" echo "TARGET_TAG=${TAG_NAME}" >> $GITHUB_OUTPUT
echo "::set-output name=CURRENT_VERSION::${CURRENT_VERSION}" echo "CURRENT_VERSION=${CURRENT_VERSION}" >> $GITHUB_OUTPUT
- name: verify-tag - name: verify-tag
run: | run: |
echo ${{ steps.tag-step.outputs.TARGET_TAG }} echo ${{ steps.tag-step.outputs.TARGET_TAG }}

4
packages/nc-cli/package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "create-nocodb-app", "name": "create-nocodb-app",
"version": "0.1.26", "version": "0.1.28",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "create-nocodb-app", "name": "create-nocodb-app",
"version": "0.1.26", "version": "0.1.28",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",

9
packages/nc-cli/package.json

@ -1,6 +1,6 @@
{ {
"name": "create-nocodb-app", "name": "create-nocodb-app",
"version": "0.1.27", "version": "0.1.28",
"description": "nc-cli", "description": "nc-cli",
"main": "dist/bundle.js", "main": "dist/bundle.js",
"module": "dist/bundle.js", "module": "dist/bundle.js",
@ -14,11 +14,8 @@
}, },
"scripts": { "scripts": {
"describe": "npm-scripts-info", "describe": "npm-scripts-info",
"build": "run-s clean && run-p build:*", "build": "webpack --config webpack.config.js",
"build:main": "tsc -p tsconfig.json", "build:publish": "export NODE_OPTIONS=--openssl-legacy-provider && rm -rf dist && npm run build && npm publish .",
"build:module": "tsc -p tsconfig.module.json",
"build:obfuscate": "webpack --config webpack.config.js",
"build:obfuscate:publish": "export NODE_OPTIONS=--openssl-legacy-provider && rm -rf dist && npm run build:obfuscate && npm publish .",
"fix": "run-s fix:*", "fix": "run-s fix:*",
"fix:prettier": "prettier \"src/**/*.ts\" --write", "fix:prettier": "prettier \"src/**/*.ts\" --write",
"fix:tslint": "tslint --fix --project .", "fix:tslint": "tslint --fix --project .",

4
packages/nc-cli/src/lib/mgr/NewMgr.ts

@ -251,7 +251,7 @@ class NewMgr {
} else if (answers.projectType) { } else if (answers.projectType) {
let env = ''; let env = '';
if (answers.type !== 'sqlite3') { if (answers.type !== 'sqlite3') {
env = `--env NC_DB="${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&t=${args._[1]}"` env = `--env NC_DB="${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}"`
} }
const linuxHost = os.type() === 'Linux' ? '--net=host' : ''; const linuxHost = os.type() === 'Linux' ? '--net=host' : '';
if (os.type() === 'Windows_NT') { if (os.type() === 'Windows_NT') {
@ -641,7 +641,7 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
`) `)
} else if (answers.projectType === 'docker') { } else if (answers.projectType === 'docker') {
const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&t=${args._[1]}`; const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`;
// console.log(` // console.log(`
// You can create docker container using following command // You can create docker container using following command
// //

1
packages/nc-gui/components.d.ts vendored

@ -8,6 +8,7 @@ export {}
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
export interface GlobalComponents { export interface GlobalComponents {
AAlert: typeof import('ant-design-vue/es')['Alert'] AAlert: typeof import('ant-design-vue/es')['Alert']
AAutoComplete: typeof import('ant-design-vue/es')['AutoComplete']
ABadgeRibbon: typeof import('ant-design-vue/es')['BadgeRibbon'] ABadgeRibbon: typeof import('ant-design-vue/es')['BadgeRibbon']
AButton: typeof import('ant-design-vue/es')['Button'] AButton: typeof import('ant-design-vue/es')['Button']
ACard: typeof import('ant-design-vue/es')['Card'] ACard: typeof import('ant-design-vue/es')['Card']

102
packages/nc-gui/components/api-client/Headers.vue

@ -7,53 +7,61 @@ const props = defineProps<{
const emits = defineEmits(['update:modelValue']) const emits = defineEmits(['update:modelValue'])
interface Option {
value: string
}
const vModel = useVModel(props, 'modelValue', emits) const vModel = useVModel(props, 'modelValue', emits)
const headerList = [ const headerList = ref<Option[]>([
'A-IM', { value: 'A-IM' },
'Accept', { value: 'Accept' },
'Accept-Charset', { value: 'Accept-Charset' },
'Accept-Encoding', { value: 'Accept-Encoding' },
'Accept-Language', { value: 'Accept-Language' },
'Accept-Datetime', { value: 'Accept-Datetime' },
'Access-Control-Request-Method', { value: 'Access-Control-Request-Method' },
'Access-Control-Request-Headers', { value: 'Access-Control-Request-Headers' },
'Authorization', { value: 'Authorization' },
'Cache-Control', { value: 'Cache-Control' },
'Connection', { value: 'Connection' },
'Content-Length', { value: 'Content-Length' },
'Content-Type', { value: 'Content-Type' },
'Cookie', { value: 'Cookie' },
'Date', { value: 'Date' },
'Expect', { value: 'Expect' },
'Forwarded', { value: 'Forwarded' },
'From', { value: 'From' },
'Host', { value: 'Host' },
'If-Match', { value: 'If-Match' },
'If-Modified-Since', { value: 'If-Modified-Since' },
'If-None-Match', { value: 'If-None-Match' },
'If-Range', { value: 'If-Range' },
'If-Unmodified-Since', { value: 'If-Unmodified-Since' },
'Max-Forwards', { value: 'Max-Forwards' },
'Origin', { value: 'Origin' },
'Pragma', { value: 'Pragma' },
'Proxy-Authorization', { value: 'Proxy-Authorization' },
'Range', { value: 'Range' },
'Referer', { value: 'Referer' },
'TE', { value: 'TE' },
'User-Agent', { value: 'User-Agent' },
'Upgrade', { value: 'Upgrade' },
'Via', { value: 'Via' },
'Warning', { value: 'Warning' },
'Non-standard headers', { value: 'Non-standard headers' },
'Dnt', { value: 'Dnt' },
'X-Requested-With', { value: 'X-Requested-With' },
'X-CSRF-Token', { value: 'X-CSRF-Token' },
] ])
const addHeaderRow = () => vModel.value.push({}) const addHeaderRow = () => vModel.value.push({})
const deleteHeaderRow = (i: number) => vModel.value.splice(i, 1) const deleteHeaderRow = (i: number) => vModel.value.splice(i, 1)
const filterOption = (input: string, option: Option) => {
return option.value.toUpperCase().includes(input.toUpperCase())
}
</script> </script>
<template> <template>
@ -89,18 +97,14 @@ const deleteHeaderRow = (i: number) => vModel.value.splice(i, 1)
<td class="px-2 w-min-[400px]"> <td class="px-2 w-min-[400px]">
<a-form-item> <a-form-item>
<a-select <a-auto-complete
v-model:value="headerRow.name" v-model:value="headerRow.name"
size="large" size="large"
placeholder="Key" placeholder="Key"
class="nc-input-hook-header-key" class="nc-input-hook-header-key"
dropdown-class-name="nc-dropdown-webhook-header" :options="headerList"
show-search :filter-option="filterOption"
> />
<a-select-option v-for="header in headerList" :key="header" :value="header">
{{ header }}
</a-select-option>
</a-select>
</a-form-item> </a-form-item>
</td> </td>

3
packages/nc-gui/package-lock.json generated

@ -87,7 +87,6 @@
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.98.1", "version": "0.98.1",
"hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
@ -114,7 +113,6 @@
"open-cli": "^6.0.1", "open-cli": "^6.0.1",
"prettier": "^2.1.1", "prettier": "^2.1.1",
"standard-version": "^9.0.0", "standard-version": "^9.0.0",
"swagger-typescript-api": "^10.0.1",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",
"typedoc": "^0.23.16", "typedoc": "^0.23.16",
"typescript": "^4.0.2" "typescript": "^4.0.2"
@ -25577,7 +25575,6 @@
"open-cli": "^6.0.1", "open-cli": "^6.0.1",
"prettier": "^2.1.1", "prettier": "^2.1.1",
"standard-version": "^9.0.0", "standard-version": "^9.0.0",
"swagger-typescript-api": "^10.0.1",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",
"typedoc": "^0.23.16", "typedoc": "^0.23.16",
"typescript": "^4.0.2" "typescript": "^4.0.2"

11307
packages/nocodb-sdk/package-lock.json generated

File diff suppressed because it is too large Load Diff

9
packages/nocodb-sdk/package.json

@ -9,7 +9,6 @@
"license": "MIT", "license": "MIT",
"keywords": [], "keywords": [],
"scripts": { "scripts": {
"preinstall": "npm install --package-lock-only --ignore-scripts && npx npm-force-resolutions",
"build": "npm run generate:sdk && run-p build:*", "build": "npm run generate:sdk && run-p build:*",
"build:main": "tsc -p tsconfig.json", "build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json", "build:module": "tsc -p tsconfig.module.json",
@ -38,8 +37,8 @@
"version": "standard-version", "version": "standard-version",
"reset-hard": "git clean -dfx && git reset --hard && npm i", "reset-hard": "git clean -dfx && git reset --hard && npm i",
"prepare-release": "run-s reset-hard test cov:check doc:html version doc:publish", "prepare-release": "run-s reset-hard test cov:check doc:html version doc:publish",
"generate:sdk": "swagger-typescript-api -r -p ../../scripts/sdk/swagger.json -o ./src/lib/ --axios --unwrap-response-data --module-name-first-tag --type-suffix=Type --templates ../../scripts/sdk/templates", "generate:sdk": "npx --yes swagger-typescript-api -r -p ../../scripts/sdk/swagger.json -o ./src/lib/ --axios --unwrap-response-data --module-name-first-tag --type-suffix=Type --templates ../../scripts/sdk/templates",
"generate:sdk:default": "swagger-typescript-api -r -p ../../scripts/sdk/swagger.json -o ./src/lib/ --name Api2.ts --unwrap-response-data --module-name-first-tag --type-suffix=Type --templates ../../scripts/sdk/templates" "generate:sdk:default": "npx --yes swagger-typescript-api -r -p ../../scripts/sdk/swagger.json -o ./src/lib/ --name Api2.ts --unwrap-response-data --module-name-first-tag --type-suffix=Type --templates ../../scripts/sdk/templates"
}, },
"engines": { "engines": {
"node": ">=10" "node": ">=10"
@ -69,14 +68,10 @@
"open-cli": "^6.0.1", "open-cli": "^6.0.1",
"prettier": "^2.1.1", "prettier": "^2.1.1",
"standard-version": "^9.0.0", "standard-version": "^9.0.0",
"swagger-typescript-api": "^10.0.1",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",
"typedoc": "^0.23.16", "typedoc": "^0.23.16",
"typescript": "^4.0.2" "typescript": "^4.0.2"
}, },
"resolutions": {
"typescript": "4.7.4"
},
"files": [ "files": [
"build/main", "build/main",
"build/module", "build/module",

3
packages/nocodb/package-lock.json generated

@ -176,7 +176,6 @@
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.98.1", "version": "0.98.1",
"hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
@ -203,7 +202,6 @@
"open-cli": "^6.0.1", "open-cli": "^6.0.1",
"prettier": "^2.1.1", "prettier": "^2.1.1",
"standard-version": "^9.0.0", "standard-version": "^9.0.0",
"swagger-typescript-api": "^10.0.1",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",
"typedoc": "^0.23.16", "typedoc": "^0.23.16",
"typescript": "^4.0.2" "typescript": "^4.0.2"
@ -36960,7 +36958,6 @@
"open-cli": "^6.0.1", "open-cli": "^6.0.1",
"prettier": "^2.1.1", "prettier": "^2.1.1",
"standard-version": "^9.0.0", "standard-version": "^9.0.0",
"swagger-typescript-api": "^10.0.1",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",
"typedoc": "^0.23.16", "typedoc": "^0.23.16",
"typescript": "^4.0.2" "typescript": "^4.0.2"

20
packages/nocodb/src/lib/cache/NocoCache.ts vendored

@ -6,6 +6,7 @@ import { CacheGetType } from '../utils/globals';
export default class NocoCache { export default class NocoCache {
private static client: CacheMgr; private static client: CacheMgr;
private static cacheDisabled: boolean; private static cacheDisabled: boolean;
private static prefix: string;
public static init() { public static init() {
this.cacheDisabled = (process.env.NC_DISABLE_CACHE || false) === 'true'; this.cacheDisabled = (process.env.NC_DISABLE_CACHE || false) === 'true';
@ -17,11 +18,15 @@ export default class NocoCache {
} else { } else {
this.client = new RedisMockCacheMgr(); this.client = new RedisMockCacheMgr();
} }
// TODO(cache): fetch orgs once it's implemented
const orgs = 'noco';
this.prefix = `nc:${orgs}`;
} }
public static async set(key, value): Promise<boolean> { public static async set(key, value): Promise<boolean> {
if (this.cacheDisabled) return Promise.resolve(true); if (this.cacheDisabled) return Promise.resolve(true);
return this.client.set(key, value); return this.client.set(`${this.prefix}:${key}`, value);
} }
public static async get(key, type): Promise<any> { public static async get(key, type): Promise<any> {
@ -30,17 +35,17 @@ export default class NocoCache {
else if (type === CacheGetType.TYPE_OBJECT) return Promise.resolve(null); else if (type === CacheGetType.TYPE_OBJECT) return Promise.resolve(null);
return Promise.resolve(null); return Promise.resolve(null);
} }
return this.client.get(key, type); return this.client.get(`${this.prefix}:${key}`, type);
} }
public static async getAll(pattern: string): Promise<any[]> { public static async getAll(pattern: string): Promise<any[]> {
if (this.cacheDisabled) return Promise.resolve([]); if (this.cacheDisabled) return Promise.resolve([]);
return this.client.getAll(pattern); return this.client.getAll(`${this.prefix}:${pattern}`);
} }
public static async del(key): Promise<boolean> { public static async del(key): Promise<boolean> {
if (this.cacheDisabled) return Promise.resolve(true); if (this.cacheDisabled) return Promise.resolve(true);
return this.client.del(key); return this.client.del(`${this.prefix}:${key}`);
} }
public static async delAll(scope: string, pattern: string): Promise<any[]> { public static async delAll(scope: string, pattern: string): Promise<any[]> {
@ -77,10 +82,15 @@ export default class NocoCache {
public static async appendToList( public static async appendToList(
scope: string, scope: string,
subListKeys: string[], subListKeys: string[],
key: string key: string
): Promise<boolean> { ): Promise<boolean> {
if (this.cacheDisabled) return Promise.resolve(true); if (this.cacheDisabled) return Promise.resolve(true);
return this.client.appendToList(scope, subListKeys, key); return this.client.appendToList(
scope,
subListKeys,
`${this.prefix}:${key}`
);
} }
public static async destroy(): Promise<boolean> { public static async destroy(): Promise<boolean> {

40
packages/nocodb/src/lib/cache/RedisCacheMgr.ts vendored

@ -6,12 +6,17 @@ const log = debug('nc:cache');
export default class RedisCacheMgr extends CacheMgr { export default class RedisCacheMgr extends CacheMgr {
client: any; client: any;
prefix: string;
constructor(config: any) { constructor(config: any) {
super(); super();
this.client = new Redis(config); this.client = new Redis(config);
// flush the existing db with selected key (Default: 0) // flush the existing db with selected key (Default: 0)
this.client.flushdb(); this.client.flushdb();
// TODO(cache): fetch orgs once it's implemented
const orgs = 'noco';
this.prefix = `nc:${orgs}`;
} }
// avoid circular structure to JSON // avoid circular structure to JSON
@ -91,10 +96,10 @@ export default class RedisCacheMgr extends CacheMgr {
// @ts-ignore // @ts-ignore
async delAll(scope: string, pattern: string): Promise<any[]> { async delAll(scope: string, pattern: string): Promise<any[]> {
// Example: model:*:<id> // Example: nc:<orgs>:model:*:<id>
const keys = await this.client.keys(`${scope}:${pattern}`); const keys = await this.client.keys(`${this.prefix}:${scope}:${pattern}`);
log( log(
`RedisCacheMgr::delAll: deleting all keys with pattern ${scope}:${pattern}` `RedisCacheMgr::delAll: deleting all keys with pattern ${this.prefix}:${scope}:${pattern}`
); );
return Promise.all( return Promise.all(
keys.map( keys.map(
@ -107,12 +112,12 @@ export default class RedisCacheMgr extends CacheMgr {
async getList(scope: string, subKeys: string[]): Promise<any[]> { async getList(scope: string, subKeys: string[]): Promise<any[]> {
// remove null from arrays // remove null from arrays
subKeys = subKeys.filter((k) => k); subKeys = subKeys.filter((k) => k);
// e.g. key = <scope>:<project_id_1>:<base_id_1>:list // e.g. key = nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
const key = const key =
subKeys.length === 0 subKeys.length === 0
? `${scope}:list` ? `${this.prefix}:${scope}:list`
: `${scope}:${subKeys.join(':')}:list`; : `${this.prefix}:${scope}:${subKeys.join(':')}:list`;
// e.g. arr = ["<scope>:<model_id_1>", "<scope>:<model_id_2>"] // e.g. arr = ["nc:<orgs>:<scope>:<model_id_1>", "nc:<orgs>:<scope>:<model_id_2>"]
const arr = (await this.get(key, CacheGetType.TYPE_ARRAY)) || []; const arr = (await this.get(key, CacheGetType.TYPE_ARRAY)) || [];
log(`RedisCacheMgr::getList: getting list with key ${key}`); log(`RedisCacheMgr::getList: getting list with key ${key}`);
return Promise.all( return Promise.all(
@ -128,11 +133,11 @@ export default class RedisCacheMgr extends CacheMgr {
// remove null from arrays // remove null from arrays
subListKeys = subListKeys.filter((k) => k); subListKeys = subListKeys.filter((k) => k);
// construct key for List // construct key for List
// e.g. <scope>:<project_id_1>:<base_id_1>:list // e.g. nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
const listKey = const listKey =
subListKeys.length === 0 subListKeys.length === 0
? `${scope}:list` ? `${this.prefix}:${scope}:list`
: `${scope}:${subListKeys.join(':')}:list`; : `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
if (!list.length) { if (!list.length) {
log(`RedisCacheMgr::setList: List is empty for ${listKey}. Skipping ...`); log(`RedisCacheMgr::setList: List is empty for ${listKey}. Skipping ...`);
return Promise.resolve(true); return Promise.resolve(true);
@ -142,11 +147,11 @@ export default class RedisCacheMgr extends CacheMgr {
(await this.get(listKey, CacheGetType.TYPE_ARRAY)) || []; (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
for (const o of list) { for (const o of list) {
// construct key for Get // construct key for Get
// e.g. <scope>:<model_id_1> // e.g. nc:<orgs>:<scope>:<model_id_1>
let getKey = `${scope}:${o.id}`; let getKey = `${this.prefix}:${scope}:${o.id}`;
// special case - MODEL_ROLE_VISIBILITY // special case - MODEL_ROLE_VISIBILITY
if (scope === CacheScope.MODEL_ROLE_VISIBILITY) { if (scope === CacheScope.MODEL_ROLE_VISIBILITY) {
getKey = `${scope}:${o.id}:${o.role}`; getKey = `${this.prefix}:${scope}:${o.id}:${o.role}`;
} }
// set Get Key // set Get Key
log(`RedisCacheMgr::setList: setting key ${getKey}`); log(`RedisCacheMgr::setList: setting key ${getKey}`);
@ -164,10 +169,11 @@ export default class RedisCacheMgr extends CacheMgr {
key: string, key: string,
direction: string direction: string
): Promise<boolean> { ): Promise<boolean> {
key = `${this.prefix}:${key}`;
log(`RedisCacheMgr::deepDel: choose direction ${direction}`); log(`RedisCacheMgr::deepDel: choose direction ${direction}`);
if (direction === CacheDelDirection.CHILD_TO_PARENT) { if (direction === CacheDelDirection.CHILD_TO_PARENT) {
// given a child key, delete all keys in corresponding parent lists // given a child key, delete all keys in corresponding parent lists
const scopeList = await this.client.keys(`${scope}*list`); const scopeList = await this.client.keys(`${this.prefix}:${scope}*list`);
for (const listKey of scopeList) { for (const listKey of scopeList) {
// get target list // get target list
let list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || []; let list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
@ -208,11 +214,11 @@ export default class RedisCacheMgr extends CacheMgr {
): Promise<boolean> { ): Promise<boolean> {
// remove null from arrays // remove null from arrays
subListKeys = subListKeys.filter((k) => k); subListKeys = subListKeys.filter((k) => k);
// e.g. key = <scope>:<project_id_1>:<base_id_1>:list // e.g. key = nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
const listKey = const listKey =
subListKeys.length === 0 subListKeys.length === 0
? `${scope}:list` ? `${this.prefix}:${scope}:list`
: `${scope}:${subListKeys.join(':')}:list`; : `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
log(`RedisCacheMgr::appendToList: append key ${key} to ${listKey}`); log(`RedisCacheMgr::appendToList: append key ${key} to ${listKey}`);
const list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || []; const list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
list.push(key); list.push(key);

40
packages/nocodb/src/lib/cache/RedisMockCacheMgr.ts vendored

@ -6,12 +6,17 @@ const log = debug('nc:cache');
export default class RedisMockCacheMgr extends CacheMgr { export default class RedisMockCacheMgr extends CacheMgr {
client: any; client: any;
prefix: string;
constructor() { constructor() {
super(); super();
this.client = new Redis(); this.client = new Redis();
// flush the existing db with selected key (Default: 0) // flush the existing db with selected key (Default: 0)
this.client.flushdb(); this.client.flushdb();
// TODO(cache): fetch orgs once it's implemented
const orgs = 'noco';
this.prefix = `nc:${orgs}`;
} }
// avoid circular structure to JSON // avoid circular structure to JSON
@ -91,10 +96,10 @@ export default class RedisMockCacheMgr extends CacheMgr {
// @ts-ignore // @ts-ignore
async delAll(scope: string, pattern: string): Promise<any[]> { async delAll(scope: string, pattern: string): Promise<any[]> {
// Example: model:*:<id> // Example: nc:<orgs>:model:*:<id>
const keys = await this.client.keys(`${scope}:${pattern}`); const keys = await this.client.keys(`${this.prefix}:${scope}:${pattern}`);
log( log(
`RedisMockCacheMgr::delAll: deleting all keys with pattern ${scope}:${pattern}` `RedisMockCacheMgr::delAll: deleting all keys with pattern ${this.prefix}:${scope}:${pattern}`
); );
return Promise.all( return Promise.all(
keys.map( keys.map(
@ -107,12 +112,12 @@ export default class RedisMockCacheMgr extends CacheMgr {
async getList(scope: string, subKeys: string[]): Promise<any[]> { async getList(scope: string, subKeys: string[]): Promise<any[]> {
// remove null from arrays // remove null from arrays
subKeys = subKeys.filter((k) => k); subKeys = subKeys.filter((k) => k);
// e.g. key = <scope>:<project_id_1>:<base_id_1>:list // e.g. key = nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
const key = const key =
subKeys.length === 0 subKeys.length === 0
? `${scope}:list` ? `${this.prefix}:${scope}:list`
: `${scope}:${subKeys.join(':')}:list`; : `${this.prefix}:${scope}:${subKeys.join(':')}:list`;
// e.g. arr = ["<scope>:<model_id_1>", "<scope>:<model_id_2>"] // e.g. arr = ["nc:<orgs>:<scope>:<model_id_1>", "nc:<orgs>:<scope>:<model_id_2>"]
const arr = (await this.get(key, CacheGetType.TYPE_ARRAY)) || []; const arr = (await this.get(key, CacheGetType.TYPE_ARRAY)) || [];
log(`RedisMockCacheMgr::getList: getting list with key ${key}`); log(`RedisMockCacheMgr::getList: getting list with key ${key}`);
return Promise.all( return Promise.all(
@ -128,11 +133,11 @@ export default class RedisMockCacheMgr extends CacheMgr {
// remove null from arrays // remove null from arrays
subListKeys = subListKeys.filter((k) => k); subListKeys = subListKeys.filter((k) => k);
// construct key for List // construct key for List
// e.g. <scope>:<project_id_1>:<base_id_1>:list // e.g. nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
const listKey = const listKey =
subListKeys.length === 0 subListKeys.length === 0
? `${scope}:list` ? `${this.prefix}:${scope}:list`
: `${scope}:${subListKeys.join(':')}:list`; : `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
if (!list.length) { if (!list.length) {
log( log(
`RedisMockCacheMgr::setList: List is empty for ${listKey}. Skipping ...` `RedisMockCacheMgr::setList: List is empty for ${listKey}. Skipping ...`
@ -144,11 +149,11 @@ export default class RedisMockCacheMgr extends CacheMgr {
(await this.get(listKey, CacheGetType.TYPE_ARRAY)) || []; (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
for (const o of list) { for (const o of list) {
// construct key for Get // construct key for Get
// e.g. <scope>:<model_id_1> // e.g. nc:<orgs>:<scope>:<model_id_1>
let getKey = `${scope}:${o.id}`; let getKey = `${this.prefix}:${scope}:${o.id}`;
// special case - MODEL_ROLE_VISIBILITY // special case - MODEL_ROLE_VISIBILITY
if (scope === CacheScope.MODEL_ROLE_VISIBILITY) { if (scope === CacheScope.MODEL_ROLE_VISIBILITY) {
getKey = `${scope}:${o.id}:${o.role}`; getKey = `${this.prefix}:${scope}:${o.id}:${o.role}`;
} }
// set Get Key // set Get Key
log(`RedisMockCacheMgr::setList: setting key ${getKey}`); log(`RedisMockCacheMgr::setList: setting key ${getKey}`);
@ -166,10 +171,11 @@ export default class RedisMockCacheMgr extends CacheMgr {
key: string, key: string,
direction: string direction: string
): Promise<boolean> { ): Promise<boolean> {
key = `${this.prefix}:${key}`;
log(`RedisMockCacheMgr::deepDel: choose direction ${direction}`); log(`RedisMockCacheMgr::deepDel: choose direction ${direction}`);
if (direction === CacheDelDirection.CHILD_TO_PARENT) { if (direction === CacheDelDirection.CHILD_TO_PARENT) {
// given a child key, delete all keys in corresponding parent lists // given a child key, delete all keys in corresponding parent lists
const scopeList = await this.client.keys(`${scope}*list`); const scopeList = await this.client.keys(`${this.prefix}:${scope}*list`);
for (const listKey of scopeList) { for (const listKey of scopeList) {
// get target list // get target list
let list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || []; let list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
@ -210,11 +216,11 @@ export default class RedisMockCacheMgr extends CacheMgr {
): Promise<boolean> { ): Promise<boolean> {
// remove null from arrays // remove null from arrays
subListKeys = subListKeys.filter((k) => k); subListKeys = subListKeys.filter((k) => k);
// e.g. key = <scope>:<project_id_1>:<base_id_1>:list // e.g. key = nc:<orgs>:<scope>:<project_id_1>:<base_id_1>:list
const listKey = const listKey =
subListKeys.length === 0 subListKeys.length === 0
? `${scope}:list` ? `${this.prefix}:${scope}:list`
: `${scope}:${subListKeys.join(':')}:list`; : `${this.prefix}:${scope}:${subListKeys.join(':')}:list`;
log(`RedisMockCacheMgr::appendToList: append key ${key} to ${listKey}`); log(`RedisMockCacheMgr::appendToList: append key ${key} to ${listKey}`);
const list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || []; const list = (await this.get(listKey, CacheGetType.TYPE_ARRAY)) || [];
list.push(key); list.push(key);

Loading…
Cancel
Save