mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-14 13:33:03 +00:00
Cache redesign part 1, and add support for alternative links
This commit is contained in:
@@ -52,7 +52,7 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
||||
path: '/testResourceType/testResourceId/testField',
|
||||
value: ['test']
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
]
|
||||
} as JsonPatchOperationsEntry
|
||||
@@ -75,14 +75,14 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
||||
path: '/testResourceType/testResourceId/testField',
|
||||
value: ['test']
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
{
|
||||
operation: {
|
||||
op: 'remove',
|
||||
path: '/testResourceType/testResourceId/testField'
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
]
|
||||
} as JsonPatchOperationsEntry
|
||||
@@ -203,14 +203,14 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
||||
path: '/testResourceType/testResourceId/testField',
|
||||
value: ['test']
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
{
|
||||
operation: {
|
||||
op: 'remove',
|
||||
path: '/testResourceType/testResourceId/testField'
|
||||
},
|
||||
timeAdded: timestampAfterStart
|
||||
timeCompleted: timestampAfterStart
|
||||
},
|
||||
]
|
||||
} as JsonPatchOperationsEntry
|
||||
@@ -226,7 +226,7 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
||||
op: 'remove',
|
||||
path: '/testResourceType/testResourceId/testField'
|
||||
},
|
||||
timeAdded: timestampAfterStart
|
||||
timeCompleted: timestampAfterStart
|
||||
},
|
||||
];
|
||||
expect(newState[testJsonPatchResourceType].transactionStartTime).toBeNull();
|
||||
@@ -246,14 +246,14 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
||||
path: '/testResourceType/testResourceId/testField',
|
||||
value: ['test']
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
{
|
||||
operation: {
|
||||
op: 'remove',
|
||||
path: '/testResourceType/testResourceId/testField'
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
]
|
||||
} as JsonPatchOperationsEntry,
|
||||
@@ -265,14 +265,14 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
||||
path: '/testResourceType/testResourceAnotherId/testField',
|
||||
value: ['test']
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
{
|
||||
operation: {
|
||||
op: 'remove',
|
||||
path: '/testResourceType/testResourceAnotherId/testField'
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
]
|
||||
} as JsonPatchOperationsEntry
|
||||
@@ -295,14 +295,14 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
||||
path: '/testResourceType/testResourceAnotherId/testField',
|
||||
value: ['test']
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
{
|
||||
operation: {
|
||||
op: 'remove',
|
||||
path: '/testResourceType/testResourceAnotherId/testField'
|
||||
},
|
||||
timeAdded: timestampBeforeStart
|
||||
timeCompleted: timestampBeforeStart
|
||||
},
|
||||
];
|
||||
expect(newState[testJsonPatchResourceType].transactionStartTime).toBeNull();
|
||||
|
@@ -20,7 +20,7 @@ import { JsonPatchOperationModel, JsonPatchOperationType } from './json-patch.mo
|
||||
*/
|
||||
export interface JsonPatchOperationObject {
|
||||
operation: JsonPatchOperationModel;
|
||||
timeAdded: number;
|
||||
timeCompleted: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,7 +264,7 @@ function flushOperation(state: JsonPatchOperationsState, action: FlushPatchOpera
|
||||
newChildren = Object.assign({}, state[ action.payload.resourceType ].children, {
|
||||
[action.payload.resourceId]: {
|
||||
body: state[ action.payload.resourceType ].children[ action.payload.resourceId ].body
|
||||
.filter((entry) => entry.timeAdded > state[ action.payload.resourceType ].transactionStartTime)
|
||||
.filter((entry) => entry.timeCompleted > state[ action.payload.resourceType ].transactionStartTime)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -278,7 +278,7 @@ function flushOperation(state: JsonPatchOperationsState, action: FlushPatchOpera
|
||||
newChildren = Object.assign({}, newChildren, {
|
||||
[resourceId]: {
|
||||
body: newChildren[ resourceId ].body
|
||||
.filter((entry) => entry.timeAdded > state[ action.payload.resourceType ].transactionStartTime)
|
||||
.filter((entry) => entry.timeCompleted > state[ action.payload.resourceType ].transactionStartTime)
|
||||
}
|
||||
});
|
||||
})
|
||||
@@ -336,5 +336,5 @@ function addOperationToList(body: JsonPatchOperationObject[], actionType, target
|
||||
}
|
||||
|
||||
function makeOperationEntry(operation) {
|
||||
return { operation: operation, timeAdded: new Date().getTime() };
|
||||
return { operation: operation, timeCompleted: new Date().getTime() };
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ import {
|
||||
StartTransactionPatchOperationsAction
|
||||
} from './json-patch-operations.actions';
|
||||
import { RequestEntry } from '../data/request.reducer';
|
||||
import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
|
||||
|
||||
class TestService extends JsonPatchOperationsService<SubmitDataResponseDefinitionObject, SubmissionPatchRequest> {
|
||||
protected linkPath = '';
|
||||
@@ -29,7 +30,8 @@ class TestService extends JsonPatchOperationsService<SubmitDataResponseDefinitio
|
||||
constructor(
|
||||
protected requestService: RequestService,
|
||||
protected store: Store<CoreState>,
|
||||
protected halService: HALEndpointService) {
|
||||
protected halService: HALEndpointService,
|
||||
protected rdbService: RemoteDataBuildService) {
|
||||
|
||||
super();
|
||||
}
|
||||
@@ -57,7 +59,7 @@ describe('JsonPatchOperationsService test suite', () => {
|
||||
path: '/testResourceType/testResourceId/testField',
|
||||
value: ['test']
|
||||
},
|
||||
timeAdded: timestamp
|
||||
timeCompleted: timestamp
|
||||
},
|
||||
]
|
||||
} as JsonPatchOperationsEntry
|
||||
@@ -82,7 +84,7 @@ describe('JsonPatchOperationsService test suite', () => {
|
||||
|
||||
const getRequestEntry$ = (successful: boolean) => {
|
||||
return observableOf({
|
||||
response: { isSuccessful: successful, timeAdded: timestampResponse } as any
|
||||
response: { isSuccessful: successful, timeCompleted: timestampResponse } as any
|
||||
} as RequestEntry)
|
||||
};
|
||||
|
||||
@@ -90,7 +92,8 @@ describe('JsonPatchOperationsService test suite', () => {
|
||||
return new TestService(
|
||||
requestService,
|
||||
store,
|
||||
halService
|
||||
halService,
|
||||
rdbService
|
||||
);
|
||||
|
||||
}
|
||||
@@ -103,6 +106,18 @@ describe('JsonPatchOperationsService test suite', () => {
|
||||
});
|
||||
}
|
||||
|
||||
function spyOnRdbServiceAndReturnSuccessfulRemoteData() {
|
||||
spyOn(rdbService, 'buildFromRequestUUID').and.returnValue(
|
||||
observableOf(Object.assign(createSuccessfulRemoteDataObject({ dataDefinition: 'test' }), { timeCompleted: new Date().getTime() + 10000 }))
|
||||
);
|
||||
}
|
||||
|
||||
function spyOnRdbServiceAndReturnFailedRemoteData() {
|
||||
spyOn(rdbService, 'buildFromRequestUUID').and.returnValue(
|
||||
observableOf(Object.assign(createFailedRemoteDataObject('Error', 500), { timeCompleted: new Date().getTime() + 10000 }))
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
store = getStore();
|
||||
requestService = getMockRequestService(getRequestEntry$(true));
|
||||
@@ -110,6 +125,7 @@ describe('JsonPatchOperationsService test suite', () => {
|
||||
scheduler = getTestScheduler();
|
||||
halService = new HALEndpointServiceStub(resourceEndpointURL);
|
||||
service = initTestService();
|
||||
spyOnRdbServiceAndReturnSuccessfulRemoteData();
|
||||
|
||||
spyOn(Date.prototype, 'getTime').and.callFake(() => {
|
||||
return timestamp;
|
||||
@@ -161,6 +177,7 @@ describe('JsonPatchOperationsService test suite', () => {
|
||||
scheduler = getTestScheduler();
|
||||
halService = new HALEndpointServiceStub(resourceEndpointURL);
|
||||
service = initTestService();
|
||||
spyOnRdbServiceAndReturnFailedRemoteData();
|
||||
|
||||
store.select.and.returnValue(observableOf(mockState['json/patch'][testJsonPatchResourceType]));
|
||||
store.dispatch.and.callThrough();
|
||||
@@ -224,6 +241,7 @@ describe('JsonPatchOperationsService test suite', () => {
|
||||
scheduler = getTestScheduler();
|
||||
halService = new HALEndpointServiceStub(resourceEndpointURL);
|
||||
service = initTestService();
|
||||
spyOnRdbServiceAndReturnFailedRemoteData();
|
||||
|
||||
store.select.and.returnValue(observableOf(mockState['json/patch'][testJsonPatchResourceType]));
|
||||
store.dispatch.and.callThrough();
|
||||
|
@@ -1,9 +1,23 @@
|
||||
import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, find, flatMap, map, partition, take, tap } from 'rxjs/operators';
|
||||
import { merge as observableMerge, Observable } from 'rxjs';
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
find,
|
||||
flatMap,
|
||||
map,
|
||||
partition,
|
||||
take,
|
||||
tap
|
||||
} from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import { hasValue, isEmpty, isNotEmpty, isNotUndefined, isUndefined } from '../../shared/empty.util';
|
||||
import { ErrorResponse, PostPatchSuccessResponse, RestResponse } from '../cache/response.models';
|
||||
import {
|
||||
hasValue,
|
||||
isEmpty,
|
||||
isNotEmpty,
|
||||
isNotUndefined,
|
||||
isUndefined
|
||||
} from '../../shared/empty.util';
|
||||
import { PatchRequest } from '../data/request.models';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
@@ -16,7 +30,9 @@ import {
|
||||
StartTransactionPatchOperationsAction
|
||||
} from './json-patch-operations.actions';
|
||||
import { JsonPatchOperationModel } from './json-patch.model';
|
||||
import { getResponseFromEntry } from '../shared/operators';
|
||||
import { getFirstCompletedRemoteData } from '../shared/operators';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
|
||||
/**
|
||||
* An abstract class that provides methods to make JSON Patch requests.
|
||||
@@ -27,6 +43,7 @@ export abstract class JsonPatchOperationsService<ResponseDefinitionDomain, Patch
|
||||
protected abstract store: Store<CoreState>;
|
||||
protected abstract linkPath: string;
|
||||
protected abstract halService: HALEndpointService;
|
||||
protected abstract rdbService: RemoteDataBuildService;
|
||||
protected abstract patchRequestConstructor: any;
|
||||
|
||||
/**
|
||||
@@ -85,20 +102,20 @@ export abstract class JsonPatchOperationsService<ResponseDefinitionDomain, Patch
|
||||
tap(() => this.store.dispatch(new StartTransactionPatchOperationsAction(resourceType, resourceId, startTransactionTime))),
|
||||
tap((request: PatchRequestDefinition) => this.requestService.configure(request)),
|
||||
flatMap(() => {
|
||||
const [successResponse$, errorResponse$] = partition((response: RestResponse) => response.isSuccessful)(this.requestService.getByUUID(requestId).pipe(
|
||||
getResponseFromEntry(),
|
||||
find((entry: RestResponse) => startTransactionTime < entry.timeAdded),
|
||||
map((entry: RestResponse) => entry),
|
||||
));
|
||||
return observableMerge(
|
||||
errorResponse$.pipe(
|
||||
tap(() => this.store.dispatch(new RollbacktPatchOperationsAction(resourceType, resourceId))),
|
||||
flatMap((error: ErrorResponse) => observableThrowError(error))),
|
||||
successResponse$.pipe(
|
||||
filter((response: PostPatchSuccessResponse) => isNotEmpty(response)),
|
||||
tap(() => this.store.dispatch(new CommitPatchOperationsAction(resourceType, resourceId))),
|
||||
map((response: PostPatchSuccessResponse) => response.dataDefinition),
|
||||
distinctUntilChanged()));
|
||||
return this.rdbService.buildFromRequestUUID(requestId).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
find((rd: RemoteData<any>) => startTransactionTime < rd.timeCompleted),
|
||||
map((rd: RemoteData<any>) => {
|
||||
if (rd.hasFailed) {
|
||||
this.store.dispatch(new RollbacktPatchOperationsAction(resourceType, resourceId));
|
||||
throw new Error(rd.errorMessage);
|
||||
} else if (hasValue(rd.payload) && isNotEmpty(rd.payload.dataDefinition)) {
|
||||
this.store.dispatch(new CommitPatchOperationsAction(resourceType, resourceId));
|
||||
return rd.payload.dataDefinition;
|
||||
}
|
||||
}),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user