Skip to content

Commit bd6c99d

Browse files
artlowelgithub-actions[bot]
authored andcommitted
ensure HALEndpointService doesn't use stale requests
(cherry picked from commit 38752d9)
1 parent 92a10ce commit bd6c99d

3 files changed

Lines changed: 16 additions & 12 deletions

File tree

src/app/core/server-check/server-check.guard.spec.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import SpyObj = jasmine.SpyObj;
99
describe('ServerCheckGuard', () => {
1010
let guard: ServerCheckGuard;
1111
let router: Router;
12-
const eventSubject = new ReplaySubject<RouterEvent>(1);
12+
let eventSubject: ReplaySubject<RouterEvent>;
1313
let rootDataServiceStub: SpyObj<RootDataService>;
1414
let testScheduler: TestScheduler;
1515
let redirectUrlTree: UrlTree;
@@ -24,6 +24,7 @@ describe('ServerCheckGuard', () => {
2424
findRoot: jasmine.createSpy('findRoot')
2525
});
2626
redirectUrlTree = new UrlTree();
27+
eventSubject = new ReplaySubject<RouterEvent>(1);
2728
router = {
2829
events: eventSubject.asObservable(),
2930
navigateByUrl: jasmine.createSpy('navigateByUrl'),
@@ -64,10 +65,10 @@ describe('ServerCheckGuard', () => {
6465
});
6566

6667
describe(`listenForRouteChanges`, () => {
67-
it(`should retrieve the root endpoint, without using the cache, when the method is first called`, () => {
68+
it(`should invalidate the root cache, when the method is first called`, () => {
6869
testScheduler.run(() => {
6970
guard.listenForRouteChanges();
70-
expect(rootDataServiceStub.findRoot).toHaveBeenCalledWith(false);
71+
expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(1);
7172
});
7273
});
7374

@@ -80,7 +81,8 @@ describe('ServerCheckGuard', () => {
8081
eventSubject.next(new NavigationEnd(2,'', ''));
8182
eventSubject.next(new NavigationStart(3,''));
8283
});
83-
expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(3);
84+
// once when the method is first called, and then 3 times for NavigationStart events
85+
expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(1 + 3);
8486
});
8587
});
8688
});

src/app/core/server-check/server-check.guard.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,8 @@ export class ServerCheckGuard implements CanActivateChild {
5353
*/
5454
listenForRouteChanges(): void {
5555
// we'll always be too late for the first NavigationStart event with the router subscribe below,
56-
// so this statement is for the very first route operation. A `find` without using the cache,
57-
// rather than an invalidateRootCache, because invalidating as the app is bootstrapping can
58-
// break other features
59-
this.rootDataService.findRoot(false);
56+
// so this statement is for the very first route operation.
57+
this.rootDataService.invalidateRootCache();
6058

6159
this.router.events.pipe(
6260
filter(event => event instanceof NavigationStart),

src/app/core/shared/hal-endpoint.service.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Observable } from 'rxjs';
2-
import { distinctUntilChanged, map, startWith, switchMap, take } from 'rxjs/operators';
2+
import { distinctUntilChanged, map, startWith, switchMap, take, skipWhile } from 'rxjs/operators';
33
import { RequestService } from '../data/request.service';
44
import { EndpointMapRequest } from '../data/request.models';
55
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
@@ -9,7 +9,7 @@ import { EndpointMap } from '../cache/response.models';
99
import { getFirstCompletedRemoteData } from './operators';
1010
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
1111
import { RemoteData } from '../data/remote-data';
12-
import { UnCacheableObject } from './uncacheable-object.model';
12+
import { CacheableObject } from '../cache/cacheable-object.model';
1313

1414
@Injectable()
1515
export class HALEndpointService {
@@ -33,9 +33,13 @@ export class HALEndpointService {
3333

3434
this.requestService.send(request, true);
3535

36-
return this.rdbService.buildFromHref<UnCacheableObject>(href).pipe(
36+
return this.rdbService.buildFromHref<CacheableObject>(href).pipe(
37+
// This skip ensures that if a stale object is present in the cache when you do a
38+
// call it isn't immediately returned, but we wait until the remote data for the new request
39+
// is created.
40+
skipWhile((rd: RemoteData<CacheableObject>) => rd.isStale),
3741
getFirstCompletedRemoteData(),
38-
map((response: RemoteData<UnCacheableObject>) => {
42+
map((response: RemoteData<CacheableObject>) => {
3943
if (hasValue(response.payload)) {
4044
return response.payload._links;
4145
} else {

0 commit comments

Comments
 (0)