Merge pull request #648 from atmire/request-by-uuid-issue

Request by UUID issue
This commit is contained in:
Tim Donohue
2020-04-13 11:34:53 -05:00
committed by GitHub
2 changed files with 78 additions and 19 deletions

View File

@@ -22,6 +22,7 @@ import {
} from './request.models'; } from './request.models';
import { RequestEntry } from './request.reducer'; import { RequestEntry } from './request.reducer';
import { RequestService } from './request.service'; import { RequestService } from './request.service';
import { parseJsonSchemaToCommandDescription } from '@angular/cli/utilities/json-schema';
describe('RequestService', () => { describe('RequestService', () => {
let scheduler: TestScheduler; let scheduler: TestScheduler;
@@ -139,13 +140,21 @@ describe('RequestService', () => {
describe('getByUUID', () => { describe('getByUUID', () => {
describe('if the request with the specified UUID exists in the store', () => { describe('if the request with the specified UUID exists in the store', () => {
beforeEach(() => { beforeEach(() => {
selectSpy.and.callFake(() => { let callCounter = 0;
return () => { const responses = [
return () => hot('a', { cold('a', { // A direct hit in the request cache
a: { a: {
completed: true completed: true
} }
}); }),
cold('b', { b: undefined }), // No hit in the index
cold('c', { c: undefined }) // So no mapped hit in the request cache
];
selectSpy.and.callFake(() => {
return () => {
const response = responses[callCounter];
callCounter++;
return () => response;
}; };
}); });
}); });
@@ -162,11 +171,19 @@ describe('RequestService', () => {
}); });
}); });
describe('if the request with the specified UUID doesn\'t exist in the store', () => { describe(`if the request with the specified UUID doesn't exist in the store `, () => {
beforeEach(() => { beforeEach(() => {
let callCounter = 0;
const responses = [
cold('a', { a: undefined }), // No direct hit in the request cache
cold('b', { b: undefined }), // No hit in the index
cold('c', { c: undefined }), // So no mapped hit in the request cache
];
selectSpy.and.callFake(() => { selectSpy.and.callFake(() => {
return () => { return () => {
return () => hot('a', { a: undefined }); const response = responses[callCounter];
callCounter++;
return () => response;
}; };
}); });
}); });
@@ -174,7 +191,39 @@ describe('RequestService', () => {
it('should return an Observable of undefined', () => { it('should return an Observable of undefined', () => {
const result = service.getByUUID(testUUID); const result = service.getByUUID(testUUID);
scheduler.expectObservable(result).toBe('b', { b: undefined }); scheduler.expectObservable(result).toBe('a', { a: undefined });
});
});
describe(`if the request with the specified UUID wasn't sent, because it was already cached`, () => {
beforeEach(() => {
let callCounter = 0;
const responses = [
cold('a', { a: undefined }), // No direct hit in the request cache with that UUID
cold('b', { b: 'otherRequestUUID' }), // A hit in the index, which returns the uuid of the cached request
cold('c', { // the call to retrieve the cached request using the UUID from the index
c: {
completed: true
}
})
];
selectSpy.and.callFake(() => {
return () => {
const response = responses[callCounter];
callCounter++;
return () => response;
};
});
});
it(`it should return the cached request`, () => {
const result = service.getByUUID(testUUID);
scheduler.expectObservable(result).toBe('c', {
c: {
completed: true
}
});
}); });
}); });

View File

@@ -2,10 +2,10 @@ import { Injectable } from '@angular/core';
import { HttpHeaders } from '@angular/common/http'; import { HttpHeaders } from '@angular/common/http';
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
import { Observable, race as observableRace } from 'rxjs'; import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { filter, map, mergeMap, take } from 'rxjs/operators'; import { filter, map, mergeMap, take, switchMap, startWith } from 'rxjs/operators';
import { cloneDeep, remove } from 'lodash'; import { cloneDeep, remove } from 'lodash';
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { hasValue, isEmpty, isNotEmpty, hasValueOperator } from '../../shared/empty.util';
import { CacheableObject } from '../cache/object-cache.reducer'; import { CacheableObject } from '../cache/object-cache.reducer';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { CoreState } from '../core.reducers'; import { CoreState } from '../core.reducers';
@@ -110,15 +110,19 @@ export class RequestService {
* Retrieve a RequestEntry based on their uuid * Retrieve a RequestEntry based on their uuid
*/ */
getByUUID(uuid: string): Observable<RequestEntry> { getByUUID(uuid: string): Observable<RequestEntry> {
return observableRace( return observableCombineLatest([
this.store.pipe(select(entryFromUUIDSelector(uuid))), this.store.pipe(
select(entryFromUUIDSelector(uuid))
),
this.store.pipe( this.store.pipe(
select(originalRequestUUIDFromRequestUUIDSelector(uuid)), select(originalRequestUUIDFromRequestUUIDSelector(uuid)),
mergeMap((originalUUID) => { switchMap((originalUUID) => {
return this.store.pipe(select(entryFromUUIDSelector(originalUUID))) return this.store.pipe(select(entryFromUUIDSelector(originalUUID)))
}, },
)) ),
).pipe( ),
]).pipe(
map((entries: RequestEntry[]) => entries.find((entry: RequestEntry) => hasValue(entry))),
map((entry: RequestEntry) => { map((entry: RequestEntry) => {
// Headers break after being retrieved from the store (because of lazy initialization) // Headers break after being retrieved from the store (because of lazy initialization)
// Combining them with a new object fixes this issue // Combining them with a new object fixes this issue
@@ -137,7 +141,13 @@ export class RequestService {
getByHref(href: string): Observable<RequestEntry> { getByHref(href: string): Observable<RequestEntry> {
return this.store.pipe( return this.store.pipe(
select(uuidFromHrefSelector(href)), select(uuidFromHrefSelector(href)),
mergeMap((uuid: string) => this.getByUUID(uuid)) mergeMap((uuid: string) => {
if (isNotEmpty(uuid)) {
return this.getByUUID(uuid);
} else {
return [undefined];
}
})
); );
} }