Skip to content
Snippets Groups Projects
object-cache.reducer.ts 3.3 KiB
Newer Older
Art Lowel's avatar
Art Lowel committed
import {
  ObjectCacheAction, ObjectCacheActionTypes, AddToObjectCacheAction,
  RemoveFromObjectCacheAction, ResetObjectCacheTimestampsAction
} from "./object-cache.actions";
Art Lowel's avatar
Art Lowel committed
import { hasValue } from "../../shared/empty.util";
import { CacheEntry } from "./cache-entry";
Art Lowel's avatar
Art Lowel committed

/**
 * An interface to represent objects that can be cached
 *
 * A cacheable object should have a uuid
 */
Art Lowel's avatar
Art Lowel committed
export interface CacheableObject {
  uuid: string;
}

/**
 * An entry in the ObjectCache
 */
export class ObjectCacheEntry implements CacheEntry {
Art Lowel's avatar
Art Lowel committed
  data: CacheableObject;
  timeAdded: number;
  msToLive: number;
}

/**
 * The ObjectCache State
 *
 * Consists of a map with UUIDs as keys,
 * and ObjectCacheEntries as values
 */
Art Lowel's avatar
Art Lowel committed
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);

/**
 * The ObjectCache Reducer
 *
 * @param state
 *    the current state
 * @param action
 *    the action to perform on the state
 * @return ObjectCacheState
 *    the new state
 */
Art Lowel's avatar
Art Lowel committed
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)
    }

Art Lowel's avatar
Art Lowel committed
    case ObjectCacheActionTypes.RESET_TIMESTAMPS: {
      return resetObjectCacheTimestamps(state, <ResetObjectCacheTimestampsAction>action)
    }

Art Lowel's avatar
Art Lowel committed
    default: {
      return state;
    }
  }
};

/**
 * Add an object to the cache
 *
 * @param state
 *    the current state
 * @param action
 *    an AddToObjectCacheAction
 * @return ObjectCacheState
 *    the new state, with the object added, or overwritten.
 */
Art Lowel's avatar
Art Lowel committed
function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState {
  return Object.assign({}, state, {
    [action.payload.objectToCache.uuid]: {
      data: action.payload.objectToCache,
      timeAdded: action.payload.timeAdded,
Art Lowel's avatar
Art Lowel committed
      msToLive: action.payload.msToLive
    }
  });
}

/**
 * Remove an object from the cache
 *
 * @param state
 *    the current state
 * @param action
 *    an RemoveFromObjectCacheAction
 * @return ObjectCacheState
 *    the new state, with the object removed if it existed.
 */
Art Lowel's avatar
Art Lowel committed
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;
  }
}
Art Lowel's avatar
Art Lowel committed

/**
 * Set the timeAdded timestamp of every cached object to the specified value
 *
 * @param state
 *    the current state
 * @param action
 *    a ResetObjectCacheTimestampsAction
 * @return ObjectCacheState
 *    the new state, with all timeAdded timestamps set to the specified value
 */
function resetObjectCacheTimestamps(state: ObjectCacheState, action: ResetObjectCacheTimestampsAction): ObjectCacheState {
  let newState = Object.create(null);
  Object.keys(state).forEach(key => {
    newState[key] = Object.assign({}, state[key], {
      timeAdded: action.payload
    });
  });
  return newState;
}