all files / collab/ DocumentEngine.js

64.71% Statements 22/34
38.89% Branches 7/18
77.78% Functions 7/9
68.75% Lines 22/32
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121                                                                                                                                                                                                     
import { EventEmitter } from '../util'
import SnapshotEngine from './SnapshotEngine'
 
/*
  DocumentEngine
*/
class DocumentEngine extends EventEmitter {
  constructor(config) {
    super()
    this.changeStore = config.changeStore
    this.snapshotStore = config.snapshotStore
    // Snapshot creation frequency (e.g. if it equals 15 then every
    // 15th version will be saved as snapshot)
    this.snapshotFrequency = config.snapshotFrequency || 1
    this.snapshotEngine = new SnapshotEngine({
      changeStore: this.changeStore,
      snapshotStore: this.snapshotStore
    })
  }
 
  /*
    Creates a new document
 
    A valid document must have at least one valid change
  */
  createDocument(documentId, initialChange, cb) {
    this.addChange(documentId, initialChange, cb)
  }
 
  /*
    Get a document snapshot for a given version. If no version
    is provivded, the latest version is returned
  */
  getDocument(documentId, version, cb) {
    Eif (typeof version === 'function') {
      cb = version
      version = undefined
    }
    Iif (!documentId) {
      throw new Error('Invalid Arguments')
    }
    Eif (version === undefined) {
      this.getVersion(documentId, (err, version) => {
        Iif (err) return cb(err)
        this.snapshotEngine.getSnapshot(documentId, version, cb)
      })
    } else {
      this.snapshotEngine.getSnapshot(documentId, version, cb)
    }
  }
 
  /*
    Delete document by documentId
  */
  deleteDocument(documentId, cb) {
    this.changeStore.deleteChanges(documentId, (err) => {
      if (err) {
        return cb(new Error('Deleting changes failed'))
      }
    })
  }
 
  /*
    Check if a given document exists
  */
  documentExists(documentId, cb) {
    this.getVersion(documentId, (err, version) => {
      if (version >= 0) {
        cb(null, true)
      } else {
        cb(null, false)
      }
    })
  }
 
  /*
    Get changes based on documentId, sinceVersion
  */
  getChanges(documentId, sinceVersion, toVersion, cb) {
    this.changeStore.getChanges(documentId, sinceVersion, toVersion, cb)
  }
 
  /*
    Get version for given documentId
  */
  getVersion(documentId, cb) {
    this.changeStore.getVersion(documentId, cb)
  }
 
  /*
    Here the implementer decides whether a snapshot should be created or not.
    It may be a good strategy to only create a snaphot for every 10th version.
    However for now we will just snapshot each change to keep things simple.
  */
  requestSnapshot(documentId, version, cb) {
    Eif (version % this.snapshotFrequency === 0) {
      this.snapshotEngine.createSnapshot(documentId, version, cb)
    } else {
      cb(null) // do nothing
    }
  }
 
  /*
    Add change to a given documentId.
 
    Snapshot creation is requested on each change to be stored.
  */
  addChange(documentId, change, cb) {
    this.changeStore.addChange(documentId, change, (err, newVersion) => {
      Iif (err) return cb(err)
 
      this.requestSnapshot(documentId, newVersion, () => {
        // no matter if snaphot creation errored or not we will confirm change
        cb(null, newVersion)
      })
    })
  }
}
 
export default DocumentEngine