Skip to content

Commit

Permalink
ensure HALEndpointService doesn't use stale requests
Browse files Browse the repository at this point in the history
(cherry picked from commit 38752d9)
  • Loading branch information
artlowel authored and github-actions[bot] committed Jan 8, 2024
1 parent 92a10ce commit bd6c99d
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 12 deletions.
10 changes: 6 additions & 4 deletions src/app/core/server-check/server-check.guard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SpyObj = jasmine.SpyObj;
describe('ServerCheckGuard', () => {
let guard: ServerCheckGuard;
let router: Router;
const eventSubject = new ReplaySubject<RouterEvent>(1);
let eventSubject: ReplaySubject<RouterEvent>;
let rootDataServiceStub: SpyObj<RootDataService>;
let testScheduler: TestScheduler;
let redirectUrlTree: UrlTree;
Expand All @@ -24,6 +24,7 @@ describe('ServerCheckGuard', () => {
findRoot: jasmine.createSpy('findRoot')
});
redirectUrlTree = new UrlTree();
eventSubject = new ReplaySubject<RouterEvent>(1);
router = {
events: eventSubject.asObservable(),
navigateByUrl: jasmine.createSpy('navigateByUrl'),
Expand Down Expand Up @@ -64,10 +65,10 @@ describe('ServerCheckGuard', () => {
});

describe(`listenForRouteChanges`, () => {
it(`should retrieve the root endpoint, without using the cache, when the method is first called`, () => {
it(`should invalidate the root cache, when the method is first called`, () => {
testScheduler.run(() => {
guard.listenForRouteChanges();
expect(rootDataServiceStub.findRoot).toHaveBeenCalledWith(false);
expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(1);
});
});

Expand All @@ -80,7 +81,8 @@ describe('ServerCheckGuard', () => {
eventSubject.next(new NavigationEnd(2,'', ''));
eventSubject.next(new NavigationStart(3,''));
});
expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(3);
// once when the method is first called, and then 3 times for NavigationStart events
expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(1 + 3);
});
});
});
6 changes: 2 additions & 4 deletions src/app/core/server-check/server-check.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ export class ServerCheckGuard implements CanActivateChild {
*/
listenForRouteChanges(): void {
// we'll always be too late for the first NavigationStart event with the router subscribe below,
// so this statement is for the very first route operation. A `find` without using the cache,
// rather than an invalidateRootCache, because invalidating as the app is bootstrapping can
// break other features
this.rootDataService.findRoot(false);
// so this statement is for the very first route operation.
this.rootDataService.invalidateRootCache();

this.router.events.pipe(
filter(event => event instanceof NavigationStart),
Expand Down
12 changes: 8 additions & 4 deletions src/app/core/shared/hal-endpoint.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Observable } from 'rxjs';
import { distinctUntilChanged, map, startWith, switchMap, take } from 'rxjs/operators';
import { distinctUntilChanged, map, startWith, switchMap, take, skipWhile } from 'rxjs/operators';
import { RequestService } from '../data/request.service';
import { EndpointMapRequest } from '../data/request.models';
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
Expand All @@ -9,7 +9,7 @@ import { EndpointMap } from '../cache/response.models';
import { getFirstCompletedRemoteData } from './operators';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { RemoteData } from '../data/remote-data';
import { UnCacheableObject } from './uncacheable-object.model';
import { CacheableObject } from '../cache/cacheable-object.model';

@Injectable()
export class HALEndpointService {
Expand All @@ -33,9 +33,13 @@ export class HALEndpointService {

this.requestService.send(request, true);

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

0 comments on commit bd6c99d

Please sign in to comment.