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 | 3× 3× 3× 3× 3× 1× 2× 2× 2× 2× 2× 2× 2× 2× 1× 2× 2× 2× 2× 2× 2× 2× | 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 |