From fdd3e922e8bfda78a5c9661bc13406183ba2a5cc Mon Sep 17 00:00:00 2001 From: dineug Date: Sun, 14 Jan 2024 17:23:21 +0900 Subject: [PATCH] fix: schema gc --- packages/erd-editor-vscode/src/utils/text.ts | 12 +- .../src/components/erd-editor/ErdEditor.ts | 2 + .../src/engine/modules/editor/actions.ts | 2 + .../src/engine/modules/editor/atom.actions.ts | 76 ++++++++ .../src/engine/replication-store.ts | 2 + .../src/services/schema-gc/schemaGCService.ts | 165 ++++++++---------- 6 files changed, 166 insertions(+), 93 deletions(-) diff --git a/packages/erd-editor-vscode/src/utils/text.ts b/packages/erd-editor-vscode/src/utils/text.ts index 2773d4dd..7ce4448d 100644 --- a/packages/erd-editor-vscode/src/utils/text.ts +++ b/packages/erd-editor-vscode/src/utils/text.ts @@ -23,10 +23,14 @@ export function toWidth(text: string) { let width = 0; if (font) { - const glyphs = font.stringToGlyphs(text); - const advance = glyphs.reduce((acc, g) => acc + (g.advanceWidth ?? 0), 0); - - width = (advance / font.unitsPerEm) * SIZE; + try { + const glyphs = font.stringToGlyphs(text); + const advance = glyphs.reduce((acc, g) => acc + (g.advanceWidth ?? 0), 0); + + width = (advance / font.unitsPerEm) * SIZE; + } catch { + width = text.length * 10; + } } else { width = text.length * 10; } diff --git a/packages/erd-editor/src/components/erd-editor/ErdEditor.ts b/packages/erd-editor/src/components/erd-editor/ErdEditor.ts index a4a68812..c01e2895 100644 --- a/packages/erd-editor/src/components/erd-editor/ErdEditor.ts +++ b/packages/erd-editor/src/components/erd-editor/ErdEditor.ts @@ -31,6 +31,7 @@ import { DatabaseVendor } from '@/constants/sql/database'; import { changeOpenMapAction, changeViewportAction, + validationIdsAction, } from '@/engine/modules/editor/atom.actions'; import { SharedStore, SharedStoreConfig } from '@/engine/shared-store'; import { useKeyBindingMap } from '@/hooks/useKeyBindingMap'; @@ -178,6 +179,7 @@ const ErdEditor: FC = (props, ctx) => { if (isChange) { procGC(store.state, gcIds); + store.dispatchSync(validationIdsAction()); ctx.dispatchEvent(new CustomEvent('change')); } }); diff --git a/packages/erd-editor/src/engine/modules/editor/actions.ts b/packages/erd-editor/src/engine/modules/editor/actions.ts index 8e2da7cd..47331e31 100644 --- a/packages/erd-editor/src/engine/modules/editor/actions.ts +++ b/packages/erd-editor/src/engine/modules/editor/actions.ts @@ -32,6 +32,7 @@ export const ActionType = { dragstartColumn: 'editor.dragstartColumn', dragendColumn: 'editor.dragendColumn', sharedMouseTracker: 'editor.sharedMouseTracker', + validationIds: 'editor.validationIds', } as const; export type ActionType = ValuesType; @@ -98,6 +99,7 @@ export type ActionMap = { x: number; y: number; }; + [ActionType.validationIds]: void; }; export type ReducerType = Reducer< diff --git a/packages/erd-editor/src/engine/modules/editor/atom.actions.ts b/packages/erd-editor/src/engine/modules/editor/atom.actions.ts index 8fdad6d0..6217aeae 100644 --- a/packages/erd-editor/src/engine/modules/editor/atom.actions.ts +++ b/packages/erd-editor/src/engine/modules/editor/atom.actions.ts @@ -510,6 +510,80 @@ const sharedMouseTracker: ReducerType = ( } }; +export const validationIdsAction = createAction< + ActionMap[typeof ActionType.validationIds] +>(ActionType.validationIds); + +const validationIds: ReducerType = ({ + doc, + collections, +}) => { + const tableCollection = query(collections).collection('tableEntities'); + const tableColumnCollection = query(collections).collection( + 'tableColumnEntities' + ); + const indexCollection = query(collections).collection('indexEntities'); + const indexColumnCollection = query(collections).collection( + 'indexColumnEntities' + ); + const relationshipCollection = query(collections).collection( + 'relationshipEntities' + ); + const memoCollection = query(collections).collection('memoEntities'); + + const invalidTableIds = doc.tableIds.filter( + id => !tableCollection.selectById(id) + ); + const invalidRelationshipIds = doc.relationshipIds.filter( + id => !relationshipCollection.selectById(id) + ); + const invalidIndexIds = doc.indexIds.filter( + id => !indexCollection.selectById(id) + ); + const invalidMemoIds = doc.memoIds.filter( + id => !memoCollection.selectById(id) + ); + + doc.tableIds = doc.tableIds.filter(id => !invalidTableIds.includes(id)); + doc.relationshipIds = doc.relationshipIds.filter( + id => !invalidRelationshipIds.includes(id) + ); + doc.indexIds = doc.indexIds.filter(id => !invalidIndexIds.includes(id)); + doc.memoIds = doc.memoIds.filter(id => !invalidMemoIds.includes(id)); + + tableCollection.selectAll().forEach(table => { + const invalidColumnIds = table.columnIds.filter( + id => !tableColumnCollection.selectById(id) + ); + const invalidSeqColumnIds = table.seqColumnIds.filter( + id => !tableColumnCollection.selectById(id) + ); + + table.columnIds = table.columnIds.filter( + id => !invalidColumnIds.includes(id) + ); + table.seqColumnIds = table.seqColumnIds.filter( + id => !invalidSeqColumnIds.includes(id) + ); + }); + + indexCollection.selectAll().forEach(index => { + const invalidIndexColumnIds = index.indexColumnIds.filter( + id => !indexColumnCollection.selectById(id) + ); + const invalidSeqIndexColumnIds = index.seqIndexColumnIds.filter( + id => !indexColumnCollection.selectById(id) + ); + + index.indexColumnIds = index.indexColumnIds.filter( + id => !invalidIndexColumnIds.includes(id) + ); + index.seqIndexColumnIds = index.seqIndexColumnIds.filter( + id => !invalidSeqIndexColumnIds.includes(id) + ); + }); +}; + export const editorReducers = { [ActionType.changeHasHistory]: changeHasHistory, [ActionType.selectAll]: selectAll, @@ -536,6 +610,7 @@ export const editorReducers = { [ActionType.dragstartColumn]: dragstartColumn, [ActionType.dragendColumn]: dragendColumn, [ActionType.sharedMouseTracker]: sharedMouseTracker, + [ActionType.validationIds]: validationIds, }; export const actions = { @@ -564,4 +639,5 @@ export const actions = { dragstartColumnAction, dragendColumnAction, sharedMouseTrackerAction, + validationIdsAction, }; diff --git a/packages/erd-editor/src/engine/replication-store.ts b/packages/erd-editor/src/engine/replication-store.ts index b6af2154..52736cf9 100644 --- a/packages/erd-editor/src/engine/replication-store.ts +++ b/packages/erd-editor/src/engine/replication-store.ts @@ -6,6 +6,7 @@ import { debounceTime, map, Observable, Subject, Subscription } from 'rxjs'; import { ChangeActionTypes } from '@/engine/actions'; import { EngineContext } from '@/engine/context'; +import { validationIdsAction } from '@/engine/modules/editor/atom.actions'; import { initialLoadJsonAction$ } from '@/engine/modules/editor/generator.actions'; import { actionsFilter } from '@/engine/rx-operators'; import { createStore } from '@/engine/store'; @@ -83,6 +84,7 @@ export function createReplicationStore( if (isChange) { procGC(store.state, gcIds); + store.dispatchSync(validationIdsAction()); emit(InternalActionType.change, undefined); } }); diff --git a/packages/erd-editor/src/services/schema-gc/schemaGCService.ts b/packages/erd-editor/src/services/schema-gc/schemaGCService.ts index 671b8f14..eaafee8d 100644 --- a/packages/erd-editor/src/services/schema-gc/schemaGCService.ts +++ b/packages/erd-editor/src/services/schema-gc/schemaGCService.ts @@ -1,13 +1,12 @@ import { query, schemaV3Parser } from '@dineug/erd-editor-schema'; import { arrayHas } from '@dineug/shared'; -import { uniq } from 'lodash-es'; import { DateTime } from 'luxon'; import type { GCIds } from '@/services/schema-gc'; import { procGC } from './procGC'; -const GC_DAYS = 30; +const GC_DAYS = 3; const hasCollectionKey = arrayHas([ 'tableEntities', 'tableColumnEntities', @@ -46,76 +45,68 @@ export class SchemaGCService { ); const memoCollection = query(collections).collection('memoEntities'); - const gcIds: GCIds = { - tableIds: [ - ...tableCollection - .selectAll() - .filter(isGC(hasTableIds)) - .map(({ id }) => id), - ], - tableColumnIds: [], - relationshipIds: [ - ...relationshipCollection - .selectAll() - .filter(isGC(hasRelationshipIds)) - .map(({ id }) => id), - ], - indexIds: [ - ...indexCollection - .selectAll() - .filter(isGC(hasIndexIds)) - .map(({ id }) => id), - ], - indexColumnIds: [], - memoIds: [ - ...memoCollection - .selectAll() - .filter(isGC(hasMemoIds)) - .map(({ id }) => id), - ], - }; - - const hasGCTableIds = arrayHas(gcIds.tableIds); - const hasGCRelationshipIds = arrayHas(gcIds.relationshipIds); - let hasGCIndexIds = arrayHas(gcIds.indexIds); - - gcIds.tableColumnIds.push( - ...tableColumnCollection + const gcTableIdsSet = new Set( + tableCollection .selectAll() - .filter(({ tableId }) => hasGCTableIds(tableId)) + .filter(isGC(hasTableIds)) .map(({ id }) => id) ); - - gcIds.relationshipIds.push( - ...relationshipCollection + const gcTableColumnIdsSet = new Set(); + const gcRelationshipIdsSet = new Set( + relationshipCollection .selectAll() - .filter( - ({ id, start, end }) => - !hasGCRelationshipIds(id) && - (hasGCTableIds(start.tableId) || hasGCTableIds(end.tableId)) - ) + .filter(isGC(hasRelationshipIds)) .map(({ id }) => id) ); - - gcIds.indexIds.push( - ...indexCollection + const gcIndexIdsSet = new Set( + indexCollection .selectAll() - .filter( - ({ id, tableId }) => !hasGCIndexIds(id) && hasGCTableIds(tableId) - ) + .filter(isGC(hasIndexIds)) .map(({ id }) => id) ); - - hasGCIndexIds = arrayHas(gcIds.indexIds); - - gcIds.indexColumnIds.push( - ...indexColumnCollection + const gcIndexColumnIdsSet = new Set(); + const gcMemoIdsSet = new Set( + memoCollection .selectAll() - .filter(({ indexId }) => hasGCIndexIds(indexId)) + .filter(isGC(hasMemoIds)) .map(({ id }) => id) ); - procGC(state, gcIds); + tableColumnCollection + .selectAll() + .filter(({ tableId }) => gcTableIdsSet.has(tableId)) + .forEach(({ id }) => gcTableColumnIdsSet.add(id)); + + relationshipCollection + .selectAll() + .filter( + ({ id, start, end }) => + !gcRelationshipIdsSet.has(id) && + (gcTableIdsSet.has(start.tableId) || gcTableIdsSet.has(end.tableId)) + ) + .forEach(({ id }) => gcRelationshipIdsSet.add(id)); + + indexCollection + .selectAll() + .filter( + ({ id, tableId }) => + !gcIndexIdsSet.has(id) && gcTableIdsSet.has(tableId) + ) + .forEach(({ id }) => gcIndexIdsSet.add(id)); + + indexColumnCollection + .selectAll() + .filter(({ indexId }) => gcIndexIdsSet.has(indexId)) + .forEach(({ id }) => gcIndexColumnIdsSet.add(id)); + + procGC(state, { + tableIds: [...gcTableIdsSet], + tableColumnIds: [...gcTableColumnIdsSet], + relationshipIds: [...gcRelationshipIdsSet], + indexIds: [...gcIndexIdsSet], + indexColumnIds: [...gcIndexColumnIdsSet], + memoIds: [...gcMemoIdsSet], + }); const hasTableIdsAll = arrayHas( tableCollection.selectAll().map(({ id }) => id) @@ -136,58 +127,54 @@ export class SchemaGCService { memoCollection.selectAll().map(({ id }) => id) ); - gcIds.tableColumnIds.push( - ...tableColumnCollection - .selectAll() - .filter( - ({ tableId, id, meta }) => - !hasTableIdsAll(tableId) && isGC(() => false)({ id, meta }) - ) - .map(({ id }) => id) - ); + tableColumnCollection + .selectAll() + .filter( + ({ tableId, id, meta }) => + !hasTableIdsAll(tableId) && isGC(() => false)({ id, meta }) + ) + .forEach(({ id }) => gcTableColumnIdsSet.add(id)); - gcIds.indexColumnIds.push( - ...indexColumnCollection - .selectAll() - .filter( - ({ indexId, id, meta }) => - !hasIndexIdsAll(indexId) && isGC(() => false)({ id, meta }) - ) - .map(({ id }) => id) - ); + indexColumnCollection + .selectAll() + .filter( + ({ indexId, id, meta }) => + !hasIndexIdsAll(indexId) && isGC(() => false)({ id, meta }) + ) + .forEach(({ id }) => gcIndexColumnIdsSet.add(id)); Object.entries(lww).forEach(([id, [key]]) => { if (!hasCollectionKey(key)) return; switch (key) { case 'tableEntities': - !hasTableIdsAll(id) && gcIds.tableIds.push(id); + !hasTableIdsAll(id) && gcTableIdsSet.add(id); break; case 'tableColumnEntities': - !hasTableColumnIdsAll(id) && gcIds.tableColumnIds.push(id); + !hasTableColumnIdsAll(id) && gcTableColumnIdsSet.add(id); break; case 'relationshipEntities': - !hasRelationshipIdsAll(id) && gcIds.relationshipIds.push(id); + !hasRelationshipIdsAll(id) && gcRelationshipIdsSet.add(id); break; case 'indexEntities': - !hasIndexIdsAll(id) && gcIds.indexIds.push(id); + !hasIndexIdsAll(id) && gcIndexIdsSet.add(id); break; case 'indexColumnEntities': - !hasIndexColumnIdsAll(id) && gcIds.indexColumnIds.push(id); + !hasIndexColumnIdsAll(id) && gcIndexColumnIdsSet.add(id); break; case 'memoEntities': - !hasMemoIdsAll(id) && gcIds.memoIds.push(id); + !hasMemoIdsAll(id) && gcMemoIdsSet.add(id); break; } }); return { - tableIds: uniq(gcIds.tableIds), - tableColumnIds: uniq(gcIds.tableColumnIds), - relationshipIds: uniq(gcIds.relationshipIds), - indexIds: uniq(gcIds.indexIds), - indexColumnIds: uniq(gcIds.indexColumnIds), - memoIds: uniq(gcIds.memoIds), + tableIds: [...gcTableIdsSet], + tableColumnIds: [...gcTableColumnIdsSet], + relationshipIds: [...gcRelationshipIdsSet], + indexIds: [...gcIndexIdsSet], + indexColumnIds: [...gcIndexColumnIdsSet], + memoIds: [...gcMemoIdsSet], }; } }