Skip to content

How should truncate() of local core be handled? #30

Description

@caolan

Calling truncate() on the underlying Hypercore seems to cause a few issues:

It can break get() and iteration (and probably other things):

import Hyperbee from './index.js'
import Corestore from 'corestore'

{
    const b = new Hyperbee(new Corestore('./sandbox/store'))
    await b.ready()

    const w = b.write()
    w.tryPut(Buffer.from('1'), Buffer.from('1'))
    await w.flush()

    const w2 = b.write()
    w2.tryPut(Buffer.from('2'), Buffer.from('2'))
    await w2.flush()

    await b.close();
}

{
    const b = new Hyperbee(new Corestore('./sandbox/store'))
    await b.ready()
    await b.core.truncate(1);
    // Does not complete:
    console.log((await b.get(Buffer.from('1'))).value.toString());
    // Never called:
    console.log('done');
    await b.close();
}

Will result in:

Warning: Detected unsettled top-level await at file:///...

But opening the store again after the truncate, it will work again (without key=2 in this case). The unsettled top-level await
it a particularly painful failure mode as you can't catch it with a regular try/catch around the block. The program may just stop running.

Truncating the core also does not emit an 'update' event on the Hyperbee instance when autoUpdate is true. That might be intentional, but if a user re-opens the store there will have been a change without any corresponding update event:

import Hyperbee from './index.js'
import Corestore from 'corestore'

{
    console.log('-- write --');
    const b = new Hyperbee(new Corestore('./sandbox/store', {autoUpdate: true}))
    b.on('update', () => console.log('update'));
    await b.ready()

    const w = b.write()
    w.tryPut(Buffer.from('1'), Buffer.from('1'))
    await w.flush()

    const w2 = b.write()
    w2.tryPut(Buffer.from('2'), Buffer.from('2'))
    await w2.flush()

    console.log((await b.get(Buffer.from('1')))?.value?.toString());
    console.log((await b.get(Buffer.from('2')))?.value?.toString());
    await b.close();
}

{
    console.log('-- truncate --');
    const b = new Hyperbee(new Corestore('./sandbox/store'), {autoUpdate: true})
    b.on('update', () => console.log('update'));
    await b.ready()
    await b.core.truncate(1);
    await b.close();
}

{
    console.log('-- re-open --');
    const b = new Hyperbee(new Corestore('./sandbox/store'), {autoUpdate: true})
    b.on('update', () => console.log('update'));
    await b.ready()
    console.log((await b.get(Buffer.from('1')))?.value?.toString());
    console.log((await b.get(Buffer.from('2')))?.value?.toString());
    await b.close();
}

Will output:

-- write --
update
update
1
2
-- truncate --
-- re-open --
1
undefined

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions