import { observable , action , computed , toJS } from 'mobx' ; import { CanaryExecutionRequest , CanaryScope , KayentaCredential } from '../domain/Kayenta' ; import CanaryExecutionFactory from '../util/CanaryExecutionFactory' ; import { validateAdditionalParameters , validateCanaryExecution , validateExtendedScopeParams } from '../validation/executionValidators' ; import { ofNullable , trimToEmpty } from '../util/OptionalUtils' ; import log from '../util/LoggerFactory' ; import { persist } from 'mobx-persist' ; const METRICS_STORE = 'METRICS_STORE' ; const OBJECT_STORE = 'OBJECT_STORE' ; export default class CanaryExecutorStore { @ observable private credentialsData : KayentaCredential [ ] = [ ] ; @ persist @ observable applicationName = '' ; @ persist @ observable metricsAccountName = '' ; @ persist @ observable storageAccountName = '' ; @ persist ( 'object' ) @ observable private internalCanaryExecutionRequestObject : CanaryExecutionRequest = CanaryExecutionFactory . createNewCanaryExecutionRequest ( ) ; @ observable controlExtendedScopes : KvPair [ ] = [ ] ; @ observable experimentExtendedScopes : KvPair [ ] = [ ] ; @ observable touched : KvMap < boolean > = { } ; @ observable hasTheRunButtonBeenClicked = false ; @ persist @ observable testingType = 'AA' ; @ observable canaryExecutionId = '' ; @ observable resultsRequestComplete = false ; @ observable stageStatus = [ ] ; @ observable isAccordionExpanded = false ; getExtendedScopeParams ( type ) { return type === 'control' ? this . controlExtendedScopes : this . experimentExtendedScopes ; } private replaceExtendedScopeParams ( type , params ) { if ( type === 'control' ) { this . controlExtendedScopes = observable . array ( params ) ; } else { this . experimentExtendedScopes = observable . array ( params ) ; } } @ computed get errors ( ) : KvMap < string > { const canaryExecutionRequestObjectErrors = validateCanaryExecution ( this . internalCanaryExecutionRequestObject ) . errors ; const controlESErrors = validateExtendedScopeParams ( 'control' , this . controlExtendedScopes ) . errors ; const experimentESErrors = validateExtendedScopeParams ( 'experiment' , this . experimentExtendedScopes ) . errors ; const additionalParametersErrors = validateAdditionalParameters ( this . applicationName , this . metricsAccountName , this . storageAccountName ) . errors ; return Object . assign ( { } , canaryExecutionRequestObjectErrors , controlESErrors , experimentESErrors , additionalParametersErrors ) ; } @ computed get isExecutionRequestValid ( ) : boolean { let isValid = true ; if ( ! validateCanaryExecution ( this . internalCanaryExecutionRequestObject ) . isValid ) { isValid = false ; } if ( ! ( validateExtendedScopeParams ( 'control' , this . controlExtendedScopes ) . isValid && validateExtendedScopeParams ( 'experiment' , this . experimentExtendedScopes ) . isValid ) ) { isValid = false ; } if ( ! validateAdditionalParameters ( this . applicationName , this . metricsAccountName , this . storageAccountName ) . isValid ) { isValid = false ; } return isValid ; } @ computed get canaryExecutionRequestObject ( ) : CanaryExecutionRequest { const mutableRequestCopy = toJS ( this . internalCanaryExecutionRequestObject ) ; mutableRequestCopy . scopes . default . controlScope . extendedScopeParams = this . controlExtendedScopes . reduce ( ( extendedScopeParams , kvPair ) => { extendedScopeParams [ kvPair . key ] = kvPair . value ; return extendedScopeParams ; } , { } as KvMap < string > ) ; mutableRequestCopy . scopes . default . experimentScope . extendedScopeParams = this . experimentExtendedScopes . reduce ( ( extendedScopeParams , kvPair ) => { extendedScopeParams [ kvPair . key ] = kvPair . value ; log . info ( extendedScopeParams ) ; return extendedScopeParams ; } , { } as KvMap < string > ) ; return mutableRequestCopy ; } @ computed get metricStoreAccounts ( ) : string [ ] { const accounts = [ ] ; accounts . push ( ... this . credentialsData . filter ( credential => credential . supportedTypes . includes ( METRICS_STORE ) ) . map ( credential => credential . name ) ) ; return accounts ; } @ computed get storageAccounts ( ) : string [ ] { const accounts = [ ] ; accounts . push ( ... this . credentialsData . filter ( credential => credential . supportedTypes . includes ( OBJECT_STORE ) ) . map ( credential => credential . name ) ) ; return accounts ; } @ action . bound addNewExtendedScopeParam ( scopeType ) { this . getExtendedScopeParams ( scopeType ) . push ( { key : '' , value : '' } ) ; } @ action . bound updateExtendedScopeParamKey ( scopeType , index , value ) { this . getExtendedScopeParams ( scopeType ) [ index ] . key = value ; } @ action . bound updateExtendedScopeParamValue ( scopeType , index , value ) { this . getExtendedScopeParams ( scopeType ) [ index ] . value = value ; } @ action . bound deleteExtendedScopeParam ( scopeType , index ) { this . replaceExtendedScopeParams ( scopeType , [ ... this . getExtendedScopeParams ( scopeType ) . slice ( 0 , index ) , ... this . getExtendedScopeParams ( scopeType ) . slice ( index + 1 ) ] ) ; } @ action . bound setKayentaCredentials ( credentialsData ) { this . credentialsData = credentialsData ; this . storageAccountName = trimToEmpty ( this . storageAccountName ) . or ( ( ) => ofNullable ( credentialsData . find ( c => c . supportedTypes . includes ( OBJECT_STORE ) ) ) . map < string > ( c => c . name ) ) . orElse ( '' ) ; } @ action . bound setCanaryExecutionRequestObject ( value ) { this . internalCanaryExecutionRequestObject = value ; } @ action . bound updateApplicationName ( value ) { this . applicationName = value ; } @ action . bound updateMetricsAccountName ( value ) { this . metricsAccountName = value ; } @ action . bound updateStorageAccountName ( value ) { this . storageAccountName = value ; } @ action . bound updateMarginalThreshold ( value ) { this . internalCanaryExecutionRequestObject . thresholds . marginal = value ; } @ action . bound updatePassThreshold ( value ) { this . internalCanaryExecutionRequestObject . thresholds . pass = value ; } @ action . bound updateCanaryScope ( newScope , type ) { if ( type === 'control' ) { this . internalCanaryExecutionRequestObject . scopes . default . controlScope = newScope ; if ( this . testingType === 'AA' ) { this . internalCanaryExecutionRequestObject . scopes . default . experimentScope = newScope ; } } else if ( type === 'experiment' ) { this . internalCanaryExecutionRequestObject . scopes . default . experimentScope = newScope ; } } @ action . bound updateTestingType ( value ) { this . testingType = value ; } @ action . bound touch ( id ) { this . touched [ id ] = true ; } @ action . bound markHasTheRunButtonBeenClickedFlagAsTrue ( ) { this . hasTheRunButtonBeenClicked = true ; } @ action . bound setCanaryExecutionId ( canaryExecutionId ) { this . canaryExecutionId = canaryExecutionId ; } @ action . bound updateResultsRequestComplete ( ) { this . resultsRequestComplete = true ; } @ action . bound clearResultsRequestComplete ( ) { this . resultsRequestComplete = false ; } @ action . bound toggleIsAccordionExpanded ( ) { this . isAccordionExpanded = ! this . isAccordionExpanded ; } @ action . bound resetIsAccordionExpanded ( ) { this . isAccordionExpanded = false ; } @ action . bound updateStageStatus ( value ) { this . stageStatus = value ; } }