From d39b69a82fe1c15a54a7a77831679b93a6d1a97b Mon Sep 17 00:00:00 2001 From: haad Date: Tue, 5 Dec 2017 23:17:46 +0100 Subject: [PATCH] Refactor creating and saving DB manifest Add test for loading an empty snapshot --- src/OrbitDB.js | 85 ++++++++++++++++++++------------------------- src/db-manifest.js | 14 ++++++++ test/persistency.js | 14 ++++++++ 3 files changed, 65 insertions(+), 48 deletions(-) create mode 100644 src/db-manifest.js diff --git a/src/OrbitDB.js b/src/OrbitDB.js index e508203..cf70d37 100644 --- a/src/OrbitDB.js +++ b/src/OrbitDB.js @@ -11,6 +11,7 @@ const Cache = require('orbit-db-cache') const Keystore = require('orbit-db-keystore') const AccessController = require('./ipfs-access-controller') const OrbitDBAddress = require('./orbit-db-address') +const createDBManifest = require('./db-manifest') const Logger = require('logplease') const logger = Logger.create("orbit-db") @@ -206,45 +207,22 @@ class OrbitDB { // Save the Access Controller in IPFS const accessControllerAddress = await accessController.save() - // Creates a DB manifest file - const createDBManifest = () => { - return { - name: name, - type: type, - accessController: path.join('/ipfs', accessControllerAddress), - } - } - // Save the manifest to IPFS - const manifest = createDBManifest() - const dag = await this._ipfs.object.put(new Buffer(JSON.stringify(manifest))) - const manifestHash = dag.toJSON().multihash.toString() + const manifestHash = await createDBManifest(this._ipfs, name, type, accessControllerAddress) // Create the database address - const address = path.join('/orbitdb', manifestHash, name) - const dbAddress = OrbitDBAddress.parse(address) + const dbAddress = OrbitDBAddress.parse(path.join('/orbitdb', manifestHash, name)) - // Load local cache - try { - const cacheFilePath = path.join(dbAddress.root, dbAddress.path) - this._cache = new Cache(path.join(directory), cacheFilePath) - await this._cache.load() - } catch (e) { - logger.warn("Couldn't load Cache:", e) - } + // // Load local cache + const haveManifest = await this._loadCache(directory, dbAddress) + .then(cache => cache.get(dbAddress.toString())) + .then(localData => localData && localData.manifest) - // Check if we already have the database - let localData = await this._cache.get(dbAddress.toString()) - - if (localData && localData.manifest && !options.overwrite) + if (haveManifest && !options.overwrite) throw new Error(`Database '${dbAddress}' already exists!`) // Save the database locally - localData = Object.assign({}, this._cache.get(dbAddress.toString()), { - manifest: dbAddress.root - }) - await this._cache.set(dbAddress.toString(), localData) - logger.debug(`Saved manifest to IPFS as '${dbAddress.root}'`) + await this._saveDBManifest(directory, dbAddress) logger.debug(`Created database '${dbAddress}'`) @@ -285,19 +263,11 @@ class OrbitDB { // Parse the database address const dbAddress = OrbitDBAddress.parse(address) - // Load local cache - try { - const cacheFilePath = path.join(dbAddress.root, dbAddress.path) - this._cache = new Cache(path.join(directory), cacheFilePath) - await this._cache.load() - } catch (e) { - console.warn(e) - logger.warn("Couldn't load Cache:", e) - } - // Check if we have the database - let localData = await this._cache.get(dbAddress.toString()) - const haveDB = localData && localData.manifest + const haveDB = await this._loadCache(directory, dbAddress) + .then(cache => cache.get(dbAddress.toString())) + .then(localData => localData && localData.manifest) + logger.debug((haveDB ? 'Found' : 'Didn\'t find') + ` database '${dbAddress}'`) // If we want to try and open the database local-only, throw an error @@ -319,17 +289,36 @@ class OrbitDB { throw new Error(`Database '${dbAddress}' is type '${manifest.type}' but was opened as '${options.type}'`) // Save the database locally - localData = Object.assign({}, this._cache.get(dbAddress.toString()), { - manifest: dbAddress.root - }) - await this._cache.set(dbAddress.toString(), localData) - logger.debug(`Saved manifest to IPFS as '${dbAddress.root}'`) + await this._saveDBManifest(directory, dbAddress) // Open the the database options = Object.assign({}, options, { accessControllerAddress: manifest.accessController }) return this._openDatabase(dbAddress, manifest.type, options) } + // Save the database locally + async _saveDBManifest (directory, dbAddress) { + const cache = await this._loadCache(directory, dbAddress) + let localData = Object.assign({}, cache.get(dbAddress.toString()), { + manifest: dbAddress.root + }) + await cache.set(dbAddress.toString(), localData) + logger.debug(`Saved manifest to IPFS as '${dbAddress.root}'`) + } + + async _loadCache (directory, dbAddress) { + let cache + try { + const cacheFilePath = path.join(dbAddress.root, dbAddress.path) + cache = new Cache(path.join(directory), cacheFilePath) + await cache.load() + } catch (e) { + logger.warn("Couldn't load Cache:", e) + } + + return cache + } + async _openDatabase (address, type, options) { if (type === 'counter') return this._createStore(CounterStore, address, options) diff --git a/src/db-manifest.js b/src/db-manifest.js new file mode 100644 index 0000000..4bbc86d --- /dev/null +++ b/src/db-manifest.js @@ -0,0 +1,14 @@ +const path = require('path') + +// Creates a DB manifest file and saves it in IPFS +const createDBManifest = async (ipfs, name, type, accessControllerAddress) => { + const manifest = { + name: name, + type: type, + accessController: path.join('/ipfs', accessControllerAddress), + } + const dag = await ipfs.object.put(Buffer.from(JSON.stringify(manifest))) + return dag.toJSON().multihash.toString() +} + +module.exports = createDBManifest diff --git a/test/persistency.js b/test/persistency.js index 348c337..60349d9 100644 --- a/test/persistency.js +++ b/test/persistency.js @@ -112,6 +112,20 @@ describe('orbit-db - Persistency', function() { }) }) + describe('load from empty snapshot', function() { + it('loads database from an empty snapshot', async () => { + db = await orbitdb1.eventlog('empty-snapshot') + address = db.address.toString() + await db.saveSnapshot() + await db.close() + + db = await orbitdb1.open(address) + await db.loadFromSnapshot() + const items = db.iterator({ limit: -1 }).collect() + assert.equal(items.length, 0) + }) + }) + describe('load from snapshot', function() { beforeEach(async () => { const dbName = new Date().getTime().toString()