Browse Source

Merge pull request #7727 from nocodb/nc-fix/cache-del

fix: cache del and update
pull/7723/head
Raju Udava 9 months ago committed by GitHub
parent
commit
67d28205ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 18
      packages/nc-gui/components/dlg/TableDuplicate.vue
  2. 2
      packages/nc-gui/components/smartsheet/Kanban.vue
  3. 2
      packages/nc-gui/composables/useKanbanViewStore.ts
  4. 11
      packages/nocodb/src/cache/CacheMgr.ts
  5. 8
      packages/nocodb/src/cache/NocoCache.ts
  6. 14
      packages/nocodb/src/db/BaseModelSqlv2.ts
  7. 10
      packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts
  8. 34
      packages/nocodb/src/models/BaseUser.ts
  9. 41
      packages/nocodb/src/models/CalendarView.ts
  10. 17
      packages/nocodb/src/models/CalendarViewColumn.ts
  11. 102
      packages/nocodb/src/models/Column.ts
  12. 11
      packages/nocodb/src/models/Filter.ts
  13. 31
      packages/nocodb/src/models/FormView.ts
  14. 25
      packages/nocodb/src/models/FormViewColumn.ts
  15. 10
      packages/nocodb/src/models/FormulaColumn.ts
  16. 24
      packages/nocodb/src/models/GalleryView.ts
  17. 32
      packages/nocodb/src/models/GridView.ts
  18. 15
      packages/nocodb/src/models/GridViewColumn.ts
  19. 13
      packages/nocodb/src/models/Hook.ts
  20. 13
      packages/nocodb/src/models/HookFilter.ts
  21. 28
      packages/nocodb/src/models/KanbanView.ts
  22. 34
      packages/nocodb/src/models/MapView.ts
  23. 136
      packages/nocodb/src/models/Model.ts
  24. 20
      packages/nocodb/src/models/ModelRoleVisibility.ts
  25. 13
      packages/nocodb/src/models/Plugin.ts
  26. 15
      packages/nocodb/src/models/Sort.ts
  27. 46
      packages/nocodb/src/models/Source.ts
  28. 129
      packages/nocodb/src/models/View.ts
  29. 7
      packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts
  30. 11
      packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts
  31. 35
      packages/nocodb/src/utils/modelUtils.ts

18
packages/nc-gui/components/dlg/TableDuplicate.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import type { TableType } from 'nocodb-sdk' import { type LinkToAnotherRecordType, type TableType, UITypes } from 'nocodb-sdk'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { useVModel } from '#imports' import { useVModel } from '#imports'
import type { TabType } from '#imports' import type { TabType } from '#imports'
@ -31,6 +31,8 @@ const { loadTables } = baseStore
const { tables } = storeToRefs(baseStore) const { tables } = storeToRefs(baseStore)
const { getMeta } = useMetas()
const { t } = useI18n() const { t } = useI18n()
const { activeTable: _activeTable } = storeToRefs(useTablesStore()) const { activeTable: _activeTable } = storeToRefs(useTablesStore())
@ -74,6 +76,20 @@ const _duplicate = async () => {
}) => { }) => {
if (data.status !== 'close') { if (data.status !== 'close') {
if (data.status === JobStatus.COMPLETED) { if (data.status === JobStatus.COMPLETED) {
const sourceTable = await getMeta(props.table.id!)
if (sourceTable) {
for (const col of sourceTable.columns || []) {
if ([UITypes.Links, UITypes.LinkToAnotherRecord].includes(col.uidt as UITypes)) {
if (col && col.colOptions) {
const relatedTableId = (col.colOptions as LinkToAnotherRecordType)?.fk_related_model_id
if (relatedTableId) {
await getMeta(relatedTableId, true)
}
}
}
}
}
await loadTables() await loadTables()
refreshCommandPalette() refreshCommandPalette()
const newTable = tables.value.find((el) => el.id === data?.data?.result?.id) const newTable = tables.value.find((el) => el.id === data?.data?.result?.id)

2
packages/nc-gui/components/smartsheet/Kanban.vue

@ -232,7 +232,7 @@ async function onMoveStack(event: any, undo = false) {
const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value
groupingFieldColOptions.value[oldIndex].order = newIndex groupingFieldColOptions.value[oldIndex].order = newIndex
groupingFieldColOptions.value[newIndex].order = oldIndex groupingFieldColOptions.value[newIndex].order = oldIndex
const stackMetaObj = JSON.parse(stack_meta as string) || {} const stackMetaObj = parseProp(stack_meta) || {}
stackMetaObj[fk_grp_col_id as string] = groupingFieldColOptions.value stackMetaObj[fk_grp_col_id as string] = groupingFieldColOptions.value
await updateKanbanMeta({ await updateKanbanMeta({
meta: stackMetaObj, meta: stackMetaObj,

2
packages/nc-gui/composables/useKanbanViewStore.ts

@ -211,7 +211,7 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value
stackMetaObj.value = stack_meta ? JSON.parse(stack_meta as string) : {} stackMetaObj.value = parseProp(stack_meta) || {}
if (stackMetaObj.value && fk_grp_col_id && stackMetaObj.value[fk_grp_col_id]) { if (stackMetaObj.value && fk_grp_col_id && stackMetaObj.value[fk_grp_col_id]) {
// keep the existing order (index of the array) but update the values done outside kanban // keep the existing order (index of the array) but update the values done outside kanban

11
packages/nocodb/src/cache/CacheMgr.ts vendored

@ -500,6 +500,17 @@ export default abstract class CacheMgr {
}); });
} }
async update(key: string, value: any): Promise<boolean> {
let o = await this.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...value };
// set cache
await this.set(key, o);
}
return true;
}
// wrap value with metadata // wrap value with metadata
prepareValue(args: { prepareValue(args: {
value: any; value: any;

8
packages/nocodb/src/cache/NocoCache.ts vendored

@ -106,6 +106,14 @@ export default class NocoCache {
); );
} }
public static async update(
key: string,
updateObj: Record<string, any>,
): Promise<boolean> {
if (this.cacheDisabled) return Promise.resolve(true);
return this.client.update(`${this.prefix}:${key}`, updateObj);
}
public static async destroy(): Promise<boolean> { public static async destroy(): Promise<boolean> {
if (this.cacheDisabled) return Promise.resolve(true); if (this.cacheDisabled) return Promise.resolve(true);
return this.client.destroy(); return this.client.destroy();

14
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -3039,6 +3039,8 @@ class BaseModelSqlv2 {
// TODO: ag column handling for raw bulk insert // TODO: ag column handling for raw bulk insert
const insertDatas = raw ? datas : []; const insertDatas = raw ? datas : [];
let postInsertOps: ((rowId: any, trx?: any) => Promise<void>)[] = []; let postInsertOps: ((rowId: any, trx?: any) => Promise<void>)[] = [];
let aiPkCol: Column;
let agPkCol: Column;
if (!raw) { if (!raw) {
const nestedCols = (await this.model.getColumns()).filter((c) => const nestedCols = (await this.model.getColumns()).filter((c) =>
@ -3194,6 +3196,9 @@ class BaseModelSqlv2 {
insertDatas.push(insertObj); insertDatas.push(insertObj);
} }
aiPkCol = this.model.primaryKeys.find((pk) => pk.ai);
agPkCol = this.model.primaryKeys.find((pk) => pk.meta?.ag);
} }
if ('beforeBulkInsert' in this) { if ('beforeBulkInsert' in this) {
@ -3219,9 +3224,6 @@ class BaseModelSqlv2 {
let responses; let responses;
const aiPkCol = this.model.primaryKeys.find((pk) => pk.ai);
const agPkCol = this.model.primaryKeys.find((pk) => pk.meta?.ag);
// insert one by one as fallback to get ids for sqlite and mysql // insert one by one as fallback to get ids for sqlite and mysql
if (insertOneByOneAsFallback && (this.isSqlite || this.isMySQL)) { if (insertOneByOneAsFallback && (this.isSqlite || this.isMySQL)) {
// sqlite and mysql doesn't support returning, so insert one by one and return ids // sqlite and mysql doesn't support returning, so insert one by one and return ids
@ -3248,8 +3250,10 @@ class BaseModelSqlv2 {
} else { } else {
const returningArr: string[] = []; const returningArr: string[] = [];
for (const col of this.model.primaryKeys) { if (!raw) {
returningArr.push(col.column_name); for (const col of this.model.primaryKeys) {
returningArr.push(col.column_name);
}
} }
responses = responses =

10
packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts

@ -1217,13 +1217,9 @@ export default async function formulaQueryBuilderv2(
error: e.message, error: e.message,
}); });
// update cache to reflect the error in UI // update cache to reflect the error in UI
const key = `${CacheScope.COL_FORMULA}:${column.id}`; await NocoCache.update(`${CacheScope.COL_FORMULA}:${column.id}`, {
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); error: e.message,
if (o) { });
o = { ...o, error: e.message };
// set cache
await NocoCache.set(key, o);
}
} }
throw new Error(`Formula error: ${e.message}`); throw new Error(`Formula error: ${e.message}`);
} }

34
packages/nocodb/src/models/BaseUser.ts

@ -3,7 +3,7 @@ import type { BaseType } from 'nocodb-sdk';
import type User from '~/models/User'; import type User from '~/models/User';
import Base from '~/models/Base'; import Base from '~/models/Base';
import { import {
// CacheDelDirection, CacheDelDirection,
CacheGetType, CacheGetType,
CacheScope, CacheScope,
MetaTable, MetaTable,
@ -205,17 +205,8 @@ export default class BaseUser {
roles: string, roles: string,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.BASE_USER}:${baseId}:${userId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.roles = roles;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.PROJECT_USERS, MetaTable.PROJECT_USERS,
@ -227,6 +218,12 @@ export default class BaseUser {
base_id: baseId, base_id: baseId,
}, },
); );
await NocoCache.update(`${CacheScope.BASE_USER}:${baseId}:${userId}`, {
roles,
});
return res;
} }
static async update( static async update(
@ -237,18 +234,17 @@ export default class BaseUser {
) { ) {
const updateObj = extractProps(baseUser, ['starred', 'hidden', 'order']); const updateObj = extractProps(baseUser, ['starred', 'hidden', 'order']);
const key = `${CacheScope.BASE_USER}:${baseId}:${userId}`;
// set meta // set meta
await ncMeta.metaUpdate(null, null, MetaTable.PROJECT_USERS, updateObj, { await ncMeta.metaUpdate(null, null, MetaTable.PROJECT_USERS, updateObj, {
fk_user_id: userId, fk_user_id: userId,
base_id: baseId, base_id: baseId,
}); });
// delete cache await NocoCache.update(
await NocoCache.del(key); `${CacheScope.BASE_USER}:${baseId}:${userId}`,
updateObj,
);
// cache and return
return await this.get(baseId, userId, ncMeta); return await this.get(baseId, userId, ncMeta);
} }
@ -265,8 +261,10 @@ export default class BaseUser {
); );
// delete list cache to refresh list // delete list cache to refresh list
await NocoCache.del(`${CacheScope.BASE_USER}:${baseId}:${userId}`); await NocoCache.deepDel(
await NocoCache.del(`${CacheScope.BASE_USER}:${baseId}:list`); `${CacheScope.BASE_USER}:${baseId}:${userId}`,
CacheDelDirection.CHILD_TO_PARENT,
);
return response; return response;
} }

41
packages/nocodb/src/models/CalendarView.ts

@ -2,9 +2,15 @@ import type { BoolType, MetaType } from 'nocodb-sdk';
import type { CalendarType } from 'nocodb-sdk'; import type { CalendarType } from 'nocodb-sdk';
import View from '~/models/View'; import View from '~/models/View';
import { extractProps } from '~/helpers/extractProps'; import { extractProps } from '~/helpers/extractProps';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco'; import Noco from '~/Noco';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; import {
CacheDelDirection,
CacheGetType,
CacheScope,
MetaTable,
} from '~/utils/globals';
import CalendarRange from '~/models/CalendarRange'; import CalendarRange from '~/models/CalendarRange';
export default class CalendarView implements CalendarType { export default class CalendarView implements CalendarType {
@ -85,24 +91,14 @@ export default class CalendarView implements CalendarType {
body: Partial<CalendarView>, body: Partial<CalendarView>,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.CALENDAR_VIEW}:${calendarId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']); const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
if (body.calendar_range) { if (body.calendar_range) {
await NocoCache.del(`${CacheScope.CALENDAR_VIEW}:${calendarId}`); // if calendar range is updated, delete cache
await NocoCache.deepDel(
`${CacheScope.CALENDAR_VIEW}:${calendarId}`,
CacheDelDirection.CHILD_TO_PARENT,
);
await ncMeta.metaDelete( await ncMeta.metaDelete(
null, null,
null, null,
@ -121,15 +117,24 @@ export default class CalendarView implements CalendarType {
}), }),
); );
} }
// update meta // update meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.CALENDAR_VIEW, MetaTable.CALENDAR_VIEW,
updateObj, prepareForDb(updateObj),
{ {
fk_view_id: calendarId, fk_view_id: calendarId,
}, },
); );
// update cache
await NocoCache.update(
`${CacheScope.CALENDAR_VIEW}:${calendarId}`,
prepareForResponse(updateObj),
);
return res;
} }
} }

17
packages/nocodb/src/models/CalendarViewColumn.ts

@ -162,21 +162,20 @@ export default class CalendarViewColumn {
'italic', 'italic',
]); ]);
// get existing cache
const key = `${CacheScope.CALENDAR_VIEW_COLUMN}:${columnId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
Object.assign(o, updateObj);
// set cache
await NocoCache.set(key, o);
}
// update meta // update meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.CALENDAR_VIEW_COLUMNS, MetaTable.CALENDAR_VIEW_COLUMNS,
updateObj, updateObj,
columnId, columnId,
); );
await NocoCache.update(
`${CacheScope.CALENDAR_VIEW_COLUMN}:${columnId}`,
updateObj,
);
return res;
} }
} }

102
packages/nocodb/src/models/Column.ts

@ -28,7 +28,11 @@ import {
MetaTable, MetaTable,
} from '~/utils/globals'; } from '~/utils/globals';
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
import { parseMetaProp, stringifyMetaProp } from '~/utils/modelUtils'; import {
parseMetaProp,
prepareForDb,
prepareForResponse,
} from '~/utils/modelUtils';
import { getFormulasReferredTheColumn } from '~/helpers/formulaHelpers'; import { getFormulasReferredTheColumn } from '~/helpers/formulaHelpers';
const selectColors = [ const selectColors = [
@ -479,13 +483,6 @@ export default class Column<T = any> implements ColumnType {
return this.model; return this.model;
} }
public static async clearList({ fk_model_id }) {
await NocoCache.deepDel(
`${CacheScope.COLUMN}:${fk_model_id}:list`,
CacheDelDirection.PARENT_TO_CHILD,
);
}
public static async list( public static async list(
{ {
fk_model_id, fk_model_id,
@ -1084,52 +1081,20 @@ export default class Column<T = any> implements ColumnType {
}); });
} }
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// get model column list from cache
const columnListFromCache = await NocoCache.getList(CacheScope.COLUMN, [
oldCol.fk_model_id,
]);
// update column list in cache if cache exists
if (!columnListFromCache.list?.length) {
const updatedColumnList = columnListFromCache.list.map((column: any) => {
if (column.id === colId) {
return {
...column,
...updateObj,
};
}
return column;
});
await NocoCache.setList(
CacheScope.COLUMN,
[oldCol.fk_model_id],
updatedColumnList,
);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.COLUMNS, MetaTable.COLUMNS,
{ prepareForDb(updateObj),
...updateObj,
meta:
updateObj.meta && typeof updateObj.meta === 'object'
? JSON.stringify(updateObj.meta)
: updateObj.meta,
},
colId, colId,
); );
await NocoCache.update(
`${CacheScope.COLUMN}:${colId}`,
prepareForResponse(updateObj),
);
await this.insertColOption(column, colId, ncMeta); await this.insertColOption(column, colId, ncMeta);
// on column update, delete any optimised single query cache // on column update, delete any optimised single query cache
@ -1166,15 +1131,6 @@ export default class Column<T = any> implements ColumnType {
{ title }: { title: string }, { title }: { title: string },
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.title = title;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, //column.base_id || column.source_id, null, //column.base_id || column.source_id,
@ -1186,6 +1142,8 @@ export default class Column<T = any> implements ColumnType {
colId, colId,
); );
await NocoCache.update(`${CacheScope.COLUMN}:${colId}`, { title });
const column = await Column.get({ colId }, ncMeta); const column = await Column.get({ colId }, ncMeta);
await View.clearSingleQueryCache(column.fk_model_id); await View.clearSingleQueryCache(column.fk_model_id);
@ -1246,15 +1204,6 @@ export default class Column<T = any> implements ColumnType {
system = true, system = true,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.system = system;
// set cache
await NocoCache.set(key, o);
}
// update system field in meta db // update system field in meta db
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -1265,6 +1214,8 @@ export default class Column<T = any> implements ColumnType {
}, },
colId, colId,
); );
await NocoCache.update(`${CacheScope.COLUMN}:${colId}`, { system });
} }
static getMaxColumnNameLength(sqlClientType: string) { static getMaxColumnNameLength(sqlClientType: string) {
@ -1284,25 +1235,19 @@ export default class Column<T = any> implements ColumnType {
{ colId, meta }: { colId: string; meta: any }, { colId, meta }: { colId: string; meta: any },
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.COLUMN}:${colId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update meta
o.meta = meta;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.COLUMNS, MetaTable.COLUMNS,
{ prepareForDb({ meta }),
meta: stringifyMetaProp({ meta }),
},
colId, colId,
); );
await NocoCache.update(
`${CacheScope.COLUMN}:${colId}`,
prepareForResponse({ meta }),
);
} }
static async bulkInsert( static async bulkInsert(
@ -1384,10 +1329,7 @@ export default class Column<T = any> implements ColumnType {
true, true,
); );
// insert column options if any
// for (const column of columns) {
await Column.bulkInsertColOption(columns, ncMeta); await Column.bulkInsertColOption(columns, ncMeta);
// }
return columns; return columns;
} }

11
packages/nocodb/src/models/Filter.ts

@ -234,15 +234,6 @@ export default class Filter implements FilterType {
if (typeof updateObj.value === 'string') if (typeof updateObj.value === 'string')
updateObj.value = updateObj.value.slice(0, 255); updateObj.value = updateObj.value.slice(0, 255);
// get existing cache
const key = `${CacheScope.FILTER_EXP}:${id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
const res = await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
@ -252,6 +243,8 @@ export default class Filter implements FilterType {
id, id,
); );
await NocoCache.update(`${CacheScope.FILTER_EXP}:${id}`, updateObj);
// on update delete any optimised single query cache // on update delete any optimised single query cache
{ {
const filter = await this.get(id, ncMeta); const filter = await this.get(id, ncMeta);

31
packages/nocodb/src/models/FormView.ts

@ -7,6 +7,7 @@ import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco'; import Noco from '~/Noco';
import { deserializeJSON, serializeJSON } from '~/utils/serialize'; import { deserializeJSON, serializeJSON } from '~/utils/serialize';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class FormView implements FormType { export default class FormView implements FormType {
show: BoolType; show: BoolType;
@ -88,9 +89,6 @@ export default class FormView implements FormType {
body: Partial<FormView>, body: Partial<FormView>,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.FORM_VIEW}:${formId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, [ const updateObj = extractProps(body, [
'heading', 'heading',
'subheading', 'subheading',
@ -105,20 +103,23 @@ export default class FormView implements FormType {
'meta', 'meta',
]); ]);
if (o) { // update meta
o = { ...o, ...updateObj }; const res = await ncMeta.metaUpdate(
// set cache null,
await NocoCache.set(key, o); null,
} MetaTable.FORM_VIEW,
prepareForDb(updateObj),
{
fk_view_id: formId,
},
);
if (updateObj.meta) { await NocoCache.update(
updateObj.meta = serializeJSON(updateObj.meta); `${CacheScope.FORM_VIEW}:${formId}`,
} prepareForResponse(updateObj),
);
// update meta return res;
return await ncMeta.metaUpdate(null, null, MetaTable.FORM_VIEW, updateObj, {
fk_view_id: formId,
});
} }
async getColumns(ncMeta = Noco.ncMeta) { async getColumns(ncMeta = Noco.ncMeta) {

25
packages/nocodb/src/models/FormViewColumn.ts

@ -10,6 +10,7 @@ import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps'; import { extractProps } from '~/helpers/extractProps';
import { deserializeJSON, serializeJSON } from '~/utils/serialize'; import { deserializeJSON, serializeJSON } from '~/utils/serialize';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class FormViewColumn implements FormColumnType { export default class FormViewColumn implements FormColumnType {
id?: string; id?: string;
@ -168,26 +169,20 @@ export default class FormViewColumn implements FormColumnType {
'enable_scanner', 'enable_scanner',
]); ]);
// get existing cache
const key = `${CacheScope.FORM_VIEW_COLUMN}:${columnId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
Object.assign(o, updateObj);
// set cache
await NocoCache.set(key, o);
}
if (updateObj.meta) {
updateObj.meta = serializeJSON(updateObj.meta);
}
// update meta // update meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.FORM_VIEW_COLUMNS, MetaTable.FORM_VIEW_COLUMNS,
updateObj, prepareForDb(updateObj),
columnId, columnId,
); );
await NocoCache.update(
`${CacheScope.FORM_VIEW_COLUMN}:${columnId}`,
prepareForResponse(updateObj),
);
return res;
} }
} }

10
packages/nocodb/src/models/FormulaColumn.ts

@ -74,20 +74,14 @@ export default class FormulaColumn {
'parsed_tree', 'parsed_tree',
]); ]);
// get existing cache
const key = `${CacheScope.COL_FORMULA}:${columnId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
if ('parsed_tree' in updateObj) if ('parsed_tree' in updateObj)
updateObj.parsed_tree = stringifyMetaProp(updateObj, 'parsed_tree'); updateObj.parsed_tree = stringifyMetaProp(updateObj, 'parsed_tree');
// set meta // set meta
await ncMeta.metaUpdate(null, null, MetaTable.COL_FORMULA, updateObj, { await ncMeta.metaUpdate(null, null, MetaTable.COL_FORMULA, updateObj, {
fk_column_id: columnId, fk_column_id: columnId,
}); });
await NocoCache.update(`${CacheScope.COL_FORMULA}:${columnId}`, updateObj);
} }
public getParsedTree() { public getParsedTree() {

24
packages/nocodb/src/models/GalleryView.ts

@ -10,6 +10,7 @@ import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps'; import { extractProps } from '~/helpers/extractProps';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class GalleryView implements GalleryType { export default class GalleryView implements GalleryType {
fk_view_id?: string; fk_view_id?: string;
@ -98,29 +99,24 @@ export default class GalleryView implements GalleryType {
body: Partial<GalleryView>, body: Partial<GalleryView>,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.GALLERY_VIEW}:${galleryId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']); const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// update meta // update meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.GALLERY_VIEW, MetaTable.GALLERY_VIEW,
updateObj, prepareForDb(updateObj),
{ {
fk_view_id: galleryId, fk_view_id: galleryId,
}, },
); );
await NocoCache.update(
`${CacheScope.GALLERY_VIEW}:${galleryId}`,
prepareForResponse(updateObj),
);
return res;
} }
} }

32
packages/nocodb/src/models/GridView.ts

@ -5,6 +5,7 @@ import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps'; import { extractProps } from '~/helpers/extractProps';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class GridView implements GridType { export default class GridView implements GridType {
fk_view_id: string; fk_view_id: string;
@ -68,23 +69,24 @@ export default class GridView implements GridType {
body: Partial<GridView>, body: Partial<GridView>,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.GRID_VIEW}:${viewId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['row_height', 'meta']); const updateObj = extractProps(body, ['row_height', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// update meta // update meta
return await ncMeta.metaUpdate(null, null, MetaTable.GRID_VIEW, updateObj, { const res = await ncMeta.metaUpdate(
fk_view_id: viewId, null,
}); null,
MetaTable.GRID_VIEW,
prepareForDb(updateObj),
{
fk_view_id: viewId,
},
);
await NocoCache.update(
`${CacheScope.GRID_VIEW}:${viewId}`,
prepareForResponse(updateObj),
);
return res;
} }
} }

15
packages/nocodb/src/models/GridViewColumn.ts

@ -140,15 +140,7 @@ export default class GridViewColumn implements GridColumnType {
'group_by_order', 'group_by_order',
'group_by_sort', 'group_by_sort',
]); ]);
// get existing cache
const key = `${CacheScope.GRID_VIEW_COLUMN}:${columnId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
const res = await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
@ -158,6 +150,11 @@ export default class GridViewColumn implements GridColumnType {
columnId, columnId,
); );
await NocoCache.update(
`${CacheScope.GRID_VIEW_COLUMN}:${columnId}`,
updateObj,
);
// on view column update, delete any optimised single query cache // on view column update, delete any optimised single query cache
{ {
const gridCol = await this.get(columnId, ncMeta); const gridCol = await this.get(columnId, ncMeta);

13
packages/nocodb/src/models/Hook.ts

@ -209,20 +209,11 @@ export default class Hook implements HookType {
updateObj.notification = JSON.stringify(updateObj.notification); updateObj.notification = JSON.stringify(updateObj.notification);
} }
// get existing cache
const key = `${CacheScope.HOOK}:${hookId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...updateObj };
// replace notification
o.notification = updateObj.notification;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate(null, null, MetaTable.HOOKS, updateObj, hookId); await ncMeta.metaUpdate(null, null, MetaTable.HOOKS, updateObj, hookId);
await NocoCache.update(`${CacheScope.HOOK}:${hookId}`, updateObj);
return this.get(hookId, ncMeta); return this.get(hookId, ncMeta);
} }

13
packages/nocodb/src/models/HookFilter.ts

@ -152,17 +152,12 @@ export default class Filter {
'is_group', 'is_group',
'logical_op', 'logical_op',
]); ]);
// get existing cache
const key = `${CacheScope.FILTER_EXP}:${id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate(null, null, MetaTable.FILTER_EXP, updateObj, id); await ncMeta.metaUpdate(null, null, MetaTable.FILTER_EXP, updateObj, id);
// update cache
await NocoCache.update(`${CacheScope.FILTER_EXP}:${id}`, updateObj);
} }
static async delete(id: string, ncMeta = Noco.ncMeta) { static async delete(id: string, ncMeta = Noco.ncMeta) {

28
packages/nocodb/src/models/KanbanView.ts

@ -5,6 +5,7 @@ import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
import { extractProps } from '~/helpers/extractProps'; import { extractProps } from '~/helpers/extractProps';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class KanbanView implements KanbanType { export default class KanbanView implements KanbanType {
fk_view_id: string; fk_view_id: string;
@ -39,6 +40,9 @@ export default class KanbanView implements KanbanType {
view = await ncMeta.metaGet2(null, null, MetaTable.KANBAN_VIEW, { view = await ncMeta.metaGet2(null, null, MetaTable.KANBAN_VIEW, {
fk_view_id: viewId, fk_view_id: viewId,
}); });
view = prepareForResponse(view);
await NocoCache.set(`${CacheScope.KANBAN_VIEW}:${viewId}`, view); await NocoCache.set(`${CacheScope.KANBAN_VIEW}:${viewId}`, view);
} }
@ -99,34 +103,28 @@ export default class KanbanView implements KanbanType {
body: Partial<KanbanView>, body: Partial<KanbanView>,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.KANBAN_VIEW}:${kanbanId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, [ const updateObj = extractProps(body, [
'fk_cover_image_col_id', 'fk_cover_image_col_id',
'fk_grp_col_id', 'fk_grp_col_id',
'meta', 'meta',
]); ]);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// update meta // update meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.KANBAN_VIEW, MetaTable.KANBAN_VIEW,
updateObj, prepareForDb(updateObj),
{ {
fk_view_id: kanbanId, fk_view_id: kanbanId,
}, },
); );
await NocoCache.update(
`${CacheScope.KANBAN_VIEW}:${kanbanId}`,
prepareForResponse(updateObj),
);
return res;
} }
} }

34
packages/nocodb/src/models/MapView.ts

@ -6,6 +6,7 @@ import { extractProps } from '~/helpers/extractProps';
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco'; import Noco from '~/Noco';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';
export default class MapView implements MapType { export default class MapView implements MapType {
fk_view_id: string; fk_view_id: string;
@ -70,22 +71,8 @@ export default class MapView implements MapType {
body: Partial<MapView>, body: Partial<MapView>,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.MAP_VIEW}:${mapId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['fk_geo_data_col_id', 'meta']); const updateObj = extractProps(body, ['fk_geo_data_col_id', 'meta']);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
if (body.fk_geo_data_col_id != null) { if (body.fk_geo_data_col_id != null) {
const mapViewColumns = await MapViewColumn.list(mapId); const mapViewColumns = await MapViewColumn.list(mapId);
const mapViewMappedByColumn = mapViewColumns.find( const mapViewMappedByColumn = mapViewColumns.find(
@ -98,8 +85,21 @@ export default class MapView implements MapType {
} }
// update meta // update meta
return await ncMeta.metaUpdate(null, null, MetaTable.MAP_VIEW, updateObj, { const res = await ncMeta.metaUpdate(
fk_view_id: mapId, null,
}); null,
MetaTable.MAP_VIEW,
prepareForDb(updateObj),
{
fk_view_id: mapId,
},
);
await NocoCache.update(
`${CacheScope.MAP_VIEW}:${mapId}`,
prepareForResponse(updateObj),
);
return res;
} }
} }

136
packages/nocodb/src/models/Model.ts

@ -26,7 +26,11 @@ import {
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
import Noco from '~/Noco'; import Noco from '~/Noco';
import { BaseModelSqlv2 } from '~/db/BaseModelSqlv2'; import { BaseModelSqlv2 } from '~/db/BaseModelSqlv2';
import { parseMetaProp } from '~/utils/modelUtils'; import {
parseMetaProp,
prepareForDb,
prepareForResponse,
} from '~/utils/modelUtils';
export default class Model implements TableType { export default class Model implements TableType {
copy_enabled: BoolType; copy_enabled: BoolType;
@ -641,27 +645,8 @@ export default class Model implements TableType {
if (!table_name) { if (!table_name) {
NcError.badRequest("Missing 'table_name' property in body"); NcError.badRequest("Missing 'table_name' property in body");
} }
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
let oldModel = { ...o };
// update alias
if (o) {
o.title = title;
o.table_name = table_name;
// set cache
await NocoCache.set(key, o);
} else {
oldModel = await this.get(tableId);
}
// delete alias cache const oldModel = await this.get(tableId, ncMeta);
await NocoCache.del([
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.title}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.title}`,
]);
// set meta // set meta
const res = await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
@ -675,6 +660,19 @@ export default class Model implements TableType {
tableId, tableId,
); );
await NocoCache.update(`${CacheScope.MODEL}:${tableId}`, {
title,
table_name,
});
// delete alias cache
await NocoCache.del([
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.id}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.title}`,
`${CacheScope.MODEL_ALIAS}:${oldModel.base_id}:${oldModel.source_id}:${oldModel.title}`,
]);
// clear all the cached query under this model // clear all the cached query under this model
await View.clearSingleQueryCache(tableId); await View.clearSingleQueryCache(tableId);
@ -693,17 +691,8 @@ export default class Model implements TableType {
} }
static async markAsMmTable(tableId, isMm = true, ncMeta = Noco.ncMeta) { static async markAsMmTable(tableId, isMm = true, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o.mm = isMm;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.MODELS, MetaTable.MODELS,
@ -712,6 +701,12 @@ export default class Model implements TableType {
}, },
tableId, tableId,
); );
await NocoCache.update(`${CacheScope.MODEL}:${tableId}`, {
mm: isMm,
});
return res;
} }
async getAliasColMapping() { async getAliasColMapping() {
@ -737,16 +732,8 @@ export default class Model implements TableType {
order: number, order: number,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.order = order;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.MODELS, MetaTable.MODELS,
@ -755,6 +742,12 @@ export default class Model implements TableType {
}, },
tableId, tableId,
); );
await NocoCache.update(`${CacheScope.MODEL}:${tableId}`, {
order,
});
return res;
} }
static async updatePrimaryColumn( static async updatePrimaryColumn(
@ -769,14 +762,6 @@ export default class Model implements TableType {
// drop existing primary column/s // drop existing primary column/s
for (const col of model.columns?.filter((c) => c.pv) || []) { for (const col of model.columns?.filter((c) => c.pv) || []) {
// get existing cache
const key = `${CacheScope.COLUMN}:${col.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.pv = false;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -787,16 +772,12 @@ export default class Model implements TableType {
}, },
col.id, col.id,
); );
}
// get existing cache await NocoCache.update(`${CacheScope.COLUMN}:${col.id}`, {
const key = `${CacheScope.COLUMN}:${newPvCol.id}`; pv: false,
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); });
if (o) {
o.pv = true;
// set cache
await NocoCache.set(key, o);
} }
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -808,6 +789,10 @@ export default class Model implements TableType {
newPvCol.id, newPvCol.id,
); );
await NocoCache.update(`${CacheScope.COLUMN}:${newPvCol.id}`, {
pv: true,
});
const grid_views_with_column = await ncMeta.metaList2( const grid_views_with_column = await ncMeta.metaList2(
null, null,
null, null,
@ -829,14 +814,6 @@ export default class Model implements TableType {
} }
static async setAsMm(id: any, ncMeta = Noco.ncMeta) { static async setAsMm(id: any, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.MODEL}:${id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.mm = true;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -847,6 +824,10 @@ export default class Model implements TableType {
}, },
id, id,
); );
await NocoCache.update(`${CacheScope.MODEL}:${id}`, {
mm: true,
});
} }
static async getByAliasOrId( static async getByAliasOrId(
@ -976,26 +957,25 @@ export default class Model implements TableType {
meta: string | Record<string, any>, meta: string | Record<string, any>,
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const existingCache = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (existingCache) {
try {
existingCache.meta = typeof meta === 'string' ? JSON.parse(meta) : meta;
// set cache
await NocoCache.set(key, existingCache);
} catch {}
}
// set meta // set meta
return await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.MODELS, MetaTable.MODELS,
{ prepareForDb({
meta: typeof meta === 'object' ? JSON.stringify(meta) : meta, meta,
}, }),
tableId, tableId,
); );
await NocoCache.update(
`${CacheScope.MODEL}:${tableId}`,
prepareForResponse({
meta,
}),
);
return res;
} }
static async getNonDefaultViewsCountAndReset( static async getNonDefaultViewsCountAndReset(

20
packages/nocodb/src/models/ModelRoleVisibility.ts

@ -86,17 +86,8 @@ export default class ModelRoleVisibility implements ModelRoleVisibilityType {
role: string, role: string,
body: { disabled: any }, body: { disabled: any },
) { ) {
// get existing cache
const key = `${CacheScope.MODEL_ROLE_VISIBILITY}:${fk_view_id}:${role}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.disabled = body.disabled;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
return await Noco.ncMeta.metaUpdate( const res = await Noco.ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.MODEL_ROLE_VISIBILITY, MetaTable.MODEL_ROLE_VISIBILITY,
@ -108,6 +99,15 @@ export default class ModelRoleVisibility implements ModelRoleVisibilityType {
role, role,
}, },
); );
await NocoCache.update(
`${CacheScope.MODEL_ROLE_VISIBILITY}:${fk_view_id}:${role}`,
{
disabled: body.disabled,
},
);
return res;
} }
async delete() { async delete() {

13
packages/nocodb/src/models/Plugin.ts

@ -65,16 +65,6 @@ export default class Plugin implements PluginType {
updateObj.input = JSON.stringify(updateObj.input); updateObj.input = JSON.stringify(updateObj.input);
} }
// get existing cache
const key = `${CacheScope.PLUGIN}:${pluginId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
await NocoCache.set(`${CacheScope.PLUGIN}:${o.title}`, o);
}
// set meta // set meta
await Noco.ncMeta.metaUpdate( await Noco.ncMeta.metaUpdate(
null, null,
@ -84,6 +74,9 @@ export default class Plugin implements PluginType {
pluginId, pluginId,
); );
await NocoCache.update(`${CacheScope.PLUGIN}:${pluginId}`, updateObj);
await NocoCache.update(`${CacheScope.PLUGIN}:${plugin.title}`, updateObj);
return this.get(pluginId); return this.get(pluginId);
} }

15
packages/nocodb/src/models/Sort.ts

@ -148,16 +148,6 @@ export default class Sort {
} }
public static async update(sortId, body, ncMeta = Noco.ncMeta) { public static async update(sortId, body, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.SORT}:${sortId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update fk_column_id & direction
o.fk_column_id = body.fk_column_id;
o.direction = body.direction;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
const res = await ncMeta.metaUpdate( const res = await ncMeta.metaUpdate(
null, null,
@ -170,6 +160,11 @@ export default class Sort {
sortId, sortId,
); );
await NocoCache.update(`${CacheScope.SORT}:${sortId}`, {
fk_column_id: body.fk_column_id,
direction: body.direction,
});
// on update, delete any optimised single query cache // on update, delete any optimised single query cache
{ {
const sort = await this.get(sortId, ncMeta); const sort = await this.get(sortId, ncMeta);

46
packages/nocodb/src/models/Source.ts

@ -17,7 +17,12 @@ import Noco from '~/Noco';
import { extractProps } from '~/helpers/extractProps'; import { extractProps } from '~/helpers/extractProps';
import { NcError } from '~/helpers/catchError'; import { NcError } from '~/helpers/catchError';
import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2';
import { parseMetaProp, stringifyMetaProp } from '~/utils/modelUtils'; import {
parseMetaProp,
prepareForDb,
prepareForResponse,
stringifyMetaProp,
} from '~/utils/modelUtils';
// todo: hide credentials // todo: hide credentials
export default class Source implements SourceType { export default class Source implements SourceType {
@ -130,10 +135,6 @@ export default class Source implements SourceType {
).toString(); ).toString();
} }
if ('meta' in updateObj) {
updateObj.meta = stringifyMetaProp(updateObj);
}
// type property is undefined even if not provided // type property is undefined even if not provided
if (!updateObj.type) { if (!updateObj.type) {
updateObj.type = oldBase.type; updateObj.type = oldBase.type;
@ -143,11 +144,14 @@ export default class Source implements SourceType {
source.baseId, source.baseId,
null, null,
MetaTable.BASES, MetaTable.BASES,
updateObj, prepareForDb(updateObj),
oldBase.id, oldBase.id,
); );
await NocoCache.del(`${CacheScope.BASE}:${sourceId}`); await NocoCache.update(
`${CacheScope.BASE}:${sourceId}`,
prepareForResponse(updateObj),
);
// call before reorder to update cache // call before reorder to update cache
const returnBase = await this.get(oldBase.id, false, ncMeta); const returnBase = await this.get(oldBase.id, false, ncMeta);
@ -474,15 +478,7 @@ export default class Source implements SourceType {
if (!this.erd_uuid) { if (!this.erd_uuid) {
const uuid = uuidv4(); const uuid = uuidv4();
this.erd_uuid = uuid; this.erd_uuid = uuid;
// get existing cache
const key = `${CacheScope.BASE}:${this.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.erd_uuid = uuid;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -493,6 +489,10 @@ export default class Source implements SourceType {
}, },
this.id, this.id,
); );
await NocoCache.update(`${CacheScope.BASE}:${this.id}`, {
erd_uuid: this.erd_uuid,
});
} }
return this; return this;
} }
@ -500,15 +500,7 @@ export default class Source implements SourceType {
async disableShareErd(ncMeta = Noco.ncMeta) { async disableShareErd(ncMeta = Noco.ncMeta) {
if (this.erd_uuid) { if (this.erd_uuid) {
this.erd_uuid = null; this.erd_uuid = null;
// get existing cache
const key = `${CacheScope.BASE}:${this.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.erd_uuid = null;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -519,6 +511,10 @@ export default class Source implements SourceType {
}, },
this.id, this.id,
); );
await NocoCache.update(`${CacheScope.BASE}:${this.id}`, {
erd_uuid: this.erd_uuid,
});
} }
return this; return this;
} }

129
packages/nocodb/src/models/View.ts

@ -26,7 +26,12 @@ import {
MetaTable, MetaTable,
} from '~/utils/globals'; } from '~/utils/globals';
import Noco from '~/Noco'; import Noco from '~/Noco';
import { parseMetaProp, stringifyMetaProp } from '~/utils/modelUtils'; import {
parseMetaProp,
prepareForDb,
prepareForResponse,
stringifyMetaProp,
} from '~/utils/modelUtils';
const { v4: uuidv4 } = require('uuid'); const { v4: uuidv4 } = require('uuid');
@ -858,18 +863,11 @@ export default class View implements ViewType {
} }
} }
// get existing cache
const key = `${cacheScope}:${colId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
const res = await ncMeta.metaUpdate(null, null, table, updateObj, colId); const res = await ncMeta.metaUpdate(null, null, table, updateObj, colId);
await NocoCache.update(`${cacheScope}:${colId}`, updateObj);
// on view column update, delete corresponding single query cache // on view column update, delete corresponding single query cache
await View.clearSingleQueryCache(view.fk_model_id, [view]); await View.clearSingleQueryCache(view.fk_model_id, [view]);
@ -988,15 +986,7 @@ export default class View implements ViewType {
if (!view.uuid) { if (!view.uuid) {
const uuid = uuidv4(); const uuid = uuidv4();
view.uuid = uuid; view.uuid = uuid;
// get existing cache
const key = `${CacheScope.VIEW}:${view.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.uuid = uuid;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -1007,32 +997,35 @@ export default class View implements ViewType {
}, },
viewId, viewId,
); );
await NocoCache.update(`${CacheScope.VIEW}:${view.id}`, {
uuid: view.uuid,
});
} }
if (!view.meta || !('allowCSVDownload' in view.meta)) { if (!view.meta || !('allowCSVDownload' in view.meta)) {
const defaultMeta = { const defaultMeta = {
...(view.meta ?? {}), ...(view.meta ?? {}),
allowCSVDownload: true, allowCSVDownload: true,
}; };
// get existing cache view.meta = defaultMeta;
const key = `${CacheScope.VIEW}:${view.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.meta = defaultMeta;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
null, null,
MetaTable.VIEWS, MetaTable.VIEWS,
{ prepareForDb({
meta: JSON.stringify(defaultMeta), meta: defaultMeta,
}, }),
viewId, viewId,
); );
view.meta = defaultMeta;
await NocoCache.update(
`${CacheScope.VIEW}:${view.id}`,
prepareForResponse({
meta: defaultMeta,
}),
);
} }
return view; return view;
} }
@ -1042,15 +1035,6 @@ export default class View implements ViewType {
{ password }: { password: string }, { password }: { password: string },
ncMeta = Noco.ncMeta, ncMeta = Noco.ncMeta,
) { ) {
// get existing cache
const key = `${CacheScope.VIEW}:${viewId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.password = password;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -1061,18 +1045,13 @@ export default class View implements ViewType {
}, },
viewId, viewId,
); );
await NocoCache.update(`${CacheScope.VIEW}:${viewId}`, {
password,
});
} }
static async sharedViewDelete(viewId, ncMeta = Noco.ncMeta) { static async sharedViewDelete(viewId, ncMeta = Noco.ncMeta) {
// get existing cache
const key = `${CacheScope.VIEW}:${viewId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
// update data
o.uuid = null;
// set cache
await NocoCache.set(key, o);
}
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
null, null,
@ -1083,6 +1062,10 @@ export default class View implements ViewType {
}, },
viewId, viewId,
); );
await NocoCache.update(`${CacheScope.VIEW}:${viewId}`, {
uuid: null,
});
} }
static async update( static async update(
@ -1108,37 +1091,33 @@ export default class View implements ViewType {
'uuid', 'uuid',
]); ]);
// get existing cache const oldView = await this.get(viewId, ncMeta);
const key = `${CacheScope.VIEW}:${viewId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); // set meta
let oldView = { ...o }; await ncMeta.metaUpdate(
if (o) { null,
// update data null,
o = { MetaTable.VIEWS,
...o, prepareForDb(updateObj),
...updateObj, viewId,
}; );
if (o.is_default) {
await NocoCache.set(`${CacheScope.VIEW}:${o.fk_model_id}:default`, o);
}
// set cache
await NocoCache.set(key, o);
} else {
oldView = await this.get(viewId);
}
// reset alias cache // reset alias cache
await NocoCache.del( await NocoCache.del(
`${CacheScope.VIEW}:${oldView.fk_model_id}:${oldView.title}`, `${CacheScope.VIEW}:${oldView.fk_model_id}:${oldView.title}`,
); );
// if meta data defined then stringify it await NocoCache.update(
if ('meta' in updateObj) { `${CacheScope.VIEW}:${viewId}`,
updateObj.meta = stringifyMetaProp(updateObj); prepareForResponse(updateObj),
} );
// set meta if (oldView.is_default) {
await ncMeta.metaUpdate(null, null, MetaTable.VIEWS, updateObj, viewId); await NocoCache.update(
`${CacheScope.VIEW}:${oldView.fk_model_id}:default`,
prepareForResponse(updateObj),
);
}
const view = await this.get(viewId); const view = await this.get(viewId);
@ -1407,7 +1386,7 @@ export default class View implements ViewType {
MetaTable.COLUMNS, MetaTable.COLUMNS,
col.fk_column_id, col.fk_column_id,
); );
view_columns_meta.push(col_meta); if (col_meta) view_columns_meta.push(col_meta);
} }
const primary_value_column_meta = view_columns_meta.find((col) => col.pv); const primary_value_column_meta = view_columns_meta.find((col) => col.pv);

7
packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts

@ -515,6 +515,8 @@ export class ExportService {
if (hasLink) { if (hasLink) {
linkStream.setEncoding('utf8'); linkStream.setEncoding('utf8');
let streamedHeaders = false;
for (const mm of mmColumns) { for (const mm of mmColumns) {
if (handledMmList.includes(mm.colOptions?.fk_mm_model_id)) continue; if (handledMmList.includes(mm.colOptions?.fk_mm_model_id)) continue;
@ -573,8 +575,11 @@ export class ExportService {
mmOffset, mmOffset,
mmLimit, mmLimit,
mmFields, mmFields,
true, streamedHeaders ? false : true,
); );
// avoid writing headers for same model multiple times
streamedHeaders = true;
} catch (e) { } catch (e) {
this.debugLog(e); this.debugLog(e);
throw e; throw e;

11
packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts

@ -1,5 +1,5 @@
import { isLinksOrLTAR, isVirtualCol, UITypes, ViewTypes } from 'nocodb-sdk'; import { isLinksOrLTAR, isVirtualCol, UITypes, ViewTypes } from 'nocodb-sdk';
import { Injectable } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import papaparse from 'papaparse'; import papaparse from 'papaparse';
import debug from 'debug'; import debug from 'debug';
import { elapsedTime, initTime } from '../../helpers'; import { elapsedTime, initTime } from '../../helpers';
@ -44,7 +44,8 @@ import { sanitizeColumnName } from '~/helpers';
@Injectable() @Injectable()
export class ImportService { export class ImportService {
private readonly debugLog = debug('nc:jobs:import'); protected readonly debugLog = debug('nc:jobs:import');
protected readonly logger = new Logger(ImportService.name);
constructor( constructor(
private tablesService: TablesService, private tablesService: TablesService,
@ -1515,7 +1516,7 @@ export class ImportService {
raw: true, raw: true,
}); });
} catch (e) { } catch (e) {
this.debugLog(e); this.logger.error(e);
} }
chunk = []; chunk = [];
parser.resume(); parser.resume();
@ -1536,7 +1537,7 @@ export class ImportService {
raw: true, raw: true,
}); });
} catch (e) { } catch (e) {
this.debugLog(e); this.logger.error(e);
} }
chunk = []; chunk = [];
} }
@ -1573,7 +1574,7 @@ export class ImportService {
}); });
lChunks[k] = []; lChunks[k] = [];
} catch (e) { } catch (e) {
this.debugLog(e); this.logger.error(e);
} }
} }
}; };

35
packages/nocodb/src/utils/modelUtils.ts

@ -23,3 +23,38 @@ export function stringifyMetaProp(model: any, propName = 'meta'): string {
return '{}'; return '{}';
} }
} }
export function prepareForDb(model: any, props: string | string[] = 'meta') {
if (!model) return model;
if (typeof props === 'string') {
props = [props];
}
props.forEach((prop) => {
if (prop in model) {
model[prop] = stringifyMetaProp(model, prop);
}
});
return model;
}
export function prepareForResponse(
model: any,
props: string | string[] = 'meta',
) {
if (!model) return model;
if (typeof props === 'string') {
props = [props];
}
props.forEach((prop) => {
if (prop in model) {
model[prop] = parseMetaProp(model, prop);
}
});
return model;
}

Loading…
Cancel
Save