patching changes

This commit is contained in:
lotte
2018-09-11 16:05:21 +02:00
parent 14fd58dd21
commit acb5f5197d
6 changed files with 102 additions and 12 deletions

View File

@@ -41,8 +41,8 @@
"server:watch": "nodemon dist/server.js", "server:watch": "nodemon dist/server.js",
"server:watch:debug": "nodemon --debug dist/server.js", "server:watch:debug": "nodemon --debug dist/server.js",
"webpack:watch": "webpack -w --mode development", "webpack:watch": "webpack -w --mode development",
"watch": "yarn run build && npm-run-all -p webpack:watch server:watch --mode development", "watch": "yarn run build && npm-run-all -p webpack:watch server:watch",
"watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug --mode development", "watch:debug": "yarn run build && npm-run-all -p webpack:watch server:watch:debug",
"predebug": "yarn run build", "predebug": "yarn run build",
"predebug:server": "yarn run build", "predebug:server": "yarn run build",
"debug": "node --debug-brk dist/server.js", "debug": "node --debug-brk dist/server.js",
@@ -96,6 +96,7 @@
"core-js": "2.5.3", "core-js": "2.5.3",
"express": "4.16.2", "express": "4.16.2",
"express-session": "1.15.6", "express-session": "1.15.6",
"fast-json-patch": "^2.0.7",
"font-awesome": "4.7.0", "font-awesome": "4.7.0",
"http-server": "0.11.1", "http-server": "0.11.1",
"https": "1.0.0", "https": "1.0.0",

View File

@@ -2,6 +2,7 @@ import { Action } from '@ngrx/store';
import { type } from '../../shared/ngrx/type'; import { type } from '../../shared/ngrx/type';
import { CacheableObject } from './object-cache.reducer'; import { CacheableObject } from './object-cache.reducer';
import { Operation } from 'fast-json-patch';
/** /**
* The list of ObjectCacheAction type definitions * The list of ObjectCacheAction type definitions
@@ -9,7 +10,8 @@ import { CacheableObject } from './object-cache.reducer';
export const ObjectCacheActionTypes = { export const ObjectCacheActionTypes = {
ADD: type('dspace/core/cache/object/ADD'), ADD: type('dspace/core/cache/object/ADD'),
REMOVE: type('dspace/core/cache/object/REMOVE'), REMOVE: type('dspace/core/cache/object/REMOVE'),
RESET_TIMESTAMPS: type('dspace/core/cache/object/RESET_TIMESTAMPS') RESET_TIMESTAMPS: type('dspace/core/cache/object/RESET_TIMESTAMPS'),
PATCH: type('dspace/core/cache/object/PATCH')
}; };
/* tslint:disable:max-classes-per-file */ /* tslint:disable:max-classes-per-file */
@@ -79,6 +81,30 @@ export class ResetObjectCacheTimestampsAction implements Action {
this.payload = newTimestamp; this.payload = newTimestamp;
} }
} }
/**
* An ngrx action to add new operations to a specified cached objects
*/
export class PatchObjectCacheAction implements Action {
type = ObjectCacheActionTypes.PATCH;
payload: {
uuid: string,
operations: Operation[]
};
/**
* Create a new PatchObjectCacheAction
*
* @param uuid
* the uuid of the object that should be updated
* @param operations
* the list of operations to add
*/
constructor(uuid: string, operations: Operation[]) {
this.payload = { uuid, operations };
}
}
/* tslint:enable:max-classes-per-file */ /* tslint:enable:max-classes-per-file */
/** /**
@@ -87,4 +113,5 @@ export class ResetObjectCacheTimestampsAction implements Action {
export type ObjectCacheAction export type ObjectCacheAction
= AddToObjectCacheAction = AddToObjectCacheAction
| RemoveFromObjectCacheAction | RemoveFromObjectCacheAction
| ResetObjectCacheTimestampsAction; | ResetObjectCacheTimestampsAction
| PatchObjectCacheAction;

View File

@@ -1,10 +1,11 @@
import { import {
ObjectCacheAction, ObjectCacheActionTypes, AddToObjectCacheAction, ObjectCacheAction, ObjectCacheActionTypes, AddToObjectCacheAction,
RemoveFromObjectCacheAction, ResetObjectCacheTimestampsAction RemoveFromObjectCacheAction, ResetObjectCacheTimestampsAction, PatchObjectCacheAction
} from './object-cache.actions'; } from './object-cache.actions';
import { hasValue } from '../../shared/empty.util'; import { hasValue, isNotEmpty } from '../../shared/empty.util';
import { CacheEntry } from './cache-entry'; import { CacheEntry } from './cache-entry';
import { ResourceType } from '../shared/resource-type'; import { ResourceType } from '../shared/resource-type';
import { Operation } from 'fast-json-patch';
export enum DirtyType { export enum DirtyType {
Created = 'Created', Created = 'Created',
@@ -36,6 +37,7 @@ export class ObjectCacheEntry implements CacheEntry {
timeAdded: number; timeAdded: number;
msToLive: number; msToLive: number;
requestHref: string; requestHref: string;
operations: Operation[];
} }
/** /**
@@ -76,6 +78,9 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi
return resetObjectCacheTimestamps(state, action as ResetObjectCacheTimestampsAction) return resetObjectCacheTimestamps(state, action as ResetObjectCacheTimestampsAction)
} }
case ObjectCacheActionTypes.PATCH: {
return patchObjectCache(state, action as PatchObjectCacheAction);
}
default: { default: {
return state; return state;
} }
@@ -98,7 +103,8 @@ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheActio
data: action.payload.objectToCache, data: action.payload.objectToCache,
timeAdded: action.payload.timeAdded, timeAdded: action.payload.timeAdded,
msToLive: action.payload.msToLive, msToLive: action.payload.msToLive,
requestHref: action.payload.requestHref requestHref: action.payload.requestHref,
operations: []
} }
}); });
} }
@@ -143,3 +149,23 @@ function resetObjectCacheTimestamps(state: ObjectCacheState, action: ResetObject
}); });
return newState; return newState;
} }
/**
* Add the list of patch operations to a cached object
*
* @param state
* the current state
* @param action
* a PatchObjectCacheAction
* @return ObjectCacheState
* the new state, with the new operations added to the state of the specified ObjectCacheEntry
*/
function patchObjectCache(state: ObjectCacheState, action: PatchObjectCacheAction): ObjectCacheState {
const uuid = action.payload.uuid;
const operations = action.payload.operations;
const newState = Object.assign({}, state);
if (hasValue(newState[uuid])) {
newState[uuid].operations = state[uuid].operations.concat(operations);
}
return newState;
}

View File

@@ -1,18 +1,23 @@
import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
import { distinctUntilChanged, filter, first, map, mergeMap, take } from 'rxjs/operators'; import { distinctUntilChanged, filter, first, map, mergeMap, take, tap } from 'rxjs/operators';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { MemoizedSelector, select, Store } from '@ngrx/store'; import { MemoizedSelector, select, Store } from '@ngrx/store';
import { IndexName } from '../index/index.reducer'; import { IndexName } from '../index/index.reducer';
import { CacheableObject, ObjectCacheEntry } from './object-cache.reducer'; import { CacheableObject, ObjectCacheEntry } from './object-cache.reducer';
import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; import {
import { hasNoValue } from '../../shared/empty.util'; AddToObjectCacheAction,
PatchObjectCacheAction,
RemoveFromObjectCacheAction
} from './object-cache.actions';
import { hasNoValue, isNotEmpty } from '../../shared/empty.util';
import { GenericConstructor } from '../shared/generic-constructor'; import { GenericConstructor } from '../shared/generic-constructor';
import { coreSelector, CoreState } from '../core.reducers'; import { coreSelector, CoreState } from '../core.reducers';
import { pathSelector } from '../shared/selectors'; import { pathSelector } from '../shared/selectors';
import { NormalizedObjectFactory } from './models/normalized-object-factory'; import { NormalizedObjectFactory } from './models/normalized-object-factory';
import { NormalizedObject } from './models/normalized-object.model'; import { NormalizedObject } from './models/normalized-object.model';
import { applyPatch, Operation } from 'fast-json-patch';
function selfLinkFromUuidSelector(uuid: string): MemoizedSelector<CoreState, string> { function selfLinkFromUuidSelector(uuid: string): MemoizedSelector<CoreState, string> {
return pathSelector<CoreState, string>(coreSelector, 'index', IndexName.OBJECT, uuid); return pathSelector<CoreState, string>(coreSelector, 'index', IndexName.OBJECT, uuid);
@@ -85,7 +90,11 @@ export class ObjectCacheService {
map((entry: ObjectCacheEntry) => { map((entry: ObjectCacheEntry) => {
const type: GenericConstructor<NormalizedObject> = NormalizedObjectFactory.getConstructor(entry.data.type); const type: GenericConstructor<NormalizedObject> = NormalizedObjectFactory.getConstructor(entry.data.type);
return Object.assign(new type(), entry.data) as T return Object.assign(new type(), entry.data) as T
})); }),
// map((entry: ObjectCacheEntry) =>
// applyPatch(entry.data, entry.operations).newDocument
// )
);
} }
private getEntry(selfLink: string): Observable<ObjectCacheEntry> { private getEntry(selfLink: string): Observable<ObjectCacheEntry> {
@@ -195,4 +204,26 @@ export class ObjectCacheService {
} }
} }
/**
* Add operations to a the existing list of operations for an ObjectCacheEntry
* @param {string} uuid
* the uuid of the ObjectCacheEntry
* @param {Operation[]} patch
* list of operations to perform
*/
private addOperations(uuid: string, patch: Operation[]) {
this.store.dispatch(new PatchObjectCacheAction(uuid, patch));
}
/**
* Check whether there are any unperformed operations for an ObjectCacheEntry
*
* @param entry
* the entry to check
* @return boolean
* false if the entry is there are no operations left in the ObjectCacheEntry, true otherwise
*/
private isDirty(entry: ObjectCacheEntry): boolean {
return isNotEmpty(entry.operations);
}
} }

View File

@@ -30,7 +30,6 @@ export interface FormState {
const initialState: FormState = Object.create(null); const initialState: FormState = Object.create(null);
export function formReducer(state = initialState, action: FormAction): FormState { export function formReducer(state = initialState, action: FormAction): FormState {
console.log('TEST');
switch (action.type) { switch (action.type) {
case FormActionTypes.FORM_INIT: { case FormActionTypes.FORM_INIT: {

View File

@@ -3026,6 +3026,12 @@ fast-glob@^2.0.2:
merge2 "^1.2.1" merge2 "^1.2.1"
micromatch "^3.1.10" micromatch "^3.1.10"
fast-json-patch@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-2.0.7.tgz#55864b08b1e50381d2f37fd472bb2e18fe54a733"
dependencies:
deep-equal "^1.0.1"
fast-json-stable-stringify@^2.0.0: fast-json-stable-stringify@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"