-
Notifications
You must be signed in to change notification settings - Fork 15
Add preupgrade
hook
#129
Add preupgrade
hook
#129
Changes from 11 commits
12f99ed
409604b
6f1a7a1
552379a
eb0079a
2884100
46bc5bb
4e26e8d
c5a7b05
6ff6c4d
a763308
cb95877
94e4e3a
3362190
02b30d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,97 @@ | ||||
module.exports = class Upgrader { | ||||
constructor (session, hooks = {}) { | ||||
this.session = session | ||||
this.active = null | ||||
this.preupgrade = hooks.preupgrade || null | ||||
} | ||||
|
||||
cancel () { | ||||
if (this.active) { | ||||
this.active.cancel() | ||||
this.active = null | ||||
} | ||||
} | ||||
|
||||
onupgrade (request) { | ||||
if (this.active) this.active.cancel() | ||||
|
||||
const upgrade = this.active = new Upgrade(this) | ||||
upgrade.run(request) | ||||
|
||||
return this.active.upgraded | ||||
} | ||||
|
||||
ontruncate () { | ||||
// TODO: handle truncation | ||||
} | ||||
} | ||||
|
||||
class Upgrade { | ||||
constructor (upgrader) { | ||||
this.upgrader = upgrader | ||||
this.active = true | ||||
this.upgraded = new Promise((resolve) => { | ||||
this.done = resolve | ||||
}) | ||||
} | ||||
|
||||
cancel () { | ||||
this.active = false | ||||
} | ||||
|
||||
async run (request) { | ||||
if (!this.active) return this.done(false) | ||||
kasperisager marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
|
||||
const session = this.upgrader.session | ||||
const preupgradeLength = session.length | ||||
|
||||
if (this.upgrader.preupgrade) session._updateSnapshot() | ||||
|
||||
let upgraded = await request | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whats stopping us from awating the request in update itself? seems cleaner There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is session here, the session the user called .update on? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep ( Line 83 in 94e4e3a
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, will see what we can do to improve this, but ok for now. |
||||
|
||||
if (!this.active) return this.done(false) | ||||
|
||||
if (this.upgrader.preupgrade) { | ||||
const latest = session.session() | ||||
|
||||
let length | ||||
try { | ||||
length = await this.upgrader.preupgrade(latest) | ||||
} catch { | ||||
length = session.length | ||||
} finally { | ||||
await latest.close() | ||||
} | ||||
|
||||
if (!this.active) return this.done(false) | ||||
|
||||
if (typeof length === 'number' && length >= preupgradeLength && length < session.core.tree.length) { | ||||
kasperisager marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
session._snapshot = { | ||||
length, | ||||
byteLength: 0, | ||||
fork: session.core.tree.fork, | ||||
compatLength: length | ||||
} | ||||
|
||||
return this.done(length !== preupgradeLength) | ||||
} | ||||
} | ||||
|
||||
if (!session.sparse) { | ||||
// Download all available blocks in non-sparse mode | ||||
const start = session.length | ||||
const end = session.core.tree.length | ||||
const contig = session.contiguousLength | ||||
|
||||
await session.download({ start, end, ifAvailable: true }).downloaded() | ||||
|
||||
if (!upgraded) upgraded = session.contiguousLength !== contig | ||||
} | ||||
|
||||
if (!upgraded) return this.done(false) | ||||
|
||||
if (this.upgrader.preupgrade || session.snapshotted) return this.done(session._updateSnapshot()) | ||||
|
||||
return this.done(true) | ||||
} | ||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
const test = require('brittle') | ||
const { create, replicate } = require('./helpers') | ||
|
||
test('upgrade to latest length', async function (t) { | ||
const a = await create() | ||
await a.append(['a', 'b', 'c']) | ||
|
||
const b = await create(a.key, { | ||
preupgrade (latest) { | ||
t.is(b.length, 0) | ||
t.is(latest.length, 3) | ||
|
||
return latest.length | ||
} | ||
}) | ||
|
||
replicate(a, b, t) | ||
t.is(b.length, 0) | ||
|
||
t.ok(await b.update()) | ||
t.is(b.length, 3) | ||
}) | ||
|
||
test('stay on previous length', async function (t) { | ||
const a = await create() | ||
await a.append(['a', 'b', 'c']) | ||
|
||
const b = await create(a.key, { | ||
preupgrade (latest) { | ||
t.is(b.length, 0) | ||
t.is(latest.length, 3) | ||
|
||
return 0 | ||
} | ||
}) | ||
|
||
replicate(a, b, t) | ||
t.is(b.length, 0) | ||
|
||
t.absent(await b.update()) | ||
t.is(b.length, 0) | ||
}) | ||
|
||
test('return no length', async function (t) { | ||
const a = await create() | ||
await a.append(['a', 'b', 'c']) | ||
|
||
const b = await create(a.key, { | ||
preupgrade (latest) { | ||
t.is(b.length, 0) | ||
t.is(latest.length, 3) | ||
} | ||
}) | ||
|
||
replicate(a, b, t) | ||
t.is(b.length, 0) | ||
|
||
t.ok(await b.update()) | ||
t.is(b.length, 3) | ||
}) | ||
|
||
test('return invalid length', async function (t) { | ||
const a = await create() | ||
await a.append(['a', 'b', 'c']) | ||
|
||
const b = await create(a.key, { | ||
preupgrade (latest) { | ||
t.is(b.length, 0) | ||
t.is(latest.length, 3) | ||
|
||
return -1 | ||
} | ||
}) | ||
|
||
replicate(a, b, t) | ||
t.is(b.length, 0) | ||
|
||
t.ok(await b.update()) | ||
t.is(b.length, 3) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ensures that only 1 upgrade is active at a time by cancelling previous upgrades as new ones are applied. Not 100% sure if that's what we're after though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
either this, or it "debounces", ie reruns the hook