@@ -947,6 +947,7 @@ export class FieldOpenApiService {
947947 oldField,
948948 modifiedOps,
949949 supplementChange,
950+ dependentFieldIds,
950951 } : {
951952 tableId : string ;
952953 newField : IFieldInstance ;
@@ -957,6 +958,7 @@ export class FieldOpenApiService {
957958 newField : IFieldInstance ;
958959 oldField : IFieldInstance ;
959960 } ;
961+ dependentFieldIds ?: string [ ] ;
960962 } ) : Promise < { compatibilityIssue : boolean } > {
961963 let encounteredCompatibilityIssue = false ;
962964
@@ -983,19 +985,47 @@ export class FieldOpenApiService {
983985 }
984986 } ;
985987
988+ const sourceMap = new Map < string , Set < string > > ( ) ;
989+ const shouldRecomputeSelf = this . fieldConvertingService . needCalculate ( newField , oldField ) ;
990+ const addSource = ( tid : string , fieldIds : string [ ] ) => {
991+ const set = sourceMap . get ( tid ) ?? new Set < string > ( ) ;
992+ fieldIds . forEach ( ( id ) => set . add ( id ) ) ;
993+ sourceMap . set ( tid , set ) ;
994+ } ;
995+
996+ if ( shouldRecomputeSelf ) {
997+ addSource ( tableId , [ newField . id ] ) ;
998+ }
999+
1000+ if ( dependentFieldIds ?. length ) {
1001+ const dependentFields = await this . prismaService . field . findMany ( {
1002+ where : { id : { in : dependentFieldIds } , deletedTime : null } ,
1003+ select : { id : true , tableId : true } ,
1004+ } ) ;
1005+ dependentFields
1006+ . filter (
1007+ ( { id, tableId : depTableId } ) =>
1008+ shouldRecomputeSelf || id !== newField . id || depTableId !== tableId
1009+ )
1010+ . forEach ( ( { id, tableId : depTableId } ) => addSource ( depTableId , [ id ] ) ) ;
1011+ }
1012+
1013+ if ( supplementChange ) {
1014+ addSource ( supplementChange . tableId , [ supplementChange . newField . id ] ) ;
1015+ }
1016+
1017+ const sources = Array . from ( sourceMap . entries ( ) ) . map ( ( [ tid , ids ] ) => ( {
1018+ tableId : tid ,
1019+ fieldIds : Array . from ( ids ) ,
1020+ } ) ) ;
1021+ const hasSources = sources . length > 0 ;
1022+
9861023 // 1. stage close constraint
9871024 await this . fieldConvertingService . closeConstraint ( tableId , newField , oldField ) ;
9881025
9891026 // 2. stage alter + apply record changes and calculate field with computed publishing (atomic)
9901027 await this . prismaService . $tx (
9911028 async ( ) => {
992- const sources = [ { tableId, fieldIds : [ newField . id ] } ] ;
993- if ( supplementChange )
994- sources . push ( {
995- tableId : supplementChange . tableId ,
996- fieldIds : [ supplementChange . newField . id ] ,
997- } ) ;
998-
9991029 const runCompute = async ( ) => {
10001030 // Update dependencies and schema first so evaluate() sees new schema
10011031 await this . fieldViewSyncService . convertDependenciesByFieldIds (
@@ -1027,14 +1057,19 @@ export class FieldOpenApiService {
10271057 }
10281058 } ;
10291059
1030- try {
1031- await this . computedOrchestrator . computeCellChangesForFields ( sources , runCompute ) ;
1032- } catch ( error ) {
1033- if ( this . isFieldReferenceCompatibilityError ( error ) ) {
1034- encounteredCompatibilityIssue = true ;
1035- return ;
1060+ if ( hasSources ) {
1061+ try {
1062+ await this . computedOrchestrator . computeCellChangesForFields ( sources , runCompute ) ;
1063+ } catch ( error ) {
1064+ if ( this . isFieldReferenceCompatibilityError ( error ) ) {
1065+ encounteredCompatibilityIssue = true ;
1066+ return ;
1067+ }
1068+
1069+ throw error ;
10361070 }
1037- throw error ;
1071+ } else {
1072+ await runCompute ( ) ;
10381073 }
10391074 } ,
10401075 { timeout : this . thresholdConfig . bigTransactionTimeout }
@@ -1086,12 +1121,26 @@ export class FieldOpenApiService {
10861121 const { newField, oldField, modifiedOps, supplementChange, references } =
10871122 await this . fieldConvertingService . stageAnalysis ( tableId , fieldId , updateFieldRo ) ;
10881123
1124+ const dependentRefs = await this . prismaService . reference . findMany ( {
1125+ where : { fromFieldId : fieldId } ,
1126+ select : { toFieldId : true } ,
1127+ } ) ;
1128+ const dependentFieldIds = Array . from (
1129+ new Set ( [ ...( references ?? [ ] ) , ...dependentRefs . map ( ( ref ) => ref . toFieldId ) ] )
1130+ ) ;
1131+
1132+ const shouldRecomputeSelf = this . fieldConvertingService . needCalculate ( newField , oldField ) ;
1133+ const filteredDependentFieldIds = shouldRecomputeSelf
1134+ ? dependentFieldIds
1135+ : dependentFieldIds . filter ( ( id ) => id !== newField . id ) ;
1136+
10891137 const { compatibilityIssue } = await this . performConvertField ( {
10901138 tableId,
10911139 newField,
10921140 oldField,
10931141 modifiedOps,
10941142 supplementChange,
1143+ dependentFieldIds : filteredDependentFieldIds ,
10951144 } ) ;
10961145
10971146 const shouldForceLookupError =
@@ -1102,20 +1151,37 @@ export class FieldOpenApiService {
11021151 ( ( newField . options as ILinkFieldOptions | undefined ) ?. foreignTableId ?? null ) !==
11031152 ( ( oldField . options as ILinkFieldOptions | undefined ) ?. foreignTableId ?? null ) ) ;
11041153
1105- const dependentRefs = await this . prismaService . reference . findMany ( {
1106- where : { fromFieldId : fieldId } ,
1107- select : { toFieldId : true } ,
1108- } ) ;
1109- const dependentFieldIds = Array . from (
1110- new Set ( [ ...( references ?? [ ] ) , ...dependentRefs . map ( ( ref ) => ref . toFieldId ) ] )
1111- ) ;
1112-
1113- if ( dependentFieldIds . length ) {
1154+ if ( filteredDependentFieldIds . length ) {
11141155 try {
1115- await this . restoreReference ( dependentFieldIds ) ;
1156+ await this . restoreReference ( filteredDependentFieldIds ) ;
11161157 const dependentFieldRaws = await this . prismaService . field . findMany ( {
1117- where : { id : { in : dependentFieldIds } , deletedTime : null } ,
1158+ where : { id : { in : filteredDependentFieldIds } , deletedTime : null } ,
11181159 } ) ;
1160+
1161+ if ( dependentFieldRaws . length ) {
1162+ const dependentSourceMap = dependentFieldRaws . reduce < Record < string , Set < string > > > (
1163+ ( acc , field ) => {
1164+ const set = acc [ field . tableId ] ?? new Set < string > ( ) ;
1165+ set . add ( field . id ) ;
1166+ acc [ field . tableId ] = set ;
1167+ return acc ;
1168+ } ,
1169+ { }
1170+ ) ;
1171+ const dependentSources = Object . entries ( dependentSourceMap ) . map ( ( [ tid , ids ] ) => ( {
1172+ tableId : tid ,
1173+ fieldIds : Array . from ( ids ) ,
1174+ } ) ) ;
1175+ if ( dependentSources . length ) {
1176+ await this . computedOrchestrator . computeCellChangesForFields (
1177+ dependentSources ,
1178+ async ( ) => {
1179+ // schema/meta already up to date; nothing additional to run here
1180+ }
1181+ ) ;
1182+ }
1183+ }
1184+
11191185 for ( const raw of dependentFieldRaws ) {
11201186 const instance = createFieldInstanceByRaw ( raw ) ;
11211187 const isValid = await this . isFieldConfigurationValid ( raw . tableId , instance ) ;
0 commit comments