mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Cache column info (#19480)
* Cache column info * checked if cache is enabled * formatting * temp activation of bb tests * deactivated bb tests again * used schema cache configuration * changeset * changeset wording * switched to schema cache --------- Co-authored-by: Jan Arends <jan.arends@mailbox.org>
This commit is contained in:
5
.changeset/dirty-rings-greet.md
Normal file
5
.changeset/dirty-rings-greet.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@directus/api': minor
|
||||
---
|
||||
|
||||
Enabled caching of field information as part of schema caching
|
||||
@@ -12,7 +12,7 @@ import { addFieldFlag, toArray } from '@directus/utils';
|
||||
import type Keyv from 'keyv';
|
||||
import type { Knex } from 'knex';
|
||||
import { isEqual, isNil, merge } from 'lodash-es';
|
||||
import { clearSystemCache, getCache } from '../cache.js';
|
||||
import { clearSystemCache, getCache, getCacheValue, setCacheValue } from '../cache.js';
|
||||
import { ALIAS_TYPES } from '../constants.js';
|
||||
import { translateDatabaseError } from '../database/errors/translate.js';
|
||||
import type { Helpers } from '../database/helpers/index.js';
|
||||
@@ -30,8 +30,10 @@ import { transaction } from '../utils/transaction.js';
|
||||
import { ItemsService } from './items.js';
|
||||
import { PayloadService } from './payload.js';
|
||||
import { RelationsService } from './relations.js';
|
||||
import { useEnv } from '@directus/env';
|
||||
|
||||
const systemFieldRows = getSystemFieldRowsWithAuthProviders();
|
||||
const env = useEnv();
|
||||
|
||||
export class FieldsService {
|
||||
knex: Knex;
|
||||
@@ -43,6 +45,7 @@ export class FieldsService {
|
||||
schema: SchemaOverview;
|
||||
cache: Keyv<any> | null;
|
||||
systemCache: Keyv<any>;
|
||||
schemaCache: Keyv<any>;
|
||||
|
||||
constructor(options: AbstractServiceOptions) {
|
||||
this.knex = options.knex || getDatabase();
|
||||
@@ -53,10 +56,11 @@ export class FieldsService {
|
||||
this.payloadService = new PayloadService('directus_fields', options);
|
||||
this.schema = options.schema;
|
||||
|
||||
const { cache, systemCache } = getCache();
|
||||
const { cache, systemCache, localSchemaCache } = getCache();
|
||||
|
||||
this.cache = cache;
|
||||
this.systemCache = systemCache;
|
||||
this.schemaCache = localSchemaCache;
|
||||
}
|
||||
|
||||
private get hasReadAccess() {
|
||||
@@ -65,6 +69,36 @@ export class FieldsService {
|
||||
});
|
||||
}
|
||||
|
||||
async columnInfo(collection?: string): Promise<Column[]>;
|
||||
async columnInfo(collection: string, field: string): Promise<Column>;
|
||||
async columnInfo(collection?: string, field?: string): Promise<Column | Column[]> {
|
||||
const schemaCacheIsEnabled = Boolean(env['CACHE_SCHEMA']);
|
||||
|
||||
let columnInfo: Column[] | null = null;
|
||||
|
||||
if (schemaCacheIsEnabled) {
|
||||
columnInfo = await getCacheValue(this.schemaCache, 'columnInfo');
|
||||
}
|
||||
|
||||
if (!columnInfo) {
|
||||
columnInfo = await this.schemaInspector.columnInfo();
|
||||
|
||||
if (schemaCacheIsEnabled) {
|
||||
setCacheValue(this.schemaCache, 'columnInfo', columnInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (collection) {
|
||||
columnInfo = columnInfo.filter((column) => column.table === collection);
|
||||
}
|
||||
|
||||
if (field) {
|
||||
return columnInfo.find((column) => column.name === field) as Column;
|
||||
}
|
||||
|
||||
return columnInfo;
|
||||
}
|
||||
|
||||
async readAll(collection?: string): Promise<Field[]> {
|
||||
let fields: FieldMeta[];
|
||||
|
||||
@@ -89,7 +123,7 @@ export class FieldsService {
|
||||
fields.push(...systemFieldRows);
|
||||
}
|
||||
|
||||
const columns = (await this.schemaInspector.columnInfo(collection)).map((column) => ({
|
||||
const columns = (await this.columnInfo(collection)).map((column) => ({
|
||||
...column,
|
||||
default_value: getDefaultValue(
|
||||
column,
|
||||
@@ -227,7 +261,7 @@ export class FieldsService {
|
||||
systemFieldRows.find((fieldMeta) => fieldMeta.collection === collection && fieldMeta.field === field);
|
||||
|
||||
try {
|
||||
column = await this.schemaInspector.columnInfo(collection, field);
|
||||
column = await this.columnInfo(collection, field);
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
@@ -430,7 +464,7 @@ export class FieldsService {
|
||||
}
|
||||
|
||||
if (hookAdjustedField.schema) {
|
||||
const existingColumn = await this.schemaInspector.columnInfo(collection, hookAdjustedField.field);
|
||||
const existingColumn = await this.columnInfo(collection, hookAdjustedField.field);
|
||||
|
||||
if (hookAdjustedField.schema?.is_nullable === true && existingColumn.is_primary_key) {
|
||||
throw new InvalidPayloadError({ reason: 'Primary key cannot be null' });
|
||||
|
||||
Reference in New Issue
Block a user