mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Refactored Data Services
This commit is contained in:
17
src/app/core/cache/cache.reducers.ts
vendored
Normal file
17
src/app/core/cache/cache.reducers.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { combineReducers } from "@ngrx/store";
|
||||
import { RequestCacheState, requestCacheReducer } from "./request-cache.reducer";
|
||||
import { ObjectCacheState, objectCacheReducer } from "./object-cache.reducer";
|
||||
|
||||
export interface CacheState {
|
||||
request: RequestCacheState,
|
||||
object: ObjectCacheState
|
||||
}
|
||||
|
||||
export const reducers = {
|
||||
request: requestCacheReducer,
|
||||
object: objectCacheReducer
|
||||
};
|
||||
|
||||
export function cacheReducer(state: any, action: any) {
|
||||
return combineReducers(reducers)(state, action);
|
||||
}
|
33
src/app/core/cache/object-cache.actions.ts
vendored
Normal file
33
src/app/core/cache/object-cache.actions.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Action } from "@ngrx/store";
|
||||
import { type } from "../../shared/ngrx/type";
|
||||
import { CacheableObject } from "./object-cache.reducer";
|
||||
|
||||
export const ObjectCacheActionTypes = {
|
||||
ADD: type('dspace/core/cache/object/ADD'),
|
||||
REMOVE: type('dspace/core/cache/object/REMOVE')
|
||||
};
|
||||
|
||||
export class AddToObjectCacheAction implements Action {
|
||||
type = ObjectCacheActionTypes.ADD;
|
||||
payload: {
|
||||
objectToCache: CacheableObject;
|
||||
msToLive: number;
|
||||
};
|
||||
|
||||
constructor(objectToCache: CacheableObject, msToLive: number) {
|
||||
this.payload = { objectToCache, msToLive };
|
||||
}
|
||||
}
|
||||
|
||||
export class RemoveFromObjectCacheAction implements Action {
|
||||
type = ObjectCacheActionTypes.REMOVE;
|
||||
payload: string;
|
||||
|
||||
constructor(uuid: string) {
|
||||
this.payload = uuid;
|
||||
}
|
||||
}
|
||||
|
||||
export type ObjectCacheAction
|
||||
= AddToObjectCacheAction
|
||||
| RemoveFromObjectCacheAction
|
58
src/app/core/cache/object-cache.reducer.ts
vendored
Normal file
58
src/app/core/cache/object-cache.reducer.ts
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import { ObjectCacheAction, ObjectCacheActionTypes, AddToObjectCacheAction, RemoveFromObjectCacheAction } from "./object-cache.actions";
|
||||
import { hasValue } from "../../shared/empty.util";
|
||||
|
||||
export interface CacheableObject {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface ObjectCacheEntry {
|
||||
data: CacheableObject;
|
||||
timeAdded: number;
|
||||
msToLive: number;
|
||||
}
|
||||
|
||||
export interface ObjectCacheState {
|
||||
[uuid: string]: ObjectCacheEntry
|
||||
}
|
||||
|
||||
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
|
||||
const initialState: ObjectCacheState = Object.create(null);
|
||||
|
||||
export const objectCacheReducer = (state = initialState, action: ObjectCacheAction): ObjectCacheState => {
|
||||
switch (action.type) {
|
||||
|
||||
case ObjectCacheActionTypes.ADD: {
|
||||
return addToObjectCache(state, <AddToObjectCacheAction>action);
|
||||
}
|
||||
|
||||
case ObjectCacheActionTypes.REMOVE: {
|
||||
return removeFromObjectCache(state, <RemoveFromObjectCacheAction>action)
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState {
|
||||
return Object.assign({}, state, {
|
||||
[action.payload.objectToCache.uuid]: {
|
||||
data: action.payload.objectToCache,
|
||||
timeAdded: new Date().getTime(),
|
||||
msToLive: action.payload.msToLive
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeFromObjectCache(state: ObjectCacheState, action: RemoveFromObjectCacheAction): ObjectCacheState {
|
||||
if (hasValue(state[action.payload])) {
|
||||
let newObjectCache = Object.assign({}, state);
|
||||
delete newObjectCache[action.payload];
|
||||
|
||||
return newObjectCache;
|
||||
}
|
||||
else {
|
||||
return state;
|
||||
}
|
||||
}
|
@@ -1,28 +1,28 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Store } from "@ngrx/store";
|
||||
import { CacheState, CacheEntry, CacheableObject } from "./cache.reducer";
|
||||
import { AddToCacheAction, RemoveFromCacheAction } from "./cache.actions";
|
||||
import { ObjectCacheState, ObjectCacheEntry, CacheableObject } from "./object-cache.reducer";
|
||||
import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from "./object-cache.actions";
|
||||
import { Observable } from "rxjs";
|
||||
import { hasNoValue } from "../../../shared/empty.util";
|
||||
import { hasNoValue } from "../../shared/empty.util";
|
||||
|
||||
@Injectable()
|
||||
export class CacheService {
|
||||
export class ObjectCacheService {
|
||||
constructor(
|
||||
private store: Store<CacheState>
|
||||
private store: Store<ObjectCacheState>
|
||||
) {}
|
||||
|
||||
add(objectToCache: CacheableObject, msToLive: number): void {
|
||||
this.store.dispatch(new AddToCacheAction(objectToCache, msToLive));
|
||||
this.store.dispatch(new AddToObjectCacheAction(objectToCache, msToLive));
|
||||
}
|
||||
|
||||
remove(uuid: string): void {
|
||||
this.store.dispatch(new RemoveFromCacheAction(uuid));
|
||||
this.store.dispatch(new RemoveFromObjectCacheAction(uuid));
|
||||
}
|
||||
|
||||
get<T extends CacheableObject>(uuid: string): Observable<T> {
|
||||
return this.store.select<CacheEntry>('core', 'cache', uuid)
|
||||
return this.store.select<ObjectCacheEntry>('core', 'cache', 'object', uuid)
|
||||
.filter(entry => this.isValid(entry))
|
||||
.map((entry: CacheEntry) => <T> entry.data);
|
||||
.map((entry: ObjectCacheEntry) => <T> entry.data);
|
||||
}
|
||||
|
||||
getList<T extends CacheableObject>(uuids: Array<string>): Observable<Array<T>> {
|
||||
@@ -34,14 +34,14 @@ export class CacheService {
|
||||
has(uuid: string): boolean {
|
||||
let result: boolean;
|
||||
|
||||
this.store.select<CacheEntry>('core', 'cache', uuid)
|
||||
this.store.select<ObjectCacheEntry>('core', 'cache', 'object', uuid)
|
||||
.take(1)
|
||||
.subscribe(entry => result = this.isValid(entry));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private isValid(entry: CacheEntry): boolean {
|
||||
private isValid(entry: ObjectCacheEntry): boolean {
|
||||
if (hasNoValue(entry)) {
|
||||
return false;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ export class CacheService {
|
||||
const timeOutdated = entry.timeAdded + entry.msToLive;
|
||||
const isOutDated = new Date().getTime() > timeOutdated;
|
||||
if (isOutDated) {
|
||||
this.store.dispatch(new RemoveFromCacheAction(entry.data.uuid));
|
||||
this.store.dispatch(new RemoveFromObjectCacheAction(entry.data.uuid));
|
||||
}
|
||||
return !isOutDated;
|
||||
}
|
@@ -4,15 +4,15 @@ import { type } from "../../shared/ngrx/type";
|
||||
import { PaginationOptions } from "../shared/pagination-options.model";
|
||||
import { SortOptions } from "../shared/sort-options.model";
|
||||
|
||||
export const DataActionTypes = {
|
||||
FIND_BY_ID_REQUEST: type('dspace/core/data/FIND_BY_ID_REQUEST'),
|
||||
FIND_ALL_REQUEST: type('dspace/core/data/FIND_ALL_REQUEST'),
|
||||
SUCCESS: type('dspace/core/data/SUCCESS'),
|
||||
ERROR: type('dspace/core/data/ERROR')
|
||||
export const RequestCacheActionTypes = {
|
||||
FIND_BY_ID_REQUEST: type('dspace/core/cache/request/FIND_BY_ID_REQUEST'),
|
||||
FIND_ALL_REQUEST: type('dspace/core/cache/request/FIND_ALL_REQUEST'),
|
||||
SUCCESS: type('dspace/core/cache/request/SUCCESS'),
|
||||
ERROR: type('dspace/core/cache/request/ERROR')
|
||||
};
|
||||
|
||||
export class DataFindAllRequestAction implements Action {
|
||||
type = DataActionTypes.FIND_ALL_REQUEST;
|
||||
export class FindAllRequestCacheAction implements Action {
|
||||
type = RequestCacheActionTypes.FIND_ALL_REQUEST;
|
||||
payload: {
|
||||
key: string,
|
||||
service: OpaqueToken,
|
||||
@@ -38,8 +38,8 @@ export class DataFindAllRequestAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class DataFindByIDRequestAction implements Action {
|
||||
type = DataActionTypes.FIND_BY_ID_REQUEST;
|
||||
export class FindByIDRequestCacheAction implements Action {
|
||||
type = RequestCacheActionTypes.FIND_BY_ID_REQUEST;
|
||||
payload: {
|
||||
key: string,
|
||||
service: OpaqueToken,
|
||||
@@ -59,8 +59,8 @@ export class DataFindByIDRequestAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class DataSuccessAction implements Action {
|
||||
type = DataActionTypes.SUCCESS;
|
||||
export class RequestCacheSuccessAction implements Action {
|
||||
type = RequestCacheActionTypes.SUCCESS;
|
||||
payload: {
|
||||
key: string,
|
||||
resourceUUIDs: Array<string>
|
||||
@@ -74,8 +74,8 @@ export class DataSuccessAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class DataErrorAction implements Action {
|
||||
type = DataActionTypes.ERROR;
|
||||
export class RequestCacheErrorAction implements Action {
|
||||
type = RequestCacheActionTypes.ERROR;
|
||||
payload: {
|
||||
key: string,
|
||||
errorMessage: string
|
||||
@@ -89,8 +89,8 @@ export class DataErrorAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
export type DataAction
|
||||
= DataFindAllRequestAction
|
||||
| DataFindByIDRequestAction
|
||||
| DataSuccessAction
|
||||
| DataErrorAction;
|
||||
export type RequestCacheAction
|
||||
= FindAllRequestCacheAction
|
||||
| FindByIDRequestCacheAction
|
||||
| RequestCacheSuccessAction
|
||||
| RequestCacheErrorAction;
|
@@ -1,12 +1,12 @@
|
||||
import { PaginationOptions } from "../shared/pagination-options.model";
|
||||
import { SortOptions } from "../shared/sort-options.model";
|
||||
import {
|
||||
DataAction, DataActionTypes, DataFindAllRequestAction,
|
||||
DataSuccessAction, DataErrorAction, DataFindByIDRequestAction
|
||||
} from "./data.actions";
|
||||
RequestCacheAction, RequestCacheActionTypes, FindAllRequestCacheAction,
|
||||
RequestCacheSuccessAction, RequestCacheErrorAction, FindByIDRequestCacheAction
|
||||
} from "./request-cache.actions";
|
||||
import { OpaqueToken } from "@angular/core";
|
||||
|
||||
export interface DataRequestState {
|
||||
export interface CachedRequest {
|
||||
service: OpaqueToken
|
||||
scopeID: string;
|
||||
resourceID: string;
|
||||
@@ -20,30 +20,30 @@ export interface DataRequestState {
|
||||
msToLive: number;
|
||||
}
|
||||
|
||||
export interface DataState {
|
||||
[key: string]: DataRequestState
|
||||
export interface RequestCacheState {
|
||||
[key: string]: CachedRequest
|
||||
}
|
||||
|
||||
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
|
||||
const initialState = Object.create(null);
|
||||
|
||||
export const dataReducer = (state = initialState, action: DataAction): DataState => {
|
||||
export const requestCacheReducer = (state = initialState, action: RequestCacheAction): RequestCacheState => {
|
||||
switch (action.type) {
|
||||
|
||||
case DataActionTypes.FIND_ALL_REQUEST: {
|
||||
return findAllRequest(state, <DataFindAllRequestAction> action);
|
||||
case RequestCacheActionTypes.FIND_ALL_REQUEST: {
|
||||
return findAllRequest(state, <FindAllRequestCacheAction> action);
|
||||
}
|
||||
|
||||
case DataActionTypes.FIND_BY_ID_REQUEST: {
|
||||
return findByIDRequest(state, <DataFindByIDRequestAction> action);
|
||||
case RequestCacheActionTypes.FIND_BY_ID_REQUEST: {
|
||||
return findByIDRequest(state, <FindByIDRequestCacheAction> action);
|
||||
}
|
||||
|
||||
case DataActionTypes.SUCCESS: {
|
||||
return success(state, <DataSuccessAction> action);
|
||||
case RequestCacheActionTypes.SUCCESS: {
|
||||
return success(state, <RequestCacheSuccessAction> action);
|
||||
}
|
||||
|
||||
case DataActionTypes.ERROR: {
|
||||
return error(state, <DataErrorAction> action);
|
||||
case RequestCacheActionTypes.ERROR: {
|
||||
return error(state, <RequestCacheErrorAction> action);
|
||||
}
|
||||
|
||||
default: {
|
||||
@@ -52,7 +52,7 @@ export const dataReducer = (state = initialState, action: DataAction): DataState
|
||||
}
|
||||
};
|
||||
|
||||
function findAllRequest(state: DataState, action: DataFindAllRequestAction): DataState {
|
||||
function findAllRequest(state: RequestCacheState, action: FindAllRequestCacheAction): RequestCacheState {
|
||||
return Object.assign({}, state, {
|
||||
[action.payload.key]: {
|
||||
service: action.payload.service,
|
||||
@@ -66,7 +66,7 @@ function findAllRequest(state: DataState, action: DataFindAllRequestAction): Dat
|
||||
});
|
||||
}
|
||||
|
||||
function findByIDRequest(state: DataState, action: DataFindByIDRequestAction): DataState {
|
||||
function findByIDRequest(state: RequestCacheState, action: FindByIDRequestCacheAction): RequestCacheState {
|
||||
return Object.assign({}, state, {
|
||||
[action.payload.key]: {
|
||||
service: action.payload.service,
|
||||
@@ -78,7 +78,7 @@ function findByIDRequest(state: DataState, action: DataFindByIDRequestAction): D
|
||||
});
|
||||
}
|
||||
|
||||
function success(state: DataState, action: DataSuccessAction): DataState {
|
||||
function success(state: RequestCacheState, action: RequestCacheSuccessAction): RequestCacheState {
|
||||
return Object.assign({}, state, {
|
||||
[action.payload.key]: Object.assign({}, state[action.payload.key], {
|
||||
isLoading: false,
|
||||
@@ -88,7 +88,7 @@ function success(state: DataState, action: DataSuccessAction): DataState {
|
||||
});
|
||||
}
|
||||
|
||||
function error(state: DataState, action: DataErrorAction): DataState {
|
||||
function error(state: RequestCacheState, action: RequestCacheErrorAction): RequestCacheState {
|
||||
return Object.assign({}, state, {
|
||||
[action.payload.key]: Object.assign({}, state[action.payload.key], {
|
||||
isLoading: false,
|
@@ -4,7 +4,7 @@ import { SharedModule } from "../shared/shared.module";
|
||||
import { isNotEmpty } from "../shared/empty.util";
|
||||
import { FooterComponent } from "./footer/footer.component";
|
||||
import { DSpaceRESTv2Service } from "./dspace-rest-v2/dspace-rest-v2.service";
|
||||
import { CacheService } from "./data-services/cache/cache.service";
|
||||
import { ObjectCacheService } from "./cache/object-cache.service";
|
||||
import { CollectionDataService } from "./data-services/collection-data.service";
|
||||
import { ItemDataService } from "./data-services/item-data.service";
|
||||
|
||||
@@ -25,7 +25,7 @@ const PROVIDERS = [
|
||||
CollectionDataService,
|
||||
ItemDataService,
|
||||
DSpaceRESTv2Service,
|
||||
CacheService
|
||||
ObjectCacheService
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@@ -1,14 +1,11 @@
|
||||
import { combineReducers } from "@ngrx/store";
|
||||
import { CacheState, cacheReducer } from "./data-services/cache/cache.reducer";
|
||||
import { dataReducer, DataState } from "./data-services/data.reducer";
|
||||
import { CacheState, cacheReducer } from "./cache/cache.reducers";
|
||||
|
||||
export interface CoreState {
|
||||
data: DataState,
|
||||
cache: CacheState
|
||||
}
|
||||
|
||||
export const reducers = {
|
||||
data: dataReducer,
|
||||
cache: cacheReducer
|
||||
};
|
||||
|
||||
|
@@ -1,33 +0,0 @@
|
||||
import { Action } from "@ngrx/store";
|
||||
import { type } from "../../../shared/ngrx/type";
|
||||
import { CacheableObject } from "./cache.reducer";
|
||||
|
||||
export const CacheActionTypes = {
|
||||
ADD: type('dspace/core/data/cache/ADD'),
|
||||
REMOVE: type('dspace/core/data/cache/REMOVE')
|
||||
};
|
||||
|
||||
export class AddToCacheAction implements Action {
|
||||
type = CacheActionTypes.ADD;
|
||||
payload: {
|
||||
objectToCache: CacheableObject;
|
||||
msToLive: number;
|
||||
};
|
||||
|
||||
constructor(objectToCache: CacheableObject, msToLive: number) {
|
||||
this.payload = { objectToCache, msToLive };
|
||||
}
|
||||
}
|
||||
|
||||
export class RemoveFromCacheAction implements Action {
|
||||
type = CacheActionTypes.REMOVE;
|
||||
payload: string;
|
||||
|
||||
constructor(uuid: string) {
|
||||
this.payload = uuid;
|
||||
}
|
||||
}
|
||||
|
||||
export type CacheAction
|
||||
= AddToCacheAction
|
||||
| RemoveFromCacheAction
|
@@ -1,58 +0,0 @@
|
||||
import { CacheAction, CacheActionTypes, AddToCacheAction, RemoveFromCacheAction } from "./cache.actions";
|
||||
import { hasValue } from "../../../shared/empty.util";
|
||||
|
||||
export interface CacheableObject {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface CacheEntry {
|
||||
data: CacheableObject;
|
||||
timeAdded: number;
|
||||
msToLive: number;
|
||||
}
|
||||
|
||||
export interface CacheState {
|
||||
[uuid: string]: CacheEntry
|
||||
}
|
||||
|
||||
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
|
||||
const initialState: CacheState = Object.create(null);
|
||||
|
||||
export const cacheReducer = (state = initialState, action: CacheAction): CacheState => {
|
||||
switch (action.type) {
|
||||
|
||||
case CacheActionTypes.ADD: {
|
||||
return addToCache(state, <AddToCacheAction>action);
|
||||
}
|
||||
|
||||
case CacheActionTypes.REMOVE: {
|
||||
return removeFromCache(state, <RemoveFromCacheAction>action)
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function addToCache(state: CacheState, action: AddToCacheAction): CacheState {
|
||||
return Object.assign({}, state, {
|
||||
[action.payload.objectToCache.uuid]: {
|
||||
data: action.payload.objectToCache,
|
||||
timeAdded: new Date().getTime(),
|
||||
msToLive: action.payload.msToLive
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeFromCache(state: CacheState, action: RemoveFromCacheAction): CacheState {
|
||||
if (hasValue(state[action.payload])) {
|
||||
let newCache = Object.assign({}, state);
|
||||
delete newCache[action.payload];
|
||||
|
||||
return newCache;
|
||||
}
|
||||
else {
|
||||
return state;
|
||||
}
|
||||
}
|
@@ -3,10 +3,10 @@ import { DataEffects } from "./data.effects";
|
||||
import { Serializer } from "../serializer";
|
||||
import { Collection } from "../shared/collection.model";
|
||||
import { DSpaceRESTv2Serializer } from "../dspace-rest-v2/dspace-rest-v2.serializer";
|
||||
import { CacheService } from "./cache/cache.service";
|
||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||
import { DSpaceRESTv2Service } from "../dspace-rest-v2/dspace-rest-v2.service";
|
||||
import { Actions, Effect } from "@ngrx/effects";
|
||||
import { DataFindAllRequestAction, DataFindByIDRequestAction } from "./data.actions";
|
||||
import { FindAllRequestCacheAction, FindByIDRequestCacheAction } from "../cache/request-cache.actions";
|
||||
import { CollectionDataService } from "./collection-data.service";
|
||||
|
||||
@Injectable()
|
||||
@@ -14,17 +14,17 @@ export class CollectionDataEffects extends DataEffects<Collection> {
|
||||
constructor(
|
||||
actions$: Actions,
|
||||
restApi: DSpaceRESTv2Service,
|
||||
cache: CacheService,
|
||||
cache: ObjectCacheService,
|
||||
dataService: CollectionDataService
|
||||
) {
|
||||
super(actions$, restApi, cache, dataService);
|
||||
}
|
||||
|
||||
protected getFindAllEndpoint(action: DataFindAllRequestAction): string {
|
||||
protected getFindAllEndpoint(action: FindAllRequestCacheAction): string {
|
||||
return '/collections';
|
||||
}
|
||||
|
||||
protected getFindByIdEndpoint(action: DataFindByIDRequestAction): string {
|
||||
protected getFindByIdEndpoint(action: FindByIDRequestCacheAction): string {
|
||||
return `/collections/${action.payload.resourceID}`;
|
||||
}
|
||||
|
||||
|
@@ -2,16 +2,16 @@ import { Injectable, OpaqueToken } from "@angular/core";
|
||||
import { Store } from "@ngrx/store";
|
||||
import { DataService } from "./data.service";
|
||||
import { Collection } from "../shared/collection.model";
|
||||
import { CacheService } from "./cache/cache.service";
|
||||
import { DataState } from "./data.reducer";
|
||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||
import { RequestCacheState } from "../cache/request-cache.reducer";
|
||||
|
||||
@Injectable()
|
||||
export class CollectionDataService extends DataService<Collection> {
|
||||
name = new OpaqueToken('CollectionDataService');
|
||||
|
||||
constructor(
|
||||
store: Store<DataState>,
|
||||
cache: CacheService
|
||||
store: Store<RequestCacheState>,
|
||||
cache: ObjectCacheService
|
||||
) {
|
||||
super(store, cache);
|
||||
}
|
||||
|
@@ -2,25 +2,25 @@ import { Actions, Effect } from "@ngrx/effects";
|
||||
import { Observable } from "rxjs";
|
||||
import { DSpaceRESTV2Response } from "../dspace-rest-v2/dspace-rest-v2-response.model";
|
||||
import { DSpaceRESTv2Service } from "../dspace-rest-v2/dspace-rest-v2.service";
|
||||
import { CacheService } from "./cache/cache.service";
|
||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||
import { GlobalConfig } from "../../../config";
|
||||
import { CacheableObject } from "./cache/cache.reducer";
|
||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||
import { Serializer } from "../serializer";
|
||||
import {
|
||||
DataActionTypes, DataFindAllRequestAction, DataSuccessAction,
|
||||
DataErrorAction, DataFindByIDRequestAction, DataAction
|
||||
} from "./data.actions";
|
||||
RequestCacheActionTypes, FindAllRequestCacheAction, RequestCacheSuccessAction,
|
||||
RequestCacheErrorAction, FindByIDRequestCacheAction
|
||||
} from "../cache/request-cache.actions";
|
||||
import { DataService } from "./data.service";
|
||||
|
||||
export abstract class DataEffects<T extends CacheableObject> {
|
||||
protected abstract getFindAllEndpoint(action: DataFindAllRequestAction): string;
|
||||
protected abstract getFindByIdEndpoint(action: DataFindByIDRequestAction): string;
|
||||
protected abstract getFindAllEndpoint(action: FindAllRequestCacheAction): string;
|
||||
protected abstract getFindByIdEndpoint(action: FindByIDRequestCacheAction): string;
|
||||
protected abstract getSerializer(): Serializer<T>;
|
||||
|
||||
constructor(
|
||||
private actions$: Actions,
|
||||
private restApi: DSpaceRESTv2Service,
|
||||
private cache: CacheService,
|
||||
private objectCache: ObjectCacheService,
|
||||
private dataService: DataService<T>
|
||||
) {}
|
||||
|
||||
@@ -28,33 +28,33 @@ export abstract class DataEffects<T extends CacheableObject> {
|
||||
// because currently the cache is more of an object store. We need to move
|
||||
// more towards memoization for things like this.
|
||||
protected findAll = this.actions$
|
||||
.ofType(DataActionTypes.FIND_ALL_REQUEST)
|
||||
.filter((action: DataFindAllRequestAction) => action.payload.service === this.dataService.name)
|
||||
.switchMap((action: DataFindAllRequestAction) => {
|
||||
.ofType(RequestCacheActionTypes.FIND_ALL_REQUEST)
|
||||
.filter((action: FindAllRequestCacheAction) => action.payload.service === this.dataService.name)
|
||||
.switchMap((action: FindAllRequestCacheAction) => {
|
||||
//TODO scope, pagination, sorting -> when we know how that works in rest
|
||||
return this.restApi.get(this.getFindAllEndpoint(action))
|
||||
.map((data: DSpaceRESTV2Response) => this.getSerializer().deserializeArray(data))
|
||||
.do((ts: T[]) => {
|
||||
ts.forEach((t) => {
|
||||
this.cache.add(t, GlobalConfig.cache.msToLive);
|
||||
this.objectCache.add(t, GlobalConfig.cache.msToLive);
|
||||
});
|
||||
})
|
||||
.map((ts: Array<T>) => ts.map(t => t.uuid))
|
||||
.map((ids: Array<string>) => new DataSuccessAction(action.payload.key, ids))
|
||||
.catch((errorMsg: string) => Observable.of(new DataErrorAction(action.payload.key, errorMsg)));
|
||||
.map((ids: Array<string>) => new RequestCacheSuccessAction(action.payload.key, ids))
|
||||
.catch((errorMsg: string) => Observable.of(new RequestCacheErrorAction(action.payload.key, errorMsg)));
|
||||
});
|
||||
|
||||
protected findById = this.actions$
|
||||
.ofType(DataActionTypes.FIND_BY_ID_REQUEST)
|
||||
.filter((action: DataFindAllRequestAction) => action.payload.service === this.dataService.name)
|
||||
.switchMap((action: DataFindByIDRequestAction) => {
|
||||
.ofType(RequestCacheActionTypes.FIND_BY_ID_REQUEST)
|
||||
.filter((action: FindAllRequestCacheAction) => action.payload.service === this.dataService.name)
|
||||
.switchMap((action: FindByIDRequestCacheAction) => {
|
||||
return this.restApi.get(this.getFindByIdEndpoint(action))
|
||||
.map((data: DSpaceRESTV2Response) => this.getSerializer().deserialize(data))
|
||||
.do((t: T) => {
|
||||
this.cache.add(t, GlobalConfig.cache.msToLive);
|
||||
this.objectCache.add(t, GlobalConfig.cache.msToLive);
|
||||
})
|
||||
.map((t: T) => new DataSuccessAction(action.payload.key, [t.uuid]))
|
||||
.catch((errorMsg: string) => Observable.of(new DataErrorAction(action.payload.key, errorMsg)));
|
||||
.map((t: T) => new RequestCacheSuccessAction(action.payload.key, [t.uuid]))
|
||||
.catch((errorMsg: string) => Observable.of(new RequestCacheErrorAction(action.payload.key, errorMsg)));
|
||||
});
|
||||
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { OpaqueToken } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
import { Store } from "@ngrx/store";
|
||||
import { CacheService } from "./cache/cache.service";
|
||||
import { CacheableObject } from "./cache/cache.reducer";
|
||||
import { DataState } from "./data.reducer";
|
||||
import { DataFindAllRequestAction, DataFindByIDRequestAction } from "./data.actions";
|
||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||
import { RequestCacheState } from "../cache/request-cache.reducer";
|
||||
import { FindAllRequestCacheAction, FindByIDRequestCacheAction } from "../cache/request-cache.actions";
|
||||
import { ParamHash } from "../shared/param-hash";
|
||||
import { isNotEmpty } from "../../shared/empty.util";
|
||||
|
||||
@@ -12,28 +12,28 @@ export abstract class DataService<T extends CacheableObject> {
|
||||
abstract name: OpaqueToken;
|
||||
|
||||
constructor(
|
||||
private store: Store<DataState>,
|
||||
private cache: CacheService
|
||||
private store: Store<RequestCacheState>,
|
||||
private objectCache: ObjectCacheService
|
||||
) { }
|
||||
|
||||
findAll(scopeID?: string): Observable<Array<T>> {
|
||||
const key = new ParamHash(this.name, 'findAll', scopeID).toString();
|
||||
this.store.dispatch(new DataFindAllRequestAction(key, this.name, scopeID));
|
||||
this.store.dispatch(new FindAllRequestCacheAction(key, this.name, scopeID));
|
||||
//get an observable of the IDs from the store
|
||||
return this.store.select<Array<string>>('core', 'data', key, 'resourceUUIDs')
|
||||
return this.store.select<Array<string>>('core', 'cache', 'request', key, 'resourceUUIDs')
|
||||
.flatMap((resourceUUIDs: Array<string>) => {
|
||||
// use those IDs to fetch the actual objects from the cache
|
||||
return this.cache.getList<T>(resourceUUIDs);
|
||||
return this.objectCache.getList<T>(resourceUUIDs);
|
||||
});
|
||||
}
|
||||
|
||||
findById(id: string): Observable<T> {
|
||||
const key = new ParamHash(this.name, 'findById', id).toString();
|
||||
this.store.dispatch(new DataFindByIDRequestAction(key, this.name, id));
|
||||
return this.store.select<Array<string>>('core', 'data', key, 'resourceUUIDs')
|
||||
this.store.dispatch(new FindByIDRequestCacheAction(key, this.name, id));
|
||||
return this.store.select<Array<string>>('core', 'cache', 'request', key, 'resourceUUIDs')
|
||||
.flatMap((resourceUUIDs: Array<string>) => {
|
||||
if(isNotEmpty(resourceUUIDs)) {
|
||||
return this.cache.get<T>(resourceUUIDs[0]);
|
||||
return this.objectCache.get<T>(resourceUUIDs[0]);
|
||||
}
|
||||
else {
|
||||
return Observable.of(undefined);
|
||||
|
@@ -3,10 +3,10 @@ import { DataEffects } from "./data.effects";
|
||||
import { Serializer } from "../serializer";
|
||||
import { Item } from "../shared/item.model";
|
||||
import { DSpaceRESTv2Serializer } from "../dspace-rest-v2/dspace-rest-v2.serializer";
|
||||
import { CacheService } from "./cache/cache.service";
|
||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||
import { DSpaceRESTv2Service } from "../dspace-rest-v2/dspace-rest-v2.service";
|
||||
import { Actions, Effect } from "@ngrx/effects";
|
||||
import { DataFindAllRequestAction, DataFindByIDRequestAction } from "./data.actions";
|
||||
import { FindAllRequestCacheAction, FindByIDRequestCacheAction } from "../cache/request-cache.actions";
|
||||
import { ItemDataService } from "./item-data.service";
|
||||
|
||||
@Injectable()
|
||||
@@ -14,17 +14,17 @@ export class ItemDataEffects extends DataEffects<Item> {
|
||||
constructor(
|
||||
actions$: Actions,
|
||||
restApi: DSpaceRESTv2Service,
|
||||
cache: CacheService,
|
||||
cache: ObjectCacheService,
|
||||
dataService: ItemDataService
|
||||
) {
|
||||
super(actions$, restApi, cache, dataService);
|
||||
}
|
||||
|
||||
protected getFindAllEndpoint(action: DataFindAllRequestAction): string {
|
||||
protected getFindAllEndpoint(action: FindAllRequestCacheAction): string {
|
||||
return '/items';
|
||||
}
|
||||
|
||||
protected getFindByIdEndpoint(action: DataFindByIDRequestAction): string {
|
||||
protected getFindByIdEndpoint(action: FindByIDRequestCacheAction): string {
|
||||
return `/items/${action.payload.resourceID}`;
|
||||
}
|
||||
|
||||
|
@@ -2,16 +2,16 @@ import { Injectable, OpaqueToken } from "@angular/core";
|
||||
import { Store } from "@ngrx/store";
|
||||
import { DataService } from "./data.service";
|
||||
import { Item } from "../shared/item.model";
|
||||
import { CacheService } from "./cache/cache.service";
|
||||
import { DataState } from "./data.reducer";
|
||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||
import { RequestCacheState } from "../cache/request-cache.reducer";
|
||||
|
||||
@Injectable()
|
||||
export class ItemDataService extends DataService<Item> {
|
||||
name = new OpaqueToken('ItemDataService');
|
||||
|
||||
constructor(
|
||||
store: Store<DataState>,
|
||||
cache: CacheService
|
||||
store: Store<RequestCacheState>,
|
||||
cache: ObjectCacheService
|
||||
) {
|
||||
super(store, cache);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { autoserialize, autoserializeAs } from "cerialize";
|
||||
import { Metadatum } from "./metadatum.model"
|
||||
import { isEmpty, isNotEmpty } from "../../shared/empty.util";
|
||||
import { CacheableObject } from "../data-services/cache/cache.reducer";
|
||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||
|
||||
/**
|
||||
* An abstract model class for a DSpaceObject.
|
||||
|
@@ -92,7 +92,7 @@ export function createMockApi() {
|
||||
|
||||
router.route('/collections/:collection_id')
|
||||
.get(function(req, res) {
|
||||
console.log('GET', util.inspect(req.collection.id, { colors: true }));
|
||||
// console.log('GET', util.inspect(req.collection.id, { colors: true }));
|
||||
res.json(toHALResponse(req, req.collection));
|
||||
// })
|
||||
// .put(function(req, res) {
|
||||
@@ -154,7 +154,7 @@ export function createMockApi() {
|
||||
|
||||
router.route('/items/:item_id')
|
||||
.get(function(req, res) {
|
||||
console.log('GET', util.inspect(req.item, { colors: true }));
|
||||
// console.log('GET', util.inspect(req.item, { colors: true }));
|
||||
res.json(toHALResponse(req, req.item));
|
||||
// })
|
||||
// .put(function(req, res) {
|
||||
@@ -199,7 +199,7 @@ export function createMockApi() {
|
||||
|
||||
router.route('/bundles/:bundle_id')
|
||||
.get(function(req, res) {
|
||||
console.log('GET', util.inspect(req.bundle, { colors: true }));
|
||||
// console.log('GET', util.inspect(req.bundle, { colors: true }));
|
||||
res.json(toHALResponse(req, req.bundle));
|
||||
});
|
||||
|
||||
@@ -229,7 +229,7 @@ export function createMockApi() {
|
||||
|
||||
router.route('/bitstreams/:bitstream_id')
|
||||
.get(function(req, res) {
|
||||
console.log('GET', util.inspect(req.bitstream, { colors: true }));
|
||||
// console.log('GET', util.inspect(req.bitstream, { colors: true }));
|
||||
res.json(toHALResponse(req, req.bitstream));
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user