Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit ef824d3

Browse files
committed
fix: make recursive true defaults, tests and more
1 parent d04e5c5 commit ef824d3

File tree

11 files changed

+190
-366
lines changed

11 files changed

+190
-366
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"aegir": "^18.1.0",
6666
"base64url": "^3.0.1",
6767
"chai": "^4.2.0",
68+
"clear-module": "^3.2.0",
6869
"delay": "^4.1.0",
6970
"detect-node": "^2.0.4",
7071
"dir-compare": "^1.4.0",
@@ -105,6 +106,7 @@
105106
"get-folder-size": "^2.0.0",
106107
"glob": "^7.1.3",
107108
"hapi-pino": "^5.4.1",
109+
"hashlru": "^2.3.0",
108110
"human-to-milliseconds": "^1.0.0",
109111
"interface-datastore": "~0.6.0",
110112
"ipfs-bitswap": "~0.23.0",
@@ -175,7 +177,6 @@
175177
"pull-stream": "^3.6.9",
176178
"pull-stream-to-stream": "^1.3.4",
177179
"readable-stream": "^3.1.1",
178-
"receptacle": "^1.3.2",
179180
"stream-to-pull-stream": "^1.7.3",
180181
"superstruct": "~0.6.0",
181182
"tar-stream": "^2.0.0",

src/cli/commands/name/publish.js

+10-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict'
22

3-
const print = require('../../utils').print
3+
const { print } = require('../../utils')
44

55
module.exports = {
66
command: 'publish <ipfsPath>',
@@ -11,36 +11,34 @@ module.exports = {
1111
resolve: {
1212
alias: 'r',
1313
describe: 'Resolve given path before publishing. Default: true.',
14-
default: true
14+
default: true,
15+
type: 'boolean'
1516
},
1617
lifetime: {
1718
alias: 't',
1819
describe: 'Time duration that the record will be valid for. Default: 24h.',
19-
default: '24h'
20+
default: '24h',
21+
type: 'string'
2022
},
2123
key: {
2224
alias: 'k',
2325
describe: 'Name of the key to be used or a valid PeerID, as listed by "ipfs key list -l". Default: self.',
24-
default: 'self'
26+
default: 'self',
27+
type: 'string'
2528
},
2629
ttl: {
2730
describe: 'Time duration this record should be cached for (caution: experimental).',
28-
default: ''
31+
default: '',
32+
type: 'string'
2933
}
3034
},
3135

3236
handler (argv) {
3337
argv.resolve((async () => {
3438
// yargs-promise adds resolve/reject properties to argv
3539
// resolve should use the alias as resolve will always be overwritten to a function
36-
let resolve = true
37-
38-
if (argv.r === false || argv.r === 'false') {
39-
resolve = false
40-
}
41-
4240
const opts = {
43-
resolve,
41+
resolve: argv.r,
4442
lifetime: argv.lifetime,
4543
key: argv.key,
4644
ttl: argv.ttl

src/cli/commands/name/resolve.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module.exports = {
1818
type: 'boolean',
1919
alias: 'r',
2020
describe: 'Resolve until the result is not an IPNS name. Default: false.',
21-
default: false
21+
default: true
2222
}
2323
},
2424

src/core/components/name.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ module.exports = function name (self) {
152152

153153
options = mergeOptions({
154154
nocache: false,
155-
recursive: false
155+
recursive: true
156156
}, options)
157157

158158
const offline = self._options.offline

src/core/ipns/index.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const { createFromPrivKey } = require('peer-id')
44
const series = require('async/series')
5-
const Receptacle = require('receptacle')
65

76
const errcode = require('err-code')
87
const debug = require('debug')
@@ -13,20 +12,28 @@ const IpnsPublisher = require('./publisher')
1312
const IpnsRepublisher = require('./republisher')
1413
const IpnsResolver = require('./resolver')
1514
const path = require('./path')
16-
15+
const { normalizePath } = require('../utils')
16+
const TLRU = require('../../utils/tlru')
1717
const defaultRecordTtl = 60 * 1000
1818

1919
class IPNS {
2020
constructor (routing, datastore, peerInfo, keychain, options) {
2121
this.publisher = new IpnsPublisher(routing, datastore)
2222
this.republisher = new IpnsRepublisher(this.publisher, datastore, peerInfo, keychain, options)
2323
this.resolver = new IpnsResolver(routing)
24-
this.cache = new Receptacle({ max: 1000 }) // Create an LRU cache with max 1000 items
24+
this.cache = new TLRU(1000)
2525
this.routing = routing
2626
}
2727

2828
// Publish
29-
publish (privKey, value, lifetime, callback) {
29+
publish (privKey, value, lifetime = IpnsPublisher.defaultRecordLifetime, callback) {
30+
try {
31+
value = normalizePath(value)
32+
} catch (err) {
33+
log.error(err)
34+
return callback(err)
35+
}
36+
3037
series([
3138
(cb) => createFromPrivKey(privKey.bytes, cb),
3239
(cb) => this.publisher.publishWithEOL(privKey, value, lifetime, cb)
@@ -38,12 +45,12 @@ class IPNS {
3845

3946
log(`IPNS value ${value} was published correctly`)
4047

41-
// Add to cache
48+
// // Add to cache
4249
const id = results[0].toB58String()
4350
const ttEol = parseFloat(lifetime)
4451
const ttl = (ttEol < defaultRecordTtl) ? ttEol : defaultRecordTtl
4552

46-
this.cache.set(id, value, { ttl: ttl })
53+
this.cache.set(id, value, ttl)
4754

4855
log(`IPNS value ${value} was cached correctly`)
4956

@@ -96,7 +103,7 @@ class IPNS {
96103
// Initialize keyspace
97104
// sets the ipns record for the given key to point to an empty directory
98105
initializeKeyspace (privKey, value, callback) {
99-
this.publisher.publish(privKey, value, callback)
106+
this.publish(privKey, value, IpnsPublisher.defaultRecordLifetime, callback)
100107
}
101108
}
102109

src/core/ipns/publisher.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ log.error = debug('ipfs:ipns:publisher:error')
1111

1212
const ipns = require('ipns')
1313

14-
const defaultRecordTtl = 60 * 60 * 1000
14+
const defaultRecordLifetime = 60 * 60 * 1000
1515

1616
// IpnsPublisher is capable of publishing and resolving names to the IPFS routing system.
1717
class IpnsPublisher {
@@ -46,7 +46,7 @@ class IpnsPublisher {
4646

4747
// Accepts a keypair, as well as a value (ipfsPath), and publishes it out to the routing system
4848
publish (privKey, value, callback) {
49-
this.publishWithEOL(privKey, value, defaultRecordTtl, callback)
49+
this.publishWithEOL(privKey, value, defaultRecordLifetime, callback)
5050
}
5151

5252
_putRecordToRouting (record, peerId, callback) {
@@ -269,4 +269,5 @@ class IpnsPublisher {
269269
}
270270
}
271271

272+
IpnsPublisher.defaultRecordLifetime = defaultRecordLifetime
272273
exports = module.exports = IpnsPublisher

src/http/api/resources/name.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ exports.resolve = {
77
query: Joi.object().keys({
88
arg: Joi.string(),
99
nocache: Joi.boolean().default(false),
10-
recursive: Joi.boolean().default(false)
10+
recursive: Joi.boolean().default(true)
1111
}).unknown()
1212
},
1313
async handler (request, h) {

src/utils/tlru.js

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
'use strict'
2+
const hashlru = require('hashlru')
3+
4+
/**
5+
* Time Aware Least Recent Used Cache
6+
* @see https://arxiv.org/pdf/1801.00390
7+
* @todo move this to ipfs-utils or it's own package
8+
*
9+
* @class TLRU
10+
*/
11+
class TLRU {
12+
/**
13+
* Creates an instance of TLRU.
14+
*
15+
* @param {number} maxSize
16+
* @memberof TLRU
17+
*/
18+
constructor (maxSize) {
19+
this.lru = hashlru(maxSize)
20+
}
21+
22+
/**
23+
* Get the value from the a key
24+
*
25+
* @param {string} key
26+
* @returns {any}
27+
* @memberof TLRU
28+
*/
29+
get (key) {
30+
const value = this.lru.get(key)
31+
if (value) {
32+
if ((value.expire) && (value.expire < Date.now())) {
33+
this.lru.remove(key)
34+
return undefined
35+
}
36+
}
37+
return value.value
38+
}
39+
40+
/**
41+
* Set a key value pair
42+
*
43+
* @param {string} key
44+
* @param {any} value
45+
* @param {number} ttl - in miliseconds
46+
* @memberof TLRU
47+
*/
48+
set (key, value, ttl) {
49+
this.lru.set(key, { value, expire: Date.now() + ttl })
50+
}
51+
52+
/**
53+
* Find if the cache has the key
54+
*
55+
* @param {string} key
56+
* @returns {boolean}
57+
* @memberof TLRU
58+
*/
59+
has (key) {
60+
return this.lru.has(key)
61+
}
62+
63+
/**
64+
* Remove key
65+
*
66+
* @param {string} key
67+
* @memberof TLRU
68+
*/
69+
remove (key) {
70+
this.lru.remove(key)
71+
}
72+
73+
/**
74+
* Clears the cache
75+
*
76+
* @memberof TLRU
77+
*/
78+
clear () {
79+
this.lru.clear()
80+
}
81+
}
82+
83+
module.exports = TLRU

test/cli/name-pubsub.js

-50
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ const ipfsExec = require('../utils/ipfs-exec')
1414
const DaemonFactory = require('ipfsd-ctl')
1515
const df = DaemonFactory.create({ type: 'js' })
1616

17-
const checkAll = (bits) => string => bits.every(bit => string.includes(bit))
18-
const emptyDirCid = 'QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn'
19-
2017
const spawnDaemon = (callback) => {
2118
df.spawn({
2219
exec: `./src/cli/bin.js`,
@@ -165,53 +162,6 @@ describe('name-pubsub', () => {
165162
})
166163
})
167164
})
168-
169-
describe('pubsub records', () => {
170-
let cidAdded
171-
172-
before(function (done) {
173-
this.timeout(50 * 1000)
174-
ipfsA('add src/init-files/init-docs/readme')
175-
.then((out) => {
176-
cidAdded = out.split(' ')[1]
177-
done()
178-
})
179-
})
180-
181-
it('should publish the received record to the subscriber', function () {
182-
this.timeout(80 * 1000)
183-
184-
return ipfsB(`name resolve ${nodeBId.id}`)
185-
.then((res) => {
186-
expect(res).to.exist()
187-
expect(res).to.satisfy(checkAll([emptyDirCid])) // Empty dir received (subscribed)
188-
189-
return ipfsA(`name resolve ${nodeBId.id}`)
190-
})
191-
.catch((err) => {
192-
expect(err).to.exist() // Not available (subscribed now)
193-
194-
return ipfsB(`name publish ${cidAdded}`)
195-
})
196-
.then((res) => {
197-
// published to IpfsB and published through pubsub to ipfsa
198-
expect(res).to.exist()
199-
expect(res).to.satisfy(checkAll([cidAdded, nodeBId.id]))
200-
201-
return ipfsB(`name resolve ${nodeBId.id}`)
202-
})
203-
.then((res) => {
204-
expect(res).to.exist()
205-
expect(res).to.satisfy(checkAll([cidAdded]))
206-
207-
return ipfsA(`name resolve ${nodeBId.id}`)
208-
})
209-
.then((res) => {
210-
expect(res).to.exist()
211-
expect(res).to.satisfy(checkAll([cidAdded])) // value propagated to node B
212-
})
213-
})
214-
})
215165
})
216166

217167
describe('disabled', () => {

0 commit comments

Comments
 (0)