Skip to content
This repository has been archived by the owner on Dec 28, 2022. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
…ore-next into encrypted-from-existing
  • Loading branch information
Nuhvi committed May 23, 2022
2 parents 165fdc8 + 9f5f3db commit 2b66115
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 11 deletions.
49 changes: 38 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ module.exports = class Hypercore extends EventEmitter {

s._passCapabilities(this)

// Pass on the cache unless explicitly disabled.
if (opts.cache !== false) s.cache = this.cache

ensureEncryption(s, opts)

this.sessions.push(s)
Expand Down Expand Up @@ -580,12 +583,10 @@ module.exports = class Hypercore extends EventEmitter {
if (this.closing !== null) throw SESSION_CLOSED()
if (this._snapshot !== null && index >= this._snapshot.compatLength) throw SNAPSHOT_NOT_AVAILABLE()

const c = this.cache && this.cache.get(index)
if (c) return c
const fork = this.core.tree.fork
const b = await this._get(index, opts)
if (this.cache && fork === this.core.tree.fork && b) this.cache.set(index, b)
return b
const block = this.cache && this.cache.get(index)
if (block) return block

return this._get(index, opts)
}

async _get (index, opts) {
Expand All @@ -594,19 +595,45 @@ module.exports = class Hypercore extends EventEmitter {
let block

if (this.core.bitfield.get(index)) {
block = await this.core.blocks.get(index)
block = this._decryptAndDecode(
index,
this.core.tree.fork,
this.core.blocks.get(index),
encoding
)

if (this.cache) this.cache.set(index, block)
} else {
if (opts && opts.wait === false) return null
if (opts && opts.onwait) opts.onwait(index)

const activeRequests = (opts && opts.activeRequests) || this.activeRequests
const req = this.replicator.addBlock(activeRequests, index)

block = await req.promise
block = this._decryptAndDecode(
index,
this.core.tree.fork,
this.replicator
.addBlock(activeRequests, index)
.promise,
encoding
)
}

return block
}

async _decryptAndDecode (index, fork, req, encoding) {
const block = await req

if (this.encryption) this.encryption.decrypt(index, block)
return this._decode(encoding, block)

const value = this._decode(encoding, block)

if (this.cache && fork === this.core.tree.fork) {
this.cache.set(index, Promise.resolve(value))
}

return value
}

createReadStream (opts) {
Expand Down Expand Up @@ -758,7 +785,7 @@ module.exports = class Hypercore extends EventEmitter {
}

_decode (enc, block) {
block = block.subarray(this.padding)
if (this.padding) block = block.subarray(this.padding)
if (enc) return c.decode(enc, block)
return block
}
Expand Down
71 changes: 71 additions & 0 deletions test/cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const test = require('brittle')
const { create, replicate } = require('./helpers')

test('cache', async function (t) {
const a = await create({ cache: true })
await a.append(['a', 'b', 'c'])

const p = a.get(0)
const q = a.get(0)

t.is(await p, await q, 'blocks are identical')
})

test('session cache', async function (t) {
const a = await create({ cache: true })
await a.append(['a', 'b', 'c'])

const s = a.session()

const p = a.get(0)
const q = s.get(0)

t.is(await p, await q, 'blocks are identical')
})

test('session cache opt-out', async function (t) {
const a = await create({ cache: true })
await a.append(['a', 'b', 'c'])

const s = a.session({ cache: false })

const p = a.get(0)
const q = s.get(0)

t.not(await p, await q, 'blocks are not identical')
})

test('clear cache on truncate', async function (t) {
const a = await create({ cache: true })
await a.append(['a', 'b', 'c'])

const p = a.get(0)

await a.truncate(0)
await a.append('d')

const q = a.get(0)

t.alike(await p, Buffer.from('a'))
t.alike(await q, Buffer.from('d'))
})

test('cache on replicate', async function (t) {
const a = await create()
await a.append(['a', 'b', 'c'])

const b = await create(a.key, { cache: true })

replicate(a, b, t)

// These will issue a replicator request
const p = b.get(0)
const q = b.get(0)

t.is(await p, await q, 'blocks are identical')

// This should use the cache
const r = b.get(0)

t.is(await p, await r, 'blocks are identical')
})

0 comments on commit 2b66115

Please sign in to comment.