mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	refactor: segment-store getAll refactor, move mappers out of main method. (#6423)
For `getAll` method, kept only sql queries and moved mappers into separate functions. No change in logic, just refactoring.
This commit is contained in:
		
							parent
							
								
									f3df7269cb
								
							
						
					
					
						commit
						ce8e15347c
					
				| @ -18,13 +18,11 @@ import { DashboardHeader } from './components/DashboardHeader/DashboardHeader'; | ||||
| import { UserStats } from './componentsStat/UserStats/UserStats'; | ||||
| import { FlagStats } from './componentsStat/FlagStats/FlagStats'; | ||||
| import { HealthStats } from './componentsStat/HealthStats/HealthStats'; | ||||
| import { TimeToProduction } from './componentsStat/TimeToProduction/TimeToProduction'; | ||||
| 
 | ||||
| import { UsersChart } from './componentsChart/UsersChart/UsersChart'; | ||||
| import { FlagsChart } from './componentsChart/FlagsChart/FlagsChart'; | ||||
| import { FlagsProjectChart } from './componentsChart/FlagsProjectChart/FlagsProjectChart'; | ||||
| import { ProjectHealthChart } from './componentsChart/ProjectHealthChart/ProjectHealthChart'; | ||||
| import { TimeToProductionChart } from './componentsChart/TimeToProductionChart/TimeToProductionChart'; | ||||
| import { MetricsSummaryChart } from './componentsChart/MetricsSummaryChart/MetricsSummaryChart'; | ||||
| import { UsersPerProjectChart } from './componentsChart/UsersPerProjectChart/UsersPerProjectChart'; | ||||
| 
 | ||||
|  | ||||
| @ -116,113 +116,13 @@ export default class SegmentStore implements ISegmentStore { | ||||
|         includeChangeRequestUsageData: boolean = false, | ||||
|     ): Promise<ISegment[]> { | ||||
|         if (includeChangeRequestUsageData) { | ||||
|             const pendingCRs = await this.db | ||||
|                 .select('id', 'project') | ||||
|                 .from('change_requests') | ||||
|                 .whereNotIn('state', ['Applied', 'Rejected', 'Cancelled']); | ||||
| 
 | ||||
|             const pendingChangeRequestIds = pendingCRs.map((cr) => cr.id); | ||||
| 
 | ||||
|             const crFeatures = await this.db | ||||
|                 .select( | ||||
|                     'payload', | ||||
|                     'feature', | ||||
|                     'change_request_id as changeRequestId', | ||||
|                 ) | ||||
|                 .from('change_request_events') | ||||
|                 .whereIn('change_request_id', pendingChangeRequestIds) | ||||
|                 .whereIn('action', ['addStrategy', 'updateStrategy']) | ||||
|                 .andWhereRaw("jsonb_array_length(payload -> 'segments') > 0"); | ||||
| 
 | ||||
|             const changeRequestToProjectMap = pendingCRs.reduce( | ||||
|                 (acc, { id, project }) => { | ||||
|                     acc[id] = project; | ||||
|                     return acc; | ||||
|                 }, | ||||
|                 {}, | ||||
|             ); | ||||
| 
 | ||||
|             const combinedUsageData = crFeatures.reduce((acc, segmentEvent) => { | ||||
|                 const { payload, changeRequestId, feature } = segmentEvent; | ||||
|                 const project = changeRequestToProjectMap[changeRequestId]; | ||||
| 
 | ||||
|                 for (const segmentId of payload.segments) { | ||||
|                     const existingData = acc[segmentId]; | ||||
|                     if (existingData) { | ||||
|                         acc[segmentId] = { | ||||
|                             features: existingData.features.add(feature), | ||||
|                             projects: existingData.projects.add(project), | ||||
|                         }; | ||||
|             return this.getAllWithChangeRequestUsageData(); | ||||
|         } else { | ||||
|                         acc[segmentId] = { | ||||
|                             features: new Set([feature]), | ||||
|                             projects: new Set([project]), | ||||
|                         }; | ||||
|             return this.getAllWithoutChangeRequestUsageData(); | ||||
|         } | ||||
|     } | ||||
|                 return acc; | ||||
|             }, {}); | ||||
| 
 | ||||
|             const currentSegmentUsage = await this.db | ||||
|                 .select( | ||||
|                     `${T.featureStrategies}.feature_name as featureName`, | ||||
|                     `${T.featureStrategies}.project_name as projectName`, | ||||
|                     'segment_id as segmentId', | ||||
|                 ) | ||||
|                 .from(T.featureStrategySegment) | ||||
|                 .leftJoin( | ||||
|                     T.featureStrategies, | ||||
|                     `${T.featureStrategies}.id`, | ||||
|                     `${T.featureStrategySegment}.feature_strategy_id`, | ||||
|                 ); | ||||
| 
 | ||||
|             currentSegmentUsage.forEach( | ||||
|                 ({ segmentId, featureName, projectName }) => { | ||||
|                     const usage = combinedUsageData[segmentId]; | ||||
|                     if (usage) { | ||||
|                         combinedUsageData[segmentId] = { | ||||
|                             features: usage.features.add(featureName), | ||||
|                             projects: usage.projects.add(projectName), | ||||
|                         }; | ||||
|                     } else { | ||||
|                         combinedUsageData[segmentId] = { | ||||
|                             features: new Set([featureName]), | ||||
|                             projects: new Set([projectName]), | ||||
|                         }; | ||||
|                     } | ||||
|                 }, | ||||
|             ); | ||||
| 
 | ||||
|             const rows: ISegmentRow[] = await this.db | ||||
|                 .select(this.prefixColumns()) | ||||
|                 .from(T.segments) | ||||
|                 .leftJoin( | ||||
|                     T.featureStrategySegment, | ||||
|                     `${T.segments}.id`, | ||||
|                     `${T.featureStrategySegment}.segment_id`, | ||||
|                 ) | ||||
|                 .groupBy(this.prefixColumns()) | ||||
|                 .orderBy('name', 'asc'); | ||||
| 
 | ||||
|             const rowsWithUsageData: ISegmentRow[] = rows.map((row) => { | ||||
|                 const usageData = combinedUsageData[row.id]; | ||||
|                 if (usageData) { | ||||
|                     return { | ||||
|                         ...row, | ||||
|                         used_in_features: usageData.features.size, | ||||
|                         used_in_projects: usageData.projects.size, | ||||
|                     }; | ||||
|                 } else { | ||||
|                     return { | ||||
|                         ...row, | ||||
|                         used_in_features: 0, | ||||
|                         used_in_projects: 0, | ||||
|                     }; | ||||
|                 } | ||||
|             }); | ||||
| 
 | ||||
|             return rowsWithUsageData.map(this.mapRow); | ||||
|         } else { | ||||
|     private async getAllWithoutChangeRequestUsageData(): Promise<ISegment[]> { | ||||
|         const rows: ISegmentRow[] = await this.db | ||||
|             .select( | ||||
|                 this.prefixColumns(), | ||||
| @ -251,6 +151,137 @@ export default class SegmentStore implements ISegmentStore { | ||||
| 
 | ||||
|         return rows.map(this.mapRow); | ||||
|     } | ||||
| 
 | ||||
|     private async getAllWithChangeRequestUsageData(): Promise<ISegment[]> { | ||||
|         const pendingCRs = await this.db | ||||
|             .select('id', 'project') | ||||
|             .from('change_requests') | ||||
|             .whereNotIn('state', ['Applied', 'Rejected', 'Cancelled']); | ||||
| 
 | ||||
|         const pendingChangeRequestIds = pendingCRs.map((cr) => cr.id); | ||||
| 
 | ||||
|         const crFeatures = await this.db | ||||
|             .select( | ||||
|                 'payload', | ||||
|                 'feature', | ||||
|                 'change_request_id as changeRequestId', | ||||
|             ) | ||||
|             .from('change_request_events') | ||||
|             .whereIn('change_request_id', pendingChangeRequestIds) | ||||
|             .whereIn('action', ['addStrategy', 'updateStrategy']) | ||||
|             .andWhereRaw("jsonb_array_length(payload -> 'segments') > 0"); | ||||
| 
 | ||||
|         const combinedUsageData = this.combineUsageData(pendingCRs, crFeatures); | ||||
| 
 | ||||
|         const currentSegmentUsage = await this.db | ||||
|             .select( | ||||
|                 `${T.featureStrategies}.feature_name as featureName`, | ||||
|                 `${T.featureStrategies}.project_name as projectName`, | ||||
|                 'segment_id as segmentId', | ||||
|             ) | ||||
|             .from(T.featureStrategySegment) | ||||
|             .leftJoin( | ||||
|                 T.featureStrategies, | ||||
|                 `${T.featureStrategies}.id`, | ||||
|                 `${T.featureStrategySegment}.feature_strategy_id`, | ||||
|             ); | ||||
| 
 | ||||
|         this.mergeCurrentUsageWithCombinedData( | ||||
|             combinedUsageData, | ||||
|             currentSegmentUsage, | ||||
|         ); | ||||
| 
 | ||||
|         const rows: ISegmentRow[] = await this.db | ||||
|             .select(this.prefixColumns()) | ||||
|             .from(T.segments) | ||||
|             .leftJoin( | ||||
|                 T.featureStrategySegment, | ||||
|                 `${T.segments}.id`, | ||||
|                 `${T.featureStrategySegment}.segment_id`, | ||||
|             ) | ||||
|             .groupBy(this.prefixColumns()) | ||||
|             .orderBy('name', 'asc'); | ||||
| 
 | ||||
|         const rowsWithUsageData = this.mapRowsWithUsageData( | ||||
|             rows, | ||||
|             combinedUsageData, | ||||
|         ); | ||||
| 
 | ||||
|         return rowsWithUsageData.map(this.mapRow); | ||||
|     } | ||||
| 
 | ||||
|     private mapRowsWithUsageData( | ||||
|         rows: ISegmentRow[], | ||||
|         combinedUsageData: any, | ||||
|     ): ISegmentRow[] { | ||||
|         return rows.map((row) => { | ||||
|             const usageData = combinedUsageData[row.id]; | ||||
|             if (usageData) { | ||||
|                 return { | ||||
|                     ...row, | ||||
|                     used_in_features: usageData.features.size, | ||||
|                     used_in_projects: usageData.projects.size, | ||||
|                 }; | ||||
|             } else { | ||||
|                 return { | ||||
|                     ...row, | ||||
|                     used_in_features: 0, | ||||
|                     used_in_projects: 0, | ||||
|                 }; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private combineUsageData = (pendingCRs, crFeatures) => { | ||||
|         const changeRequestToProjectMap = pendingCRs.reduce( | ||||
|             (acc, { id, project }) => { | ||||
|                 acc[id] = project; | ||||
|                 return acc; | ||||
|             }, | ||||
|             {}, | ||||
|         ); | ||||
| 
 | ||||
|         const combinedUsageData = crFeatures.reduce((acc, segmentEvent) => { | ||||
|             const { payload, changeRequestId, feature } = segmentEvent; | ||||
|             const project = changeRequestToProjectMap[changeRequestId]; | ||||
| 
 | ||||
|             for (const segmentId of payload.segments) { | ||||
|                 const existingData = acc[segmentId]; | ||||
|                 if (existingData) { | ||||
|                     acc[segmentId] = { | ||||
|                         features: existingData.features.add(feature), | ||||
|                         projects: existingData.projects.add(project), | ||||
|                     }; | ||||
|                 } else { | ||||
|                     acc[segmentId] = { | ||||
|                         features: new Set([feature]), | ||||
|                         projects: new Set([project]), | ||||
|                     }; | ||||
|                 } | ||||
|             } | ||||
|             return acc; | ||||
|         }, {}); | ||||
|         return combinedUsageData; | ||||
|     }; | ||||
| 
 | ||||
|     private mergeCurrentUsageWithCombinedData( | ||||
|         combinedUsageData: any, | ||||
|         currentSegmentUsage: any[], | ||||
|     ) { | ||||
|         currentSegmentUsage.forEach( | ||||
|             ({ segmentId, featureName, projectName }) => { | ||||
|                 const usage = combinedUsageData[segmentId]; | ||||
|                 if (usage) { | ||||
|                     usage.features.add(featureName); | ||||
|                     usage.projects.add(projectName); | ||||
|                 } else { | ||||
|                     combinedUsageData[segmentId] = { | ||||
|                         features: new Set([featureName]), | ||||
|                         projects: new Set([projectName]), | ||||
|                     }; | ||||
|                 } | ||||
|             }, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     async getActive(): Promise<ISegment[]> { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user