import { IClusterHealthChunk , IDeployedServicePackageHealthStateChunk } from '../../HealthChunkRawDataTypes' ; import { IResponseMessageHandler } from 'src/app/Common/ResponseMessageHandlers' ; import { Observable , of , throwError } from 'rxjs' ; import { ValueResolver , ITextAndBadge } from 'src/app/Utils/ValueResolver' ; import { IRawDeployedServicePackage } from '../../RawDataTypes' ; import { IdGenerator } from 'src/app/Utils/IdGenerator' ; import { DataService } from 'src/app/services/data.service' ; import { HealthStateConstants } from 'src/app/Common/Constants' ; import { mergeMap , map } from 'rxjs/operators' ; import { BackupPolicy } from '../Cluster' ; import { ApplicationBackupConfigurationInfo , Application } from '../Application' ; import { ApplicationTypeGroup , ApplicationType } from '../ApplicationType' ; import { Service , ServiceType , ServiceBackupConfigurationInfo } from '../Service' ; import { IdUtils } from 'src/app/Utils/IdUtils' ; import { Partition } from '../Partition' ; import { ReplicaOnPartition } from '../Replica' ; import { DeployedApplication } from '../DeployedApplication' ; import { DeployedServicePackage } from '../DeployedServicePackage' ; import { DeployedCodePackage } from '../DeployedCodePackage' ; import { DeployedReplica } from '../DeployedReplica' ; import { FabricEventBase , FabricEventInstanceModel , ClusterEvent , NodeEvent , ApplicationEvent , ServiceEvent , PartitionEvent , ReplicaEvent , FabricEvent } from '../../eventstore/Events' ; import { ListSettings , ListColumnSetting , ListColumnSettingWithFilter , ListColumnSettingWithEventStoreFullDescription , ListColumnSettingWithEventStoreRowDisplay } from '../../ListSettings' ; import { TimeUtils } from 'src/app/Utils/TimeUtils' ; import { PartitionBackup , PartitionBackupInfo } from '../PartitionBackupInfo' ; import { DataModelCollectionBase , IDataModelCollection } from './CollectionBase' ; import groupBy from 'lodash/groupBy' ; import { RoutesService } from 'src/app/services/routes.service' ; export class BackupPolicyCollection extends DataModelCollectionBase < BackupPolicy > { protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getBackupPolicies ( messageHandler ) . pipe ( map ( items => { return items . map ( raw => new BackupPolicy ( this . data , raw ) ) ; } ) ) ; } } export class ApplicationCollection extends DataModelCollectionBase < Application > { public upgradingAppCount = 0 ; public healthState : ITextAndBadge ; public constructor ( data ) { super ( data ) ; } public get viewPath ( ) : string { return RoutesService . getAppsViewPath ( ) ; } public mergeClusterHealthStateChunk ( clusterHealthChunk ) { return this . updateCollectionFromHealthChunkList ( clusterHealthChunk . ApplicationHealthStateChunks , item => IdGenerator . app ( IdUtils . nameToId ( item . ApplicationName ) ) ) . pipe ( mergeMap ( ( ) => { this . updateAppsHealthState ( ) ; return this . refreshAppTypeGroups ( ) ; } ) ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getApplications ( this . data . readOnlyHeader , messageHandler ) . pipe ( map ( items => { return items . map ( raw => new Application ( this . data , raw ) ) ; } ) ) ; } protected updateInternal ( ) { this . upgradingAppCount = this . collection . filter ( app => app . isUpgrading ) . length ; this . updateAppsHealthState ( ) ; return this . refreshAppTypeGroups ( ) ; } private updateAppsHealthState ( ) { this . collection . map ( app => HealthStateConstants . Values [ app . healthState . text ] ) ; this . healthState = this . length > 0 ? this . valueResolver . resolveHealthStatus ( Math . max ( ... this . collection . map ( app => HealthStateConstants . Values [ app . healthState . text ] ) as number [ ] ) . toString ( ) ) : ValueResolver . healthStatuses [ 1 ] ; } private refreshAppTypeGroups ( ) { return this . data . getAppTypeGroups ( false ) . pipe ( map ( appTypeGroups => { appTypeGroups . collection . forEach ( appTypeGroup => appTypeGroup . refreshAppTypeApps ( this ) ) ; return appTypeGroups ; } ) ) ; } } export class ApplicationTypeGroupCollection extends DataModelCollectionBase < ApplicationTypeGroup > { public constructor ( data ) { super ( data ) ; } public get viewPath ( ) : string { return RoutesService . getAppTypesViewPath ( ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getApplicationTypes ( null , messageHandler ) . pipe ( map ( response => { const appTypes = response . map ( item => new ApplicationType ( this . data , item ) ) ; const groups = groupBy ( appTypes , item => item . raw . Name ) ; return Object . keys ( groups ) . map ( g => new ApplicationTypeGroup ( this . data , groups [ g ] ) ) ; } ) ) ; } } export class ApplicationBackupConfigurationInfoCollection extends DataModelCollectionBase < ApplicationBackupConfigurationInfo > { public constructor ( data , public parent ) { super ( data , parent ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getApplicationBackupConfigurationInfoCollection ( this . parent . id , messageHandler ) . pipe ( map ( items => { return items . map ( raw => new ApplicationBackupConfigurationInfo ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class ServiceBackupConfigurationInfoCollection extends DataModelCollectionBase < ServiceBackupConfigurationInfo > { public constructor ( data , public parent ) { super ( data , parent ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getServiceBackupConfigurationInfoCollection ( this . parent . id , messageHandler ) . pipe ( map ( items => { return items . map ( raw => new ServiceBackupConfigurationInfo ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class PartitionBackupCollection extends DataModelCollectionBase < PartitionBackup > { public startDate : Date ; public endDate : Date ; public constructor ( data , public parent ) { super ( data , parent ) ; this . startDate = null ; this . endDate = null ; } public retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getPartitionBackupList ( this . parent . parent . id , messageHandler , this . startDate , this . endDate ) . pipe ( map ( items => { return items . map ( raw => new PartitionBackup ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class SinglePartitionBackupCollection extends DataModelCollectionBase < PartitionBackup > { public constructor ( data , public parent ) { super ( data , parent ) ; } public retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getLatestPartitionBackup ( this . parent . parent . id , messageHandler ) . pipe ( map ( items => { return items . map ( raw => new PartitionBackup ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class ServiceTypeCollection extends DataModelCollectionBase < ServiceType > { public constructor ( data , public parent ) { super ( data , parent ) ; } protected retrieveNewCollection ( messageHandler ? ) { let appTypeName = null ; let appTypeVersion = null ; if ( this . parent instanceof ApplicationType ) { appTypeName = ( ( this . parent ) as ApplicationType ) . raw . Name ; appTypeVersion = ( ( this . parent ) as ApplicationType ) . raw . Version ; } else { appTypeName = ( ( this . parent ) as Application ) . raw . TypeName ; appTypeVersion = ( ( this . parent ) as Application ) . raw . TypeVersion ; } return this . data . restClient . getServiceTypes ( appTypeName , appTypeVersion , messageHandler ) . pipe ( map ( response => { return response . map ( raw => new ServiceType ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class PartitionCollection extends DataModelCollectionBase < Partition > { public constructor ( data , public parent ) { super ( data , parent ) ; } public mergeClusterHealthStateChunk ( clusterHealthChunk ) { const appHealthChunk = clusterHealthChunk . ApplicationHealthStateChunks . Items . find ( item => item . ApplicationName === this . parent . parent . name ) ; if ( appHealthChunk ) { const serviceHealthChunk = appHealthChunk . ServiceHealthStateChunks . Items . find ( item => item . ServiceName === this . parent . name ) ; if ( serviceHealthChunk ) { return this . updateCollectionFromHealthChunkList ( serviceHealthChunk . PartitionHealthStateChunks , item => IdGenerator . partition ( item . PartitionId ) ) ; } } return of ( true ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getPartitions ( this . parent . parent . id , this . parent . id , messageHandler ) . pipe ( map ( items => { return items . map ( raw => new Partition ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class ReplicaOnPartitionCollection extends DataModelCollectionBase < ReplicaOnPartition > { public constructor ( data , public parent ) { super ( data , parent ) ; } public get isStatefulService ( ) : boolean { return this . parent . parent . isStatefulService ; } public get isStatelessService ( ) : boolean { return this . parent . isStatelessService ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getReplicasOnPartition ( this . parent . parent . parent . id , this . parent . parent . id , this . parent . id , messageHandler ) . pipe ( map ( items => { return items . map ( raw => new ReplicaOnPartition ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class DeployedServicePackageCollection extends DataModelCollectionBase < DeployedServicePackage > { public constructor ( data , public parent ) { super ( data , parent ) ; } public mergeClusterHealthStateChunk ( clusterHealthChunk ) { const appHealthChunk = clusterHealthChunk . ApplicationHealthStateChunks . Items . find ( item => item . ApplicationName === this . parent . name ) ; if ( appHealthChunk ) { const deployedAppHealthChunk = appHealthChunk . DeployedApplicationHealthStateChunks . Items . find ( deployedAppHealth => deployedAppHealth . NodeName === this . parent . parent . name ) ; if ( deployedAppHealthChunk ) { return this . updateCollectionFromHealthChunkList < IDeployedServicePackageHealthStateChunk > ( deployedAppHealthChunk . DeployedServicePackageHealthStateChunks , item => IdGenerator . deployedServicePackage ( item . ServiceManifestName , item . ServicePackageActivationId ) ) ; } } return of ( true ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getDeployedServicePackages ( this . parent . parent . name , this . parent . id , messageHandler ) . pipe ( map ( ( raw ) => { return raw . map ( rawServicePackage => new DeployedServicePackage ( this . data , rawServicePackage , this . parent ) ) ; } ) ) ; } protected updateInternal ( ) { if ( this . length > 0 ) { const healthChunkQueryDescription = this . data . getInitialClusterHealthChunkQueryDescription ( ) ; this . parent . addHealthStateFiltersForChildren ( healthChunkQueryDescription ) ; return this . data . getClusterHealthChunk ( healthChunkQueryDescription ) . pipe ( mergeMap ( healthChunk => { return this . mergeClusterHealthStateChunk ( healthChunk ) ; } ) ) ; } else { return of ( true ) ; } } } export class DeployedCodePackageCollection extends DataModelCollectionBase < DeployedCodePackage > { public constructor ( data , public parent ) { super ( data , parent ) ; } public get viewPath ( ) : string { return RoutesService . getDeployedCodePackagesViewPath ( this . parent . parent . parent . name , this . parent . parent . id , this . parent . id , this . parent . servicePackageActivationId ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getDeployedCodePackages ( this . parent . parent . parent . name , this . parent . parent . id , this . parent . name , messageHandler ) . pipe ( map ( response => { return response . filter ( raw => raw . ServicePackageActivationId === this . parent . servicePackageActivationId ) . map ( raw => new DeployedCodePackage ( this . data , raw , this . parent ) ) ; } ) ) ; } } export class DeployedReplicaCollection extends DataModelCollectionBase < DeployedReplica > { public constructor ( data , public parent ) { super ( data , parent ) ; } public get viewPath ( ) : string { return RoutesService . getDeployedReplicasViewPath ( this . parent . parent . parent . name , this . parent . parent . id , this . parent . id , this . parent . servicePackageActivationId ) ; } public get isStatefulService ( ) : boolean { return this . length > 0 && this . collection [ 0 ] . isStatefulService ; } public get isStatelessService ( ) : boolean { return this . length > 0 && this . collection [ 0 ] . isStatelessService ; } protected retrieveNewCollection ( messageHandler ? ) { return this . data . restClient . getDeployedReplicas ( this . parent . parent . parent . name , this . parent . parent . id , this . parent . name , messageHandler ) . pipe ( map ( response => { return response . filter ( raw => raw . ServicePackageActivationId === this . parent . servicePackageActivationId ) . map ( raw => new DeployedReplica ( this . data , raw , this . parent ) ) ; } ) ) ; } } export abstract class EventListBase < T extends FabricEventBase > extends DataModelCollectionBase < FabricEventInstanceModel < T > > { public readonly settings : ListSettings ; public readonly detailsSettings : ListSettings ; public readonly pageSize : number = 15 ; public readonly defaultDateWindowInDays : number = 7 ; public readonly latestRefreshPeriodInSecs : number = 60 * 60 ; protected readonly optionalColsStartIndex : number = 2 ; private iStartDate : Date ; private iEndDate : Date ; public get startDate ( ) { return new Date ( this . iStartDate . valueOf ( ) ) ; } public get endDate ( ) { let endDate = new Date ( this . iEndDate . valueOf ( ) ) ; const timeNow = new Date ( ) ; if ( endDate > timeNow ) { endDate = timeNow ; } return endDate ; } public get queryStartDate ( ) { return this . startDate ; } public get queryEndDate ( ) { return this . endDate ; } public constructor ( data , startDate ? , endDate ? ) { super ( data , null , false ) ; this . settings = this . createListSettings ( ) ; this . detailsSettings = this . createListSettings ( ) ; this . setNewDateWindowInternal ( startDate , endDate ) ; } public setDateWindow ( startDate ? , endDate ? ) { return this . setNewDateWindowInternal ( startDate , endDate ) ; } public resetDateWindow ( ) { return this . setDateWindow ( null , null ) ; } public reload ( messageHandler ? ) { return this . clear ( ) . pipe ( map ( ( ) => { return this . refresh ( messageHandler ) ; } ) ) ; } protected retrieveNewCollection ( messageHandler ? ) { return this . retrieveEvents ( messageHandler ) ; } protected getDetailsList ( item ) { return this . data . createCorrelatedEventList ( item . raw . eventInstanceId ) ; } protected retrieveEvents ( messageHandler ? ) { return of ( [ ] ) ; } private createListSettings ( ) { const listSettings = new ListSettings ( this . pageSize , [ 'raw.timeStamp' ] , 'Events results' , [ new ListColumnSettingWithEventStoreRowDisplay ( ) , new ListColumnSetting ( 'raw.category' , 'Event Category' , { enableFilter : true , getDisplayHtml : ( item ) => ( ! item . raw . category ? 'Operational' : item . raw . category ) } ) , new ListColumnSetting ( 'raw.timeStampString' , 'Timestamp' , { sortPropertyPaths : [ 'raw.timestamp' ] } ) , new ListColumnSetting ( 'raw.timeStamp' , 'Timestamp(UTC)' ) ] , [ new ListColumnSettingWithEventStoreFullDescription ( ) ] , true , ( item ) => ( Object . keys ( item . raw . eventProperties ) . length > 0 ) , true ) ; return listSettings ; } private setNewDateWindowInternal ( startDate ? , endDate ? ) { if ( ! startDate ) { startDate = TimeUtils . AddDays ( endDate ? endDate : new Date ( ) , ( - 1 * this . defaultDateWindowInDays ) ) ; } if ( ! endDate ) { endDate = TimeUtils . AddDays ( startDate , this . defaultDateWindowInDays ) ; } if ( ! this . iStartDate || this . iStartDate . getTime ( ) !== startDate . getTime ( ) || ! this . iEndDate || this . iEndDate . getTime ( ) !== endDate . getTime ( ) ) { this . iStartDate = startDate ; this . iEndDate = endDate ; return true ; } return false ; } } export class ClusterEventList extends EventListBase < ClusterEvent > { public constructor ( data , partitionId ? ) { super ( data ) ; } protected retrieveEvents ( messageHandler ? ) { return this . data . restClient . getClusterEvents ( this . queryStartDate , this . queryEndDate , messageHandler ) . pipe ( map ( result => { return result . map ( event => new FabricEventInstanceModel < ClusterEvent > ( this . data , event ) ) ; } ) ) ; } } export class NodeEventList extends EventListBase < NodeEvent > { private nodeName ? : string ; public constructor ( data , nodeName ? ) { super ( data ) ; this . nodeName = nodeName ; if ( ! this . nodeName ) { this . settings . columnSettings . splice ( this . optionalColsStartIndex , 0 , new ListColumnSettingWithFilter ( 'raw.nodeName' , 'Node Name' ) ) ; } } protected retrieveEvents ( messageHandler ? ) { return this . data . restClient . getNodeEvents ( this . queryStartDate , this . queryEndDate , this . nodeName , messageHandler ) . pipe ( map ( result => { return result . map ( event => new FabricEventInstanceModel < NodeEvent > ( this . data , event ) ) ; } ) ) ; } } export class ApplicationEventList extends EventListBase < ApplicationEvent > { private applicationId ? : string ; public constructor ( data , applicationId ? ) { super ( data ) ; if ( applicationId ) { this . applicationId = applicationId . replace ( new RegExp ( '/' , 'g' ) , '~' ) ; } if ( ! this . applicationId ) { this . settings . columnSettings . splice ( this . optionalColsStartIndex , 0 , new ListColumnSettingWithFilter ( 'raw.applicationId' , 'Application Id' ) ) ; } } protected retrieveEvents ( messageHandler ? ) { return this . data . restClient . getApplicationEvents ( this . queryStartDate , this . queryEndDate , this . applicationId , messageHandler ) . pipe ( map ( result => { return result . map ( event => new FabricEventInstanceModel < ApplicationEvent > ( this . data , event ) ) ; } ) ) ; } } export class ServiceEventList extends EventListBase < ServiceEvent > { private serviceId ? : string ; public constructor ( data , serviceId ? ) { super ( data ) ; if ( serviceId ) { this . serviceId = serviceId . replace ( new RegExp ( '/' , 'g' ) , '~' ) ; } if ( ! this . serviceId ) { this . settings . columnSettings . splice ( this . optionalColsStartIndex , 0 , new ListColumnSettingWithFilter ( 'raw.serviceId' , 'Service Id' ) ) ; } } protected retrieveEvents ( messageHandler ? ) { return this . data . restClient . getServiceEvents ( this . queryStartDate , this . queryEndDate , this . serviceId , messageHandler ) . pipe ( map ( result => { return result . map ( event => new FabricEventInstanceModel < ServiceEvent > ( this . data , event ) ) ; } ) ) ; } } export class PartitionEventList extends EventListBase < PartitionEvent > { private partitionId ? : string ; public constructor ( data , partitionId ? ) { super ( data ) ; this . partitionId = partitionId ; if ( ! this . partitionId ) { this . settings . columnSettings . splice ( this . optionalColsStartIndex , 0 , new ListColumnSettingWithFilter ( 'raw.partitionId' , 'Partition Id' ) ) ; } } protected retrieveEvents ( messageHandler ? ) { return this . data . restClient . getPartitionEvents ( this . queryStartDate , this . queryEndDate , this . partitionId , messageHandler ) . pipe ( map ( result => { return result . map ( event => new FabricEventInstanceModel < PartitionEvent > ( this . data , event ) ) ; } ) ) ; } } export class ReplicaEventList extends EventListBase < ReplicaEvent > { private partitionId : string ; private replicaId ? : string ; public constructor ( data , partitionId , replicaId ? ) { super ( data ) ; this . partitionId = partitionId ; this . replicaId = replicaId ; if ( ! this . replicaId ) { this . settings . columnSettings . splice ( this . optionalColsStartIndex , 0 , new ListColumnSettingWithFilter ( 'raw.replicaId' , 'Replica Id' ) ) ; } } protected retrieveEvents ( messageHandler ? ) { return this . data . restClient . getReplicaEvents ( this . queryStartDate , this . queryEndDate , this . partitionId , this . replicaId , messageHandler ) . pipe ( map ( result => { return result . map ( event => new FabricEventInstanceModel < ReplicaEvent > ( this . data , event ) ) ; } ) ) ; } } export class CorrelatedEventList extends EventListBase < FabricEvent > { private eventInstanceId : string ; public constructor ( data , eventInstanceId ) { super ( data ) ; this . eventInstanceId = eventInstanceId ; } protected retrieveEvents ( messageHandler ? ) { return this . data . restClient . getCorrelatedEvents ( this . eventInstanceId , messageHandler ) . pipe ( map ( result => { return result . map ( event => new FabricEventInstanceModel < FabricEvent > ( this . data , event ) ) ; } ) ) ; } }