mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: constraints limit in a strategy (#7554)
This commit is contained in:
		
							parent
							
								
									ef80d7f81e
								
							
						
					
					
						commit
						7ca2ace0bc
					
				| @ -200,6 +200,7 @@ exports[`should create default config 1`] = ` | ||||
|     "actionSetsPerProject": 5, | ||||
|     "apiTokens": 2000, | ||||
|     "constraintValues": 250, | ||||
|     "constraints": 30, | ||||
|     "environments": 50, | ||||
|     "featureEnvironmentStrategies": 30, | ||||
|     "featureFlags": 5000, | ||||
|  | ||||
| @ -663,6 +663,10 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig { | ||||
|                 options?.resourceLimits?.constraintValues || 250, | ||||
|             ), | ||||
|         ), | ||||
|         constraints: Math.max( | ||||
|             0, | ||||
|             parseEnvVarNumber(process.env.UNLEASH_CONSTRAINTS_LIMIT, 30), | ||||
|         ), | ||||
|         environments: parseEnvVarNumber( | ||||
|             process.env.UNLEASH_ENVIRONMENTS_LIMIT, | ||||
|             50, | ||||
|  | ||||
| @ -387,19 +387,24 @@ class FeatureToggleService { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     validateConstraintValuesLimit(updatedConstrains: IConstraint[]) { | ||||
|     validateConstraintsLimit(updatedConstrains: IConstraint[]) { | ||||
|         if (!this.flagResolver.isEnabled('resourceLimits')) return; | ||||
| 
 | ||||
|         const limit = this.resourceLimits.constraintValues; | ||||
|         const constraintsLimit = this.resourceLimits.constraints; | ||||
|         if (updatedConstrains.length > constraintsLimit) { | ||||
|             throw new ExceedsLimitError(`constraints`, constraintsLimit); | ||||
|         } | ||||
| 
 | ||||
|         const constraintValuesLimit = this.resourceLimits.constraintValues; | ||||
|         const constraintOverLimit = updatedConstrains.find( | ||||
|             (constraint) => | ||||
|                 Array.isArray(constraint.values) && | ||||
|                 constraint.values?.length > limit, | ||||
|                 constraint.values?.length > constraintValuesLimit, | ||||
|         ); | ||||
|         if (constraintOverLimit) { | ||||
|             throw new ExceedsLimitError( | ||||
|                 `content values for ${constraintOverLimit.contextName}`, | ||||
|                 limit, | ||||
|                 constraintValuesLimit, | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| @ -649,7 +654,7 @@ class FeatureToggleService { | ||||
|             strategyConfig.constraints && | ||||
|             strategyConfig.constraints.length > 0 | ||||
|         ) { | ||||
|             this.validateConstraintValuesLimit(strategyConfig.constraints); | ||||
|             this.validateConstraintsLimit(strategyConfig.constraints); | ||||
|             strategyConfig.constraints = await this.validateConstraints( | ||||
|                 strategyConfig.constraints, | ||||
|             ); | ||||
| @ -808,7 +813,7 @@ class FeatureToggleService { | ||||
| 
 | ||||
|         if (existingStrategy.id === id) { | ||||
|             if (updates.constraints && updates.constraints.length > 0) { | ||||
|                 this.validateConstraintValuesLimit(updates.constraints); | ||||
|                 this.validateConstraintsLimit(updates.constraints); | ||||
|                 updates.constraints = await this.validateConstraints( | ||||
|                     updates.constraints, | ||||
|                 ); | ||||
|  | ||||
| @ -47,6 +47,50 @@ describe('Strategy limits', () => { | ||||
|         ); | ||||
|     }); | ||||
| 
 | ||||
|     test('Should not allow to exceed constraints limit', async () => { | ||||
|         const LIMIT = 1; | ||||
|         const { featureToggleService, featureToggleStore } = | ||||
|             createFakeFeatureToggleService({ | ||||
|                 getLogger, | ||||
|                 flagResolver: alwaysOnFlagResolver, | ||||
|                 resourceLimits: { | ||||
|                     constraints: LIMIT, | ||||
|                 }, | ||||
|             } as unknown as IUnleashConfig); | ||||
| 
 | ||||
|         const addStrategy = (constraints: IConstraint[]) => | ||||
|             featureToggleService.unprotectedCreateStrategy( | ||||
|                 { | ||||
|                     name: 'default', | ||||
|                     featureName: 'feature', | ||||
|                     constraints: constraints, | ||||
|                 } as IStrategyConfig, | ||||
|                 { projectId: 'default', featureName: 'feature' } as any, | ||||
|                 {} as IAuditUser, | ||||
|             ); | ||||
|         await featureToggleStore.create('default', { | ||||
|             name: 'feature', | ||||
|             createdByUserId: 1, | ||||
|         }); | ||||
| 
 | ||||
|         await expect( | ||||
|             addStrategy([ | ||||
|                 { | ||||
|                     values: ['1'], | ||||
|                     operator: 'IN', | ||||
|                     contextName: 'accountId', | ||||
|                 }, | ||||
|                 { | ||||
|                     values: ['2'], | ||||
|                     operator: 'IN', | ||||
|                     contextName: 'accountId', | ||||
|                 }, | ||||
|             ]), | ||||
|         ).rejects.toThrow( | ||||
|             "Failed to create constraints. You can't create more than the established limit of 1", | ||||
|         ); | ||||
|     }); | ||||
| 
 | ||||
|     test('Should not allow to exceed constraint values limit', async () => { | ||||
|         const LIMIT = 3; | ||||
|         const { featureToggleService, featureToggleStore } = | ||||
|  | ||||
| @ -20,6 +20,7 @@ export const resourceLimitsSchema = { | ||||
|         'apiTokens', | ||||
|         'segments', | ||||
|         'featureFlags', | ||||
|         'constraints', | ||||
|     ], | ||||
|     additionalProperties: false, | ||||
|     properties: { | ||||
| @ -80,6 +81,12 @@ export const resourceLimitsSchema = { | ||||
|             description: | ||||
|                 'The maximum number of values for a single constraint.', | ||||
|         }, | ||||
|         constraints: { | ||||
|             type: 'integer', | ||||
|             example: 30, | ||||
|             description: | ||||
|                 'The maximum number of constraints in a single strategy.', | ||||
|         }, | ||||
|         environments: { | ||||
|             type: 'integer', | ||||
|             minimum: 1, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user