Skip to content

Commit

Permalink
remove immediately returning the feed, instead always using callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
substack committed Dec 22, 2019
1 parent caaa74d commit ffc6283
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 98 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,31 @@ Find the public key for a string name `localName` as `cb(err, key)`.

`key` is a Buffer like `feed.key`.

# var feed = store.createLocal(localName, opts, cb)
# store.createLocal(localName, opts, cb)

Create a "local" hypercore `feed` from an optional `localName`, `opts` (passed
to hypercore's constructor), and an optional `cb(err, feed)` called after feed
metadata has been written to internal storage and the feed is ready.
to hypercore's constructor), as `cb(err, feed)` called after feed metadata has
been written to internal storage and the feed is ready.

"Local" hypercores are feeds where the secret key is stored locally and the
local machine may append messages. A new keypair is created when `createLocal()`
is called.

# var feed = store.createRemote(key, opts, cb)
# store.createRemote(key, opts, cb)

Create a "remote" hypercore `feed` from a hex string or buffer `key`, `opts`
(passed to hypercore's constructor), and an optional `cb(err, feed)` called
after feed metadata has been written to internal storage and the feed is ready.
(passed to hypercore's constructor), as `cb(err, feed)` called after feed
metadata has been written to internal storage and the feed is ready.

"Remote" hypercores are feeds where the secret key is not stored locally and the
local machine may not append messages. Use this method to sync a feed created on
a remote machine.

# var feed = store.get(id, opts)
# store.get(id, opts, cb)

Load a hypercore by its `id`: either a 32-byte buffer or hex string or a local
name string. `opts` are passed along to the hypercore constructor.
name string as `cb(err, feed)`.
`opts` are passed along to the hypercore constructor.

If this feed is already open, you will get the opened instance, which may have
been created with different hypercore options than the `opts` you specify.
Expand Down
105 changes: 38 additions & 67 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
var hypercore = require('hypercore')
var hcrypto = require('hypercore-crypto')
var deferred = require('deferred-random-access')
var TinyBox = require('tinybox')
var path = require('path')
var LRU = require('lru')
Expand Down Expand Up @@ -101,7 +100,6 @@ Storage.prototype.createLocal = function (localname, opts, cb) {
if (--pending === 0) cb(null, feed)
})
if (--pending === 0) cb(null, feed)
return feed
function onput (err) {
if (err) error(err)
else if (--pending === 0) cb(null, feed)
Expand Down Expand Up @@ -149,7 +147,6 @@ Storage.prototype.createRemote = function (key, opts, cb) {
if (--pending === 0) cb(null, feed)
})
if (--pending === 0) cb(null, feed)
return feed
function onput (err) {
if (err) error(err)
else if (--pending === 0) cb(null, feed)
Expand All @@ -168,70 +165,50 @@ Storage.prototype.get = function (id, opts, cb) {
cb = opts
opts = {}
}
var feed = null
if (self._feeds.hasOwnProperty(id)) {
// cached
feed = self._feeds[id]
} else if (Buffer.isBuffer(id) && id.length === 32) {
// buffer key
var hkey = asHexStr(id)
if (self._feeds.hasOwnProperty(hkey)) {
// cached
feed = self._feeds[hkey]
} else {
// not cached
var store = self._storageF(FEED + hkey)
feed = self._feeds[hkey] = hypercore(store, key, opts)
feed.once('close', function () {
delete self._feeds[hkey]
})
var hdkey = hcrypto.discoveryKey(id)
self._dkeys[hdkey] = key
}
} else if (/^[0-9A-Fa-f]{64}$/.test(id)) {
// string key
var key = asBuffer(id)
var store = self._storageF(FEED + id)
var hdkey = hcrypto.discoveryKey(key)
self._dkeys[hdkey] = key
feed = self._feeds[id] = hypercore(store, key, opts)
feed.once('close', function () {
delete self._feeds[hkey]
})
if (!cb) cb = noop
var key = asBuffer(id)
var hkey = asHexStr(id)
if (self._feeds.hasOwnProperty(hkey)) {
// hex or buffer key cached
ready(key, hkey, self._feeds[hkey])
} else if (/^[0-9A-Fa-f]{64}$/.test(hkey)) {
// hex or buffer key not cached
var store = self._storageF(FEED + hkey)
ready(key, hkey, hypercore(store, key, opts))
} else if (self._lnames.hasOwnProperty(id)) {
// cached local name
feed = self._feeds[asHexStr(self._lnames[id])]
// local name cached
key = self._lnames[id]
hkey = asHexStr(key)
ready(key, hkey, self._feeds[hkey])
} else {
// not cached local name
feed = hypercore(function (name) {
return deferred(function (cb) {
self.fromLocalName(id, function (err, key) {
if (err) return cb(err)
if (key) {
// exists
self._lnames[id] = key
var hkey = asHexStr(key)
var hdkey = hcrypto.discoveryKey(key)
self._dkeys[hdkey] = key
self._feeds[hkey] = feed
cb(null, self._storage(path.join(FEED + hkey, name)))
} else {
// does not exist
cb(new Error('feed not found'))
}
})
})
}, opts)
feed.once('close', function () {
delete self._feeds[hkey]
// local name not cached
self.fromLocalName(id, function (err, key) {
if (err) return cb(err)
if (key) {
// exists
self._lnames[id] = key
var hkey = asHexStr(key)
var store = self._storageF(FEED + hkey)
ready(key, hkey, hypercore(store, key, opts))
} else {
// does not exist
cb(new Error('feed not found'))
}
})
}
if (typeof cb === 'function') {
function ready (key, hkey, feed) {
if (!self._feeds.hasOwnProperty(hkey)) {
self._feeds[hkey] = feed
var hdkey = hcrypto.discoveryKey(key)
self._dkeys[hdkey] = key
feed.once('close', function () {
delete self._feeds[hkey]
})
}
feed.ready(function () {
cb(null, feed)
})
}
return feed
}

// Whether a hypercore is stored on disk or in memory
Expand Down Expand Up @@ -264,10 +241,7 @@ Storage.prototype.getOrCreateRemote = function (key, opts, cb) {
self.has(key, function (err, has) {
if (err) return cb(err)
if (has) {
var feed = self.get(key, opts)
feed.ready(function () {
cb(null, feed)
})
self.get(key, opts, cb)
} else self.createRemote(key, opts, cb)
})
}
Expand All @@ -284,10 +258,7 @@ Storage.prototype.getOrCreateLocal = function (localname, opts, cb) {
self.hasLocal(localname, function (err, has) {
if (err) return cb(err)
if (has) {
var feed = self.get(localname, opts)
feed.ready(function () {
cb(null, feed)
})
self.get(localname, opts, cb)
} else self.createLocal(localname, opts, cb)
})
}
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"author": "noffle",
"license": "ISC",
"dependencies": {
"deferred-random-access": "^1.0.0",
"hypercore": "^8.3.0",
"tinybox": "0.0.0"
},
Expand Down
40 changes: 22 additions & 18 deletions test/local.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ var mkdirp = require('mkdirp')
var { randomBytes } = require('hypercore-crypto')

test('create local without name', function (t) {
t.plan(2)
t.plan(3)
var s = Storage(ram)
var feed = s.createLocal()
feed.ready(function () {
s.createLocal(function (err, feed) {
t.ifError(err)
s.fromDiscoveryKey(feed.discoveryKey, function (err, key) {
t.ifError(err)
t.deepEqual(key, feed.key, 'discovery key')
Expand All @@ -20,10 +20,10 @@ test('create local without name', function (t) {
})

test('create local with name', function (t) {
t.plan(4)
t.plan(5)
var s = Storage(ram)
var feed = s.createLocal('cool')
feed.ready(function () {
s.createLocal('cool', function (err, feed) {
t.ifError(err)
s.fromDiscoveryKey(feed.discoveryKey, function (err, key) {
t.ifError(err)
t.deepEqual(key, feed.key, 'key from discovery key')
Expand All @@ -36,48 +36,52 @@ test('create local with name', function (t) {
})

test('create local and get', function (t) {
t.plan(4)
t.plan(6)
var dir = path.join(tmpdir(), randomBytes(8).toString('hex'))
mkdirp.sync(dir)
var s = Storage(function (name) {
return raf(path.join(dir, name))
})
var feed0 = s.createLocal()
feed0.ready(function () {
s.createLocal(function (err, feed0) {
t.ifError(err)
feed0.append('hi', function (err) {
t.ifError(err)
s.close(feed0.key, function (err) {
t.ifError(err)
var feed1 = s.get(feed0.key)
feed1.get(0, function (err, buf) {
s.get(feed0.key, function (err, feed1) {
t.ifError(err)
t.deepEqual(buf, Buffer.from('hi'))
feed1.get(0, function (err, buf) {
t.ifError(err)
t.deepEqual(buf, Buffer.from('hi'))
})
})
})
})
})
})

test('create local and get from name', function (t) {
t.plan(6)
t.plan(8)
var dir = path.join(tmpdir(), randomBytes(8).toString('hex'))
mkdirp.sync(dir)
var s = Storage(function (name) {
return raf(path.join(dir, name))
})
var feed0 = s.createLocal('wow')
feed0.ready(function () {
s.createLocal('wow', function (err, feed0) {
t.ifError(err)
feed0.append('hi', function (err) {
t.ifError(err)
s.close(feed0.key, function (err) {
t.ifError(err)
s.fromLocalName('wow', function (err, key) {
t.ifError(err)
t.deepEqual(key, feed0.key, 'key from local name')
var feed1 = s.get(key)
feed1.get(0, function (err, buf) {
s.get(key, function (err, feed1) {
t.ifError(err)
t.deepEqual(buf, Buffer.from('hi'))
feed1.get(0, function (err, buf) {
t.ifError(err)
t.deepEqual(buf, Buffer.from('hi'))
})
})
})
})
Expand Down
16 changes: 12 additions & 4 deletions test/remote.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test('create local without a name and sync to a remote without a name', function
})

test('create local with a name and sync to a remote with a different name', function (t) {
t.plan(6)
t.plan(8)
var sA = Storage(ram)
var sB = Storage(ram)
sA.createLocal('x', function (err, feedA) {
Expand All @@ -57,9 +57,17 @@ test('create local with a name and sync to a remote with a different name', func
t.ifError(err)
sB.createRemote(feedA.key, { localname: 'y' }, function (err, feedB) {
t.ifError(err)
var feedB2 = sB.get('y')
var feedA2 = sA.get('x')
sync(feedA2, feedB2)
var feedA2, feedB2, pending = 2
sB.get('y', function (err, feed) {
t.ifError(err)
feedB2 = feed
if (--pending === 0) sync(feedA2, feedB2)
})
sA.get('x', function (err, feed) {
t.ifError(err)
feedA2 = feed
if (--pending === 0) sync(feedA2, feedB2)
})
})
})
})
Expand Down

0 comments on commit ffc6283

Please sign in to comment.