Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 23 additions & 22 deletions src/app/devices/device-toolbar/device-toolbar.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe('DeviceToolbarComponent', () => {
'sendDeactivate',
'getPowerState',
'getAMTFeatures',
'getAMTFeaturesCached',
'getAMTVersion',
'featuresChanges'
])
Expand All @@ -54,28 +55,28 @@ describe('DeviceToolbarComponent', () => {
)

devicesService.getPowerState.and.returnValue(of({ powerstate: 2 }))
devicesService.getAMTFeatures.and.returnValue(
of({
userConsent: 'None',
ocr: true,
httpsBootSupported: true,
kvm: true,
sol: true,
ider: true,
redirection: true,
optInState: 1,
kvmAvailable: true,
winREBootSupported: true,
localPBABootSupported: true,
remoteErase: true,
pbaBootFilesPath: [],
winREBootFilesPath: {
instanceID: '',
biosBootString: '',
bootString: ''
}
} as any)
)
const mockAMTFeatures = {
userConsent: 'None',
ocr: true,
httpsBootSupported: true,
kvm: true,
sol: true,
ider: true,
redirection: true,
optInState: 1,
kvmAvailable: true,
winREBootSupported: true,
localPBABootSupported: true,
remoteErase: true,
pbaBootFilesPath: [],
winREBootFilesPath: {
instanceID: '',
biosBootString: '',
bootString: ''
}
} as any
devicesService.getAMTFeatures.and.returnValue(of(mockAMTFeatures))
devicesService.getAMTFeaturesCached.and.returnValue(of(mockAMTFeatures))
getDeviceSpy = devicesService.getDevice.and.returnValue(of({ guid: 'guid' } as any))
sendDeactivateSpy = devicesService.sendDeactivate.and.returnValue(of({ status: 'SUCCESS' }))
sendDeactivateErrorSpy = devicesService.sendDeactivate.and.returnValue(throwError({ error: 'Error' }))
Expand Down
4 changes: 3 additions & 1 deletion src/app/devices/device-toolbar/device-toolbar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ export class DeviceToolbarComponent implements OnInit {
}

private loadAMTFeatures(): void {
this.devicesService.getAMTFeatures(this.deviceId()).subscribe((features) => {
// Use cached features if fresher than 30s — avoids a duplicate AMT round-trip
// when the KVM/SOL component already loaded features moments before the toolbar.
this.devicesService.getAMTFeaturesCached(this.deviceId()).subscribe((features) => {
this.amtFeatures.set(features)
this.buildPowerOptions()
})
Expand Down
28 changes: 24 additions & 4 deletions src/app/devices/devices.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { HttpClient } from '@angular/common/http'
import { EventEmitter, Injectable, inject } from '@angular/core'
import { Observable, Subject, BehaviorSubject } from 'rxjs'
import { Observable, Subject, BehaviorSubject, of } from 'rxjs'
import { catchError, map, tap } from 'rxjs/operators'
import { environment } from 'src/environments/environment'
import {
Expand Down Expand Up @@ -43,6 +43,9 @@ export class DevicesService {
private readonly http = inject(HttpClient)
// Reactive AMT features stream, keyed by deviceId
private readonly amtFeaturesStreams = new Map<string, BehaviorSubject<AMTFeaturesResponse | null>>()
// Timestamps for TTL-based features cache — configured via environment.amtFeaturesCacheTtlMs, capped at 3 min
private readonly featuresTimestamps = new Map<string, number>()
private readonly FEATURES_TTL_MS = Math.min(environment.amtFeaturesCacheTtlMs ?? 30_000, 180_000)

private getOrCreateFeaturesStream(deviceId: string): BehaviorSubject<AMTFeaturesResponse | null> {
if (!this.amtFeaturesStreams.has(deviceId)) {
Expand Down Expand Up @@ -265,13 +268,31 @@ export class DevicesService {

getAMTFeatures(guid: string): Observable<AMTFeaturesResponse> {
return this.http.get<AMTFeaturesResponse>(`${environment.mpsServer}/api/v1/amt/features/${guid}`).pipe(
tap((features) => this.getOrCreateFeaturesStream(guid).next(features)),
tap((features) => {
this.getOrCreateFeaturesStream(guid).next(features)
this.featuresTimestamps.set(guid, Date.now())
}),
catchError((err) => {
throw err
})
)
}

/**
* Returns cached AMT features immediately if they are fresher than ttlMs,
* otherwise falls back to a real HTTP call. Eliminates duplicate round-trips
* when the toolbar and KVM component both load features within the same session.
* TTL is read from environment.amtFeaturesCacheTtlMs (default 30 s, max 3 min).
*/
getAMTFeaturesCached(guid: string, ttlMs = this.FEATURES_TTL_MS): Observable<AMTFeaturesResponse> {
const cached = this.getOrCreateFeaturesStream(guid).value
const ts = this.featuresTimestamps.get(guid) ?? 0
if (cached !== null && Date.now() - ts < ttlMs) {
return of(cached)
}
return this.getAMTFeatures(guid)
}

getAlarmOccurrences(guid: string): Observable<IPSAlarmClockOccurrence[]> {
return this.http
.get<IPSAlarmClockOccurrence[]>(`${environment.mpsServer}/api/v1/amt/alarmOccurrences/${guid}`)
Expand Down Expand Up @@ -366,8 +387,7 @@ export class DevicesService {
}

getDevice(guid: string): Observable<Device> {
const query = `${environment.mpsServer}/api/v1/devices/${guid}`
return this.http.get<Device>(query).pipe(
return this.http.get<Device>(`${environment.mpsServer}/api/v1/devices/${guid}`).pipe(
catchError((err) => {
throw err
})
Expand Down
1 change: 1 addition & 0 deletions src/environments/environment.enterprise.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const environment = {
mpsServer: 'http://localhost:8181',
rpsServer: 'http://localhost:8181',
vault: '',
amtFeaturesCacheTtlMs: 30_000, // 30 s default; max 3 min (180_000)
auth: {
clientId: '##CLIENTID##',
issuer: '##ISSUER##',
Expand Down
1 change: 1 addition & 0 deletions src/environments/environment.enterprise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const environment = {
mpsServer: '##CONSOLE_SERVER_API##',
rpsServer: '##CONSOLE_SERVER_API##',
vault: '##VAULT_SERVER##',
amtFeaturesCacheTtlMs: 30_000, // 30 s default; max 3 min (180_000)
auth: {
clientId: '##CLIENTID##',
issuer: '##ISSUER##',
Expand Down
1 change: 1 addition & 0 deletions src/environments/environment.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export const environment = {
mpsServer: '##MPS_SERVER##',
rpsServer: '##RPS_SERVER##',
vault: '##VAULT_SERVER##',
amtFeaturesCacheTtlMs: 30_000, // 30 s default; max 3 min (180_000)
auth: {}
}
1 change: 1 addition & 0 deletions src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const environment = {
mpsServer: 'http://localhost:3000',
rpsServer: 'http://localhost:8081',
vault: 'http://localhost/vault',
amtFeaturesCacheTtlMs: 30_000, // 30 s default; max 3 min (180_000)
auth: {
clientId: '',
issuer: '',
Expand Down
Loading