forked from hazza/dspace-angular
Removed the handle index (not needed because the uuid index will always be used internally) and all associated code.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { LookupGuard } from './lookup-guard';
|
import { LookupGuard } from './lookup-guard';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { IdentifierType } from '../core/index/index.reducer';
|
import { IdentifierType } from '../core/data/request.models';
|
||||||
|
|
||||||
describe('LookupGuard', () => {
|
describe('LookupGuard', () => {
|
||||||
let dsoService: any;
|
let dsoService: any;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { IdentifierType } from '../core/index/index.reducer';
|
import { IdentifierType } from '../core/data/request.models';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { RemoteData } from '../core/data/remote-data';
|
import { RemoteData } from '../core/data/remote-data';
|
||||||
|
9
src/app/core/cache/object-cache.service.ts
vendored
9
src/app/core/cache/object-cache.service.ts
vendored
@@ -21,7 +21,6 @@ import {
|
|||||||
import { CacheableObject, ObjectCacheEntry, ObjectCacheState } from './object-cache.reducer';
|
import { CacheableObject, ObjectCacheEntry, ObjectCacheState } from './object-cache.reducer';
|
||||||
import { AddToSSBAction } from './server-sync-buffer.actions';
|
import { AddToSSBAction } from './server-sync-buffer.actions';
|
||||||
import { getMapsToType } from './builders/build-decorators';
|
import { getMapsToType } from './builders/build-decorators';
|
||||||
import { IdentifierType } from '../index/index.reducer';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base selector function to select the object cache in the store
|
* The base selector function to select the object cache in the store
|
||||||
@@ -81,10 +80,10 @@ export class ObjectCacheService {
|
|||||||
* @return Observable<NormalizedObject<T>>
|
* @return Observable<NormalizedObject<T>>
|
||||||
* An observable of the requested object in normalized form
|
* An observable of the requested object in normalized form
|
||||||
*/
|
*/
|
||||||
getObjectByID<T extends CacheableObject>(id: string, identifierType: IdentifierType = IdentifierType.UUID):
|
getObjectByID<T extends CacheableObject>(id: string):
|
||||||
Observable<NormalizedObject<T>> {
|
Observable<NormalizedObject<T>> {
|
||||||
return this.store.pipe(
|
return this.store.pipe(
|
||||||
select(selfLinkFromUuidSelector(id, identifierType)),
|
select(selfLinkFromUuidSelector(id)),
|
||||||
mergeMap((selfLink: string) => this.getObjectBySelfLink(selfLink)
|
mergeMap((selfLink: string) => this.getObjectBySelfLink(selfLink)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -196,11 +195,11 @@ export class ObjectCacheService {
|
|||||||
* true if the object with the specified UUID is cached,
|
* true if the object with the specified UUID is cached,
|
||||||
* false otherwise
|
* false otherwise
|
||||||
*/
|
*/
|
||||||
hasById(id: string, identifierType: IdentifierType = IdentifierType.UUID): boolean {
|
hasById(id: string): boolean {
|
||||||
let result: boolean;
|
let result: boolean;
|
||||||
|
|
||||||
this.store.pipe(
|
this.store.pipe(
|
||||||
select(selfLinkFromUuidSelector(id, identifierType)),
|
select(selfLinkFromUuidSelector(id)),
|
||||||
take(1)
|
take(1)
|
||||||
).subscribe((selfLink: string) => result = this.hasBySelfLink(selfLink));
|
).subscribe((selfLink: string) => result = this.hasBySelfLink(selfLink));
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { ObjectCacheEffects } from './cache/object-cache.effects';
|
import { ObjectCacheEffects } from './cache/object-cache.effects';
|
||||||
import { IdentifierIndexEffects } from './index/index.effects';
|
import { UUIDIndexEffects } from './index/index.effects';
|
||||||
import { RequestEffects } from './data/request.effects';
|
import { RequestEffects } from './data/request.effects';
|
||||||
import { AuthEffects } from './auth/auth.effects';
|
import { AuthEffects } from './auth/auth.effects';
|
||||||
import { JsonPatchOperationsEffects } from './json-patch/json-patch-operations.effects';
|
import { JsonPatchOperationsEffects } from './json-patch/json-patch-operations.effects';
|
||||||
@@ -10,7 +10,7 @@ import { RouteEffects } from './services/route.effects';
|
|||||||
export const coreEffects = [
|
export const coreEffects = [
|
||||||
RequestEffects,
|
RequestEffects,
|
||||||
ObjectCacheEffects,
|
ObjectCacheEffects,
|
||||||
IdentifierIndexEffects,
|
UUIDIndexEffects,
|
||||||
AuthEffects,
|
AuthEffects,
|
||||||
JsonPatchOperationsEffects,
|
JsonPatchOperationsEffects,
|
||||||
ServerSyncBufferEffects,
|
ServerSyncBufferEffects,
|
||||||
|
@@ -37,7 +37,6 @@ import { NormalizedObjectBuildService } from '../cache/builders/normalized-objec
|
|||||||
import { ChangeAnalyzer } from './change-analyzer';
|
import { ChangeAnalyzer } from './change-analyzer';
|
||||||
import { RestRequestMethod } from './rest-request-method';
|
import { RestRequestMethod } from './rest-request-method';
|
||||||
import { getMapsToType } from '../cache/builders/build-decorators';
|
import { getMapsToType } from '../cache/builders/build-decorators';
|
||||||
import { IdentifierType } from '../index/index.reducer';
|
|
||||||
|
|
||||||
export abstract class DataService<T extends CacheableObject> {
|
export abstract class DataService<T extends CacheableObject> {
|
||||||
protected abstract requestService: RequestService;
|
protected abstract requestService: RequestService;
|
||||||
@@ -147,19 +146,15 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
return `${endpoint}/${resourceID}`;
|
return `${endpoint}/${resourceID}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
findById(id: string, identifierType: IdentifierType = IdentifierType.UUID): Observable<RemoteData<T>> {
|
findById(id: string): Observable<RemoteData<T>> {
|
||||||
let hrefObs;
|
|
||||||
if (identifierType === IdentifierType.UUID) {
|
const hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
|
||||||
hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
|
map((endpoint: string) => this.getIDHref(endpoint, encodeURIComponent(id))))
|
||||||
map((endpoint: string) => this.getIDHref(endpoint, id)));
|
|
||||||
} else if (identifierType === IdentifierType.HANDLE) {
|
|
||||||
hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
|
|
||||||
map((endpoint: string) => this.getIDHref(endpoint, encodeURIComponent(id))));
|
|
||||||
}
|
|
||||||
hrefObs.pipe(
|
hrefObs.pipe(
|
||||||
find((href: string) => hasValue(href)))
|
find((href: string) => hasValue(href)))
|
||||||
.subscribe((href: string) => {
|
.subscribe((href: string) => {
|
||||||
const request = new FindByIDRequest(this.requestService.generateRequestId(), href, id, identifierType);
|
const request = new FindByIDRequest(this.requestService.generateRequestId(), href, id);
|
||||||
this.requestService.configure(request, this.forceBypassCache);
|
this.requestService.configure(request, this.forceBypassCache);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -2,13 +2,12 @@ import { cold, getTestScheduler } from 'jasmine-marbles';
|
|||||||
import { TestScheduler } from 'rxjs/testing';
|
import { TestScheduler } from 'rxjs/testing';
|
||||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
import { FindByIDRequest } from './request.models';
|
import { FindByIDRequest, IdentifierType } from './request.models';
|
||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||||
import { IdentifierType } from '../index/index.reducer';
|
|
||||||
import { DsoRedirectDataService } from './dso-redirect-data.service';
|
import { DsoRedirectDataService } from './dso-redirect-data.service';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { CoreState } from '../core.reducers';
|
import { CoreState } from '../core.reducers';
|
||||||
@@ -111,7 +110,7 @@ describe('DsoRedirectDataService', () => {
|
|||||||
scheduler.schedule(() => service.findById(dsoUUID, IdentifierType.UUID));
|
scheduler.schedule(() => service.findById(dsoUUID, IdentifierType.UUID));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestUUIDURL, dsoUUID, IdentifierType.UUID), false);
|
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestUUIDURL, dsoUUID), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should configure the proper FindByIDRequest for handle', () => {
|
it('should configure the proper FindByIDRequest for handle', () => {
|
||||||
@@ -119,7 +118,7 @@ describe('DsoRedirectDataService', () => {
|
|||||||
scheduler.schedule(() => service.findById(dsoHandle, IdentifierType.HANDLE));
|
scheduler.schedule(() => service.findById(dsoHandle, IdentifierType.HANDLE));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestHandleURL, dsoHandle, IdentifierType.HANDLE), false);
|
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestHandleURL, dsoHandle), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to item route', () => {
|
it('should navigate to item route', () => {
|
||||||
|
@@ -8,9 +8,8 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv
|
|||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { CoreState } from '../core.reducers';
|
import { CoreState } from '../core.reducers';
|
||||||
import { FindAllOptions, FindByIDRequest } from './request.models';
|
import { FindAllOptions, FindByIDRequest, IdentifierType } from './request.models';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { IdentifierType } from '../index/index.reducer';
|
|
||||||
import { RemoteData } from './remote-data';
|
import { RemoteData } from './remote-data';
|
||||||
import { DSOChangeAnalyzer } from './dso-change-analyzer.service';
|
import { DSOChangeAnalyzer } from './dso-change-analyzer.service';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
@@ -61,7 +60,7 @@ export class DsoRedirectDataService extends DataService<any> {
|
|||||||
|
|
||||||
findById(id: string, identifierType = IdentifierType.UUID): Observable<RemoteData<FindByIDRequest>> {
|
findById(id: string, identifierType = IdentifierType.UUID): Observable<RemoteData<FindByIDRequest>> {
|
||||||
this.setLinkPath(identifierType);
|
this.setLinkPath(identifierType);
|
||||||
return super.findById(id, identifierType).pipe(
|
return super.findById(id).pipe(
|
||||||
getFinishedRemoteData(),
|
getFinishedRemoteData(),
|
||||||
take(1),
|
take(1),
|
||||||
tap((response) => {
|
tap((response) => {
|
||||||
|
@@ -10,7 +10,6 @@ import { ObjectCacheService } from '../cache/object-cache.service';
|
|||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||||
import { IdentifierType } from '../index/index.reducer';
|
|
||||||
|
|
||||||
describe('DSpaceObjectDataService', () => {
|
describe('DSpaceObjectDataService', () => {
|
||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
@@ -73,7 +72,7 @@ describe('DSpaceObjectDataService', () => {
|
|||||||
scheduler.schedule(() => service.findById(testObject.uuid));
|
scheduler.schedule(() => service.findById(testObject.uuid));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestURL, testObject.uuid, IdentifierType.UUID), false);
|
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestURL, testObject.uuid), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a RemoteData<DSpaceObject> for the object with the given ID', () => {
|
it('should return a RemoteData<DSpaceObject> for the object with the given ID', () => {
|
||||||
|
@@ -19,10 +19,15 @@ import { MetadatafieldParsingService } from './metadatafield-parsing.service';
|
|||||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||||
import { TaskResponseParsingService } from '../tasks/task-response-parsing.service';
|
import { TaskResponseParsingService } from '../tasks/task-response-parsing.service';
|
||||||
import { MappedCollectionsReponseParsingService } from './mapped-collections-reponse-parsing.service';
|
import { MappedCollectionsReponseParsingService } from './mapped-collections-reponse-parsing.service';
|
||||||
import { IdentifierType } from '../index/index.reducer';
|
|
||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
|
|
||||||
|
// uuid and handle requests have separate endpoints
|
||||||
|
export enum IdentifierType {
|
||||||
|
UUID ='uuid',
|
||||||
|
HANDLE = 'handle'
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class RestRequest {
|
export abstract class RestRequest {
|
||||||
public responseMsToLive = 0;
|
public responseMsToLive = 0;
|
||||||
constructor(
|
constructor(
|
||||||
@@ -126,8 +131,7 @@ export class FindByIDRequest extends GetRequest {
|
|||||||
constructor(
|
constructor(
|
||||||
uuid: string,
|
uuid: string,
|
||||||
href: string,
|
href: string,
|
||||||
public resourceID: string,
|
public resourceID: string
|
||||||
public identifierType?: IdentifierType
|
|
||||||
) {
|
) {
|
||||||
super(uuid, href);
|
super(uuid, href);
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ import { UUIDService } from '../shared/uuid.service';
|
|||||||
import { RequestConfigureAction, RequestExecuteAction } from './request.actions';
|
import { RequestConfigureAction, RequestExecuteAction } from './request.actions';
|
||||||
import {
|
import {
|
||||||
DeleteRequest,
|
DeleteRequest,
|
||||||
FindByIDRequest,
|
|
||||||
GetRequest,
|
GetRequest,
|
||||||
HeadRequest,
|
HeadRequest,
|
||||||
OptionsRequest,
|
OptionsRequest,
|
||||||
@@ -22,7 +21,6 @@ import {
|
|||||||
} from './request.models';
|
} from './request.models';
|
||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
import { TestScheduler } from 'rxjs/testing';
|
import { TestScheduler } from 'rxjs/testing';
|
||||||
import { IdentifierType } from '../index/index.reducer';
|
|
||||||
|
|
||||||
describe('RequestService', () => {
|
describe('RequestService', () => {
|
||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
@@ -40,7 +38,6 @@ describe('RequestService', () => {
|
|||||||
const testDeleteRequest = new DeleteRequest(testUUID, testHref);
|
const testDeleteRequest = new DeleteRequest(testUUID, testHref);
|
||||||
const testOptionsRequest = new OptionsRequest(testUUID, testHref);
|
const testOptionsRequest = new OptionsRequest(testUUID, testHref);
|
||||||
const testHeadRequest = new HeadRequest(testUUID, testHref);
|
const testHeadRequest = new HeadRequest(testUUID, testHref);
|
||||||
const testFindByIdRequest = new FindByIDRequest(testUUID, testHref, testUUID, IdentifierType.UUID);
|
|
||||||
const testPatchRequest = new PatchRequest(testUUID, testHref);
|
const testPatchRequest = new PatchRequest(testUUID, testHref);
|
||||||
let selectSpy;
|
let selectSpy;
|
||||||
|
|
||||||
@@ -309,14 +306,6 @@ describe('RequestService', () => {
|
|||||||
const result = serviceAsAny.isCachedOrPending(testGetRequest);
|
const result = serviceAsAny.isCachedOrPending(testGetRequest);
|
||||||
const expected = true;
|
const expected = true;
|
||||||
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
it('should return true for instance of FindByIdRequest', () => {
|
|
||||||
(objectCache.hasBySelfLink as any).and.returnValue(false);
|
|
||||||
const result = serviceAsAny.isCachedOrPending(testFindByIdRequest);
|
|
||||||
expect(objectCache.hasById).toHaveBeenCalledWith(testUUID, IdentifierType.UUID);
|
|
||||||
const expected = true;
|
|
||||||
|
|
||||||
expect(result).toEqual(expected);
|
expect(result).toEqual(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -11,7 +11,7 @@ import { hasValue, isEmpty, isNotEmpty } 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';
|
||||||
import { IdentifierType, IndexState, MetaIndexState, REQUEST, UUID_MAPPING } from '../index/index.reducer';
|
import { IndexName, IndexState, MetaIndexState } from '../index/index.reducer';
|
||||||
import {
|
import {
|
||||||
originalRequestUUIDFromRequestUUIDSelector,
|
originalRequestUUIDFromRequestUUIDSelector,
|
||||||
requestIndexSelector,
|
requestIndexSelector,
|
||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
} from '../index/index.selectors';
|
} from '../index/index.selectors';
|
||||||
import { UUIDService } from '../shared/uuid.service';
|
import { UUIDService } from '../shared/uuid.service';
|
||||||
import { RequestConfigureAction, RequestExecuteAction, RequestRemoveAction } from './request.actions';
|
import { RequestConfigureAction, RequestExecuteAction, RequestRemoveAction } from './request.actions';
|
||||||
import { FindByIDRequest, GetRequest, RestRequest } from './request.models';
|
import { GetRequest, RestRequest } from './request.models';
|
||||||
import { RequestEntry, RequestState } from './request.reducer';
|
import { RequestEntry, RequestState } from './request.reducer';
|
||||||
import { CommitSSBAction } from '../cache/server-sync-buffer.actions';
|
import { CommitSSBAction } from '../cache/server-sync-buffer.actions';
|
||||||
import { RestRequestMethod } from './rest-request-method';
|
import { RestRequestMethod } from './rest-request-method';
|
||||||
@@ -162,7 +162,7 @@ export class RequestService {
|
|||||||
filter((entry) => hasValue(entry)),
|
filter((entry) => hasValue(entry)),
|
||||||
take(1)
|
take(1)
|
||||||
).subscribe((entry) => {
|
).subscribe((entry) => {
|
||||||
return this.store.dispatch(new AddToIndexAction(UUID_MAPPING, request.uuid, entry.request.uuid))
|
return this.store.dispatch(new AddToIndexAction(IndexName.UUID_MAPPING, request.uuid, entry.request.uuid))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ export class RequestService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.requestsOnTheirWayToTheStore = this.requestsOnTheirWayToTheStore.filter((reqHref: string) => reqHref.indexOf(href) < 0);
|
this.requestsOnTheirWayToTheStore = this.requestsOnTheirWayToTheStore.filter((reqHref: string) => reqHref.indexOf(href) < 0);
|
||||||
this.indexStore.dispatch(new RemoveFromIndexBySubstringAction(REQUEST, href));
|
this.indexStore.dispatch(new RemoveFromIndexBySubstringAction(IndexName.REQUEST, href));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,14 +225,7 @@ export class RequestService {
|
|||||||
private isCachedOrPending(request: GetRequest): boolean {
|
private isCachedOrPending(request: GetRequest): boolean {
|
||||||
const inReqCache = this.hasByHref(request.href);
|
const inReqCache = this.hasByHref(request.href);
|
||||||
const inObjCache = this.objectCache.hasBySelfLink(request.href);
|
const inObjCache = this.objectCache.hasBySelfLink(request.href);
|
||||||
let inObjIdCache = false;
|
const isCached = inReqCache || inObjCache;
|
||||||
if (request instanceof FindByIDRequest) {
|
|
||||||
const req = request as FindByIDRequest;
|
|
||||||
if (hasValue(req.identifierType && hasValue(req.resourceID))) {
|
|
||||||
inObjIdCache = this.objectCache.hasById(req.resourceID, req.identifierType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const isCached = inReqCache || inObjCache || inObjIdCache;
|
|
||||||
const isPending = this.isPending(request);
|
const isPending = this.isPending(request);
|
||||||
return isCached || isPending;
|
return isCached || isPending;
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { type } from '../../shared/ngrx/type';
|
import { type } from '../../shared/ngrx/type';
|
||||||
import { } from './index.reducer';
|
import { IndexName } from './index.reducer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of HrefIndexAction type definitions
|
* The list of HrefIndexAction type definitions
|
||||||
@@ -19,7 +19,7 @@ export const IndexActionTypes = {
|
|||||||
export class AddToIndexAction implements Action {
|
export class AddToIndexAction implements Action {
|
||||||
type = IndexActionTypes.ADD;
|
type = IndexActionTypes.ADD;
|
||||||
payload: {
|
payload: {
|
||||||
name: string;
|
name: IndexName;
|
||||||
value: string;
|
value: string;
|
||||||
key: string;
|
key: string;
|
||||||
};
|
};
|
||||||
@@ -34,7 +34,7 @@ export class AddToIndexAction implements Action {
|
|||||||
* @param value
|
* @param value
|
||||||
* the self link of the resource the key belongs to
|
* the self link of the resource the key belongs to
|
||||||
*/
|
*/
|
||||||
constructor(name: string, key: string, value: string) {
|
constructor(name: IndexName, key: string, value: string) {
|
||||||
this.payload = { name, key, value };
|
this.payload = { name, key, value };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ export class AddToIndexAction implements Action {
|
|||||||
export class RemoveFromIndexByValueAction implements Action {
|
export class RemoveFromIndexByValueAction implements Action {
|
||||||
type = IndexActionTypes.REMOVE_BY_VALUE;
|
type = IndexActionTypes.REMOVE_BY_VALUE;
|
||||||
payload: {
|
payload: {
|
||||||
name: string,
|
name: IndexName,
|
||||||
value: string
|
value: string
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ export class RemoveFromIndexByValueAction implements Action {
|
|||||||
* @param value
|
* @param value
|
||||||
* the value to remove the UUID for
|
* the value to remove the UUID for
|
||||||
*/
|
*/
|
||||||
constructor(name: string, value: string) {
|
constructor(name: IndexName, value: string) {
|
||||||
this.payload = { name, value };
|
this.payload = { name, value };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ export class RemoveFromIndexByValueAction implements Action {
|
|||||||
export class RemoveFromIndexBySubstringAction implements Action {
|
export class RemoveFromIndexBySubstringAction implements Action {
|
||||||
type = IndexActionTypes.REMOVE_BY_SUBSTRING;
|
type = IndexActionTypes.REMOVE_BY_SUBSTRING;
|
||||||
payload: {
|
payload: {
|
||||||
name: string,
|
name: IndexName,
|
||||||
value: string
|
value: string
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ export class RemoveFromIndexBySubstringAction implements Action {
|
|||||||
* @param value
|
* @param value
|
||||||
* the value to remove the UUID for
|
* the value to remove the UUID for
|
||||||
*/
|
*/
|
||||||
constructor(name: string, value: string) {
|
constructor(name: IndexName, value: string) {
|
||||||
this.payload = { name, value };
|
this.payload = { name, value };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,55 +10,31 @@ import {
|
|||||||
import { RequestActionTypes, RequestConfigureAction } from '../data/request.actions';
|
import { RequestActionTypes, RequestConfigureAction } from '../data/request.actions';
|
||||||
import { AddToIndexAction, RemoveFromIndexByValueAction } from './index.actions';
|
import { AddToIndexAction, RemoveFromIndexByValueAction } from './index.actions';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import { getIdentiferByIndexName, IdentifierType, REQUEST } from './index.reducer';
|
import { IndexName } from './index.reducer';
|
||||||
import { RestRequestMethod } from '../data/rest-request-method';
|
import { RestRequestMethod } from '../data/rest-request-method';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IdentifierIndexEffects {
|
export class UUIDIndexEffects {
|
||||||
|
|
||||||
@Effect() addObjectByUUID$ = this.actions$
|
@Effect() addObject$ = this.actions$
|
||||||
.pipe(
|
.pipe(
|
||||||
ofType(ObjectCacheActionTypes.ADD),
|
ofType(ObjectCacheActionTypes.ADD),
|
||||||
filter((action: AddToObjectCacheAction) => hasValue(action.payload.objectToCache.uuid)),
|
filter((action: AddToObjectCacheAction) => hasValue(action.payload.objectToCache.uuid)),
|
||||||
map((action: AddToObjectCacheAction) => {
|
map((action: AddToObjectCacheAction) => {
|
||||||
return new AddToIndexAction(
|
return new AddToIndexAction(
|
||||||
getIdentiferByIndexName(IdentifierType.UUID),
|
IndexName.OBJECT,
|
||||||
action.payload.objectToCache.uuid,
|
action.payload.objectToCache.uuid,
|
||||||
action.payload.objectToCache.self
|
action.payload.objectToCache.self
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@Effect() addObjectByHandle$ = this.actions$
|
@Effect() removeObject$ = this.actions$
|
||||||
.pipe(
|
|
||||||
ofType(ObjectCacheActionTypes.ADD),
|
|
||||||
filter((action: AddToObjectCacheAction) => hasValue(action.payload.objectToCache.handle)),
|
|
||||||
map((action: AddToObjectCacheAction) => {
|
|
||||||
return new AddToIndexAction(
|
|
||||||
getIdentiferByIndexName(IdentifierType.HANDLE),
|
|
||||||
action.payload.objectToCache.handle,
|
|
||||||
action.payload.objectToCache.self
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
@Effect() removeObjectByUUID$ = this.actions$
|
|
||||||
.pipe(
|
.pipe(
|
||||||
ofType(ObjectCacheActionTypes.REMOVE),
|
ofType(ObjectCacheActionTypes.REMOVE),
|
||||||
map((action: RemoveFromObjectCacheAction) => {
|
map((action: RemoveFromObjectCacheAction) => {
|
||||||
return new RemoveFromIndexByValueAction(
|
return new RemoveFromIndexByValueAction(
|
||||||
getIdentiferByIndexName(IdentifierType.UUID),
|
IndexName.OBJECT,
|
||||||
action.payload
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
@Effect() removeObjectByHandle$ = this.actions$
|
|
||||||
.pipe(
|
|
||||||
ofType(ObjectCacheActionTypes.REMOVE),
|
|
||||||
map((action: RemoveFromObjectCacheAction) => {
|
|
||||||
return new RemoveFromIndexByValueAction(
|
|
||||||
getIdentiferByIndexName(IdentifierType.HANDLE),
|
|
||||||
action.payload
|
action.payload
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -70,7 +46,7 @@ export class IdentifierIndexEffects {
|
|||||||
filter((action: RequestConfigureAction) => action.payload.method === RestRequestMethod.GET),
|
filter((action: RequestConfigureAction) => action.payload.method === RestRequestMethod.GET),
|
||||||
map((action: RequestConfigureAction) => {
|
map((action: RequestConfigureAction) => {
|
||||||
return new AddToIndexAction(
|
return new AddToIndexAction(
|
||||||
REQUEST,
|
IndexName.REQUEST,
|
||||||
action.payload.href,
|
action.payload.href,
|
||||||
action.payload.uuid
|
action.payload.uuid
|
||||||
);
|
);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import * as deepFreeze from 'deep-freeze';
|
import * as deepFreeze from 'deep-freeze';
|
||||||
|
|
||||||
import { getIdentiferByIndexName, IdentifierType, indexReducer, MetaIndexState, REQUEST, } from './index.reducer';
|
import { IndexName, indexReducer, MetaIndexState } from './index.reducer';
|
||||||
import { AddToIndexAction, RemoveFromIndexBySubstringAction, RemoveFromIndexByValueAction } from './index.actions';
|
import { AddToIndexAction, RemoveFromIndexBySubstringAction, RemoveFromIndexByValueAction } from './index.actions';
|
||||||
|
|
||||||
class NullAction extends AddToIndexAction {
|
class NullAction extends AddToIndexAction {
|
||||||
@@ -15,19 +15,14 @@ class NullAction extends AddToIndexAction {
|
|||||||
describe('requestReducer', () => {
|
describe('requestReducer', () => {
|
||||||
const key1 = '567a639f-f5ff-4126-807c-b7d0910808c8';
|
const key1 = '567a639f-f5ff-4126-807c-b7d0910808c8';
|
||||||
const key2 = '1911e8a4-6939-490c-b58b-a5d70f8d91fb';
|
const key2 = '1911e8a4-6939-490c-b58b-a5d70f8d91fb';
|
||||||
const key3 = '123456789/22';
|
|
||||||
const val1 = 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/567a639f-f5ff-4126-807c-b7d0910808c8';
|
const val1 = 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/567a639f-f5ff-4126-807c-b7d0910808c8';
|
||||||
const val2 = 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/1911e8a4-6939-490c-b58b-a5d70f8d91fb';
|
const val2 = 'https://dspace7.4science.it/dspace-spring-rest/api/core/items/1911e8a4-6939-490c-b58b-a5d70f8d91fb';
|
||||||
const uuidIndex = getIdentiferByIndexName(IdentifierType.UUID);
|
|
||||||
const handleIndex = getIdentiferByIndexName(IdentifierType.HANDLE);
|
|
||||||
const testState: MetaIndexState = {
|
const testState: MetaIndexState = {
|
||||||
'object/uuid-to-self-link/uuid': {
|
[IndexName.OBJECT]: {
|
||||||
[key1]: val1
|
[key1]: val1
|
||||||
},'object/uuid-to-self-link/handle': {
|
},[IndexName.REQUEST]: {
|
||||||
[key3]: val1
|
|
||||||
},'get-request/href-to-uuid': {
|
|
||||||
[key1]: val1
|
[key1]: val1
|
||||||
},'get-request/configured-to-cache-uuid': {
|
},[IndexName.UUID_MAPPING]: {
|
||||||
[key1]: val1
|
[key1]: val1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -50,38 +45,27 @@ describe('requestReducer', () => {
|
|||||||
it('should add the \'key\' with the corresponding \'value\' to the correct substate, in response to an ADD action', () => {
|
it('should add the \'key\' with the corresponding \'value\' to the correct substate, in response to an ADD action', () => {
|
||||||
const state = testState;
|
const state = testState;
|
||||||
|
|
||||||
const action = new AddToIndexAction(REQUEST, key2, val2);
|
const action = new AddToIndexAction(IndexName.REQUEST, key2, val2);
|
||||||
const newState = indexReducer(state, action);
|
const newState = indexReducer(state, action);
|
||||||
|
|
||||||
expect(newState[REQUEST][key2]).toEqual(val2);
|
expect(newState[IndexName.REQUEST][key2]).toEqual(val2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove the given \'value\' from its corresponding \'key\' in the correct substate, in response to a REMOVE_BY_VALUE action', () => {
|
it('should remove the given \'value\' from its corresponding \'key\' in the correct substate, in response to a REMOVE_BY_VALUE action', () => {
|
||||||
const state = testState;
|
const state = testState;
|
||||||
|
|
||||||
let action = new RemoveFromIndexByValueAction(uuidIndex, val1);
|
const action = new RemoveFromIndexByValueAction(IndexName.OBJECT, val1);
|
||||||
let newState = indexReducer(state, action);
|
const newState = indexReducer(state, action);
|
||||||
|
|
||||||
expect(newState[uuidIndex][key1]).toBeUndefined();
|
|
||||||
|
|
||||||
action = new RemoveFromIndexByValueAction(handleIndex, val1);
|
|
||||||
newState = indexReducer(state, action);
|
|
||||||
|
|
||||||
expect(newState[handleIndex][key3]).toBeUndefined();
|
|
||||||
|
|
||||||
|
expect(newState[IndexName.OBJECT][key1]).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove the given \'value\' from its corresponding \'key\' in the correct substate, in response to a REMOVE_BY_SUBSTRING action', () => {
|
it('should remove the given \'value\' from its corresponding \'key\' in the correct substate, in response to a REMOVE_BY_SUBSTRING action', () => {
|
||||||
const state = testState;
|
const state = testState;
|
||||||
|
|
||||||
let action = new RemoveFromIndexBySubstringAction(uuidIndex, key1);
|
const action = new RemoveFromIndexBySubstringAction(IndexName.OBJECT, key1);
|
||||||
let newState = indexReducer(state, action);
|
const newState = indexReducer(state, action);
|
||||||
|
|
||||||
expect(newState[uuidIndex][key1]).toBeUndefined();
|
expect(newState[IndexName.OBJECT][key1]).toBeUndefined();
|
||||||
|
|
||||||
action = new RemoveFromIndexBySubstringAction(handleIndex, key3);
|
|
||||||
newState = indexReducer(state, action);
|
|
||||||
|
|
||||||
expect(newState[uuidIndex][key3]).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -6,25 +6,23 @@ import {
|
|||||||
RemoveFromIndexByValueAction
|
RemoveFromIndexByValueAction
|
||||||
} from './index.actions';
|
} from './index.actions';
|
||||||
|
|
||||||
export enum IdentifierType {
|
/**
|
||||||
UUID ='uuid',
|
* An enum containing all index names
|
||||||
HANDLE = 'handle'
|
*/
|
||||||
}
|
export enum IndexName {
|
||||||
|
// Contains all objects in the object cache indexed by UUID
|
||||||
|
OBJECT = 'object/uuid-to-self-link',
|
||||||
|
|
||||||
|
// contains all requests in the request cache indexed by UUID
|
||||||
|
REQUEST = 'get-request/href-to-uuid',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the UUIDs of requests that were sent to the server and
|
* Contains the UUIDs of requests that were sent to the server and
|
||||||
* have their responses cached, indexed by the UUIDs of requests that
|
* have their responses cached, indexed by the UUIDs of requests that
|
||||||
* weren't sent because the response they requested was already cached
|
* weren't sent because the response they requested was already cached
|
||||||
*/
|
*/
|
||||||
export const UUID_MAPPING = 'get-request/configured-to-cache-uuid';
|
UUID_MAPPING = 'get-request/configured-to-cache-uuid'
|
||||||
|
}
|
||||||
// contains all requests in the request cache indexed by UUID
|
|
||||||
export const REQUEST = 'get-request/href-to-uuid';
|
|
||||||
|
|
||||||
// returns the index for the provided id type (uuid, handle)
|
|
||||||
export const getIdentiferByIndexName = (idType: IdentifierType): string => {
|
|
||||||
return `object/uuid-to-self-link/${idType}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state of a single index
|
* The state of a single index
|
||||||
@@ -36,11 +34,8 @@ export interface IndexState {
|
|||||||
/**
|
/**
|
||||||
* The state that contains all indices
|
* The state that contains all indices
|
||||||
*/
|
*/
|
||||||
export interface MetaIndexState {
|
export type MetaIndexState = {
|
||||||
'get-request/configured-to-cache-uuid': IndexState,
|
[name in IndexName]: IndexState
|
||||||
'get-request/href-to-uuid': IndexState,
|
|
||||||
'object/uuid-to-self-link/uuid': IndexState,
|
|
||||||
'object/uuid-to-self-link/handle': IndexState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
|
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
|
||||||
|
@@ -3,14 +3,7 @@ import { AppState } from '../../app.reducer';
|
|||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import { CoreState } from '../core.reducers';
|
import { CoreState } from '../core.reducers';
|
||||||
import { coreSelector } from '../core.selectors';
|
import { coreSelector } from '../core.selectors';
|
||||||
import {
|
import { IndexName, IndexState, MetaIndexState } from './index.reducer';
|
||||||
getIdentiferByIndexName,
|
|
||||||
IdentifierType,
|
|
||||||
IndexState,
|
|
||||||
MetaIndexState,
|
|
||||||
REQUEST,
|
|
||||||
UUID_MAPPING
|
|
||||||
} from './index.reducer';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the MetaIndexState based on the CoreSate
|
* Return the MetaIndexState based on the CoreSate
|
||||||
@@ -27,17 +20,13 @@ export const metaIndexSelector: MemoizedSelector<AppState, MetaIndexState> = cre
|
|||||||
* Return the object index based on the MetaIndexState
|
* Return the object index based on the MetaIndexState
|
||||||
* It contains all objects in the object cache indexed by UUID
|
* It contains all objects in the object cache indexed by UUID
|
||||||
*
|
*
|
||||||
* @param identifierType the type of index, used to select index from state
|
|
||||||
*
|
|
||||||
* @returns
|
* @returns
|
||||||
* a MemoizedSelector to select the object index
|
* a MemoizedSelector to select the object index
|
||||||
*/
|
*/
|
||||||
export const objectIndexSelector = (identifierType: IdentifierType = IdentifierType.UUID): MemoizedSelector<AppState, IndexState> => {
|
export const objectIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector(
|
||||||
return createSelector(
|
|
||||||
metaIndexSelector,
|
metaIndexSelector,
|
||||||
(state: MetaIndexState) => state[getIdentiferByIndexName(identifierType)]
|
(state: MetaIndexState) => state[IndexName.OBJECT]
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the request index based on the MetaIndexState
|
* Return the request index based on the MetaIndexState
|
||||||
@@ -47,7 +36,7 @@ export const objectIndexSelector = (identifierType: IdentifierType = IdentifierT
|
|||||||
*/
|
*/
|
||||||
export const requestIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector(
|
export const requestIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector(
|
||||||
metaIndexSelector,
|
metaIndexSelector,
|
||||||
(state: MetaIndexState) => state[REQUEST]
|
(state: MetaIndexState) => state[IndexName.REQUEST]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,7 +47,7 @@ export const requestIndexSelector: MemoizedSelector<AppState, IndexState> = crea
|
|||||||
*/
|
*/
|
||||||
export const requestUUIDIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector(
|
export const requestUUIDIndexSelector: MemoizedSelector<AppState, IndexState> = createSelector(
|
||||||
metaIndexSelector,
|
metaIndexSelector,
|
||||||
(state: MetaIndexState) => state[UUID_MAPPING]
|
(state: MetaIndexState) => state[IndexName.UUID_MAPPING]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,9 +60,9 @@ export const requestUUIDIndexSelector: MemoizedSelector<AppState, IndexState> =
|
|||||||
* a MemoizedSelector to select the self link
|
* a MemoizedSelector to select the self link
|
||||||
*/
|
*/
|
||||||
export const selfLinkFromUuidSelector =
|
export const selfLinkFromUuidSelector =
|
||||||
(id: string, identifierType: IdentifierType = IdentifierType.UUID): MemoizedSelector<AppState, string> => createSelector(
|
(uuid: string): MemoizedSelector<AppState, string> => createSelector(
|
||||||
objectIndexSelector(identifierType),
|
objectIndexSelector,
|
||||||
(state: IndexState) => hasValue(state) ? state[id] : undefined
|
(state: IndexState) => hasValue(state) ? state[uuid] : undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user