pzp-db/test/log/compact.test.js

172 lines
4.6 KiB
JavaScript

const test = require('node:test')
const assert = require('node:assert')
const p = require('node:util').promisify
const Log = require('../../lib/log')
test('Log compaction', async (t) => {
await t.test('compact a log that does not have holes', async (t) => {
const file = '/tmp/pzp-db-log-compaction-test-' + Date.now() + '.log'
const log = Log(file, { blockSize: 15 })
const stats = await p(log.stats)()
assert.equal(stats.totalBytes, 0, 'stats.totalBytes (1)')
assert.equal(stats.deletedBytes, 0, 'stats.deletedBytes (1)')
const buf1 = Buffer.from('first')
const buf2 = Buffer.from('second')
const offset1 = await p(log.append)(buf1)
const offset2 = await p(log.append)(buf2)
await p(log.onDrain)()
assert('append two records')
const stats2 = await p(log.stats)()
assert.equal(stats2.totalBytes, 25, 'stats.totalBytes (2)')
assert.equal(stats2.deletedBytes, 0, 'stats.deletedBytes (2)')
const progressArr = []
log.compactionProgress((stats) => {
progressArr.push(stats)
})
await p(log.compact)()
assert.deepEqual(
progressArr,
[
{ percent: 0, done: false },
{ percent: 1, done: true, sizeDiff: 0, holesFound: 0 },
],
'progress events'
)
const stats3 = await p(log.stats)()
assert.equal(stats3.totalBytes, 25, 'stats.totalBytes (3)')
assert.equal(stats3.deletedBytes, 0, 'stats.deletedBytes (3)')
await new Promise((resolve, reject) => {
const arr = []
log.scan(
(offset, data, size) => {
arr.push(data)
},
(err) => {
if (err) return reject(err)
assert.deepEqual(arr, [buf1, buf2], 'both records exist')
resolve()
}
)
})
await p(log.close)()
})
await t.test('delete first record, compact, stream', async (t) => {
const file = '/tmp/pzp-db-log-compaction-test-' + Date.now() + '.log'
const log = Log(file, { blockSize: 15 })
const buf1 = Buffer.from('first')
const buf2 = Buffer.from('second')
const progressArr = []
log.compactionProgress((stats) => {
progressArr.push(stats)
})
const offset1 = await p(log.append)(buf1)
const offset2 = await p(log.append)(buf2)
await p(log.onDrain)()
assert('append two records')
const stats1 = await p(log.stats)()
assert.equal(stats1.totalBytes, 25, 'stats.totalBytes before')
assert.equal(stats1.deletedBytes, 0, 'stats.deletedBytes before')
await p(log.del)(offset1)
await p(log.onOverwritesFlushed)()
assert('delete first record')
await p(log.compact)()
assert.deepEqual(
progressArr,
[
{ percent: 0, done: false },
{ percent: 1, done: true, sizeDiff: 15, holesFound: 1 },
],
'progress events'
)
const stats2 = await p(log.stats)()
assert.equal(stats2.totalBytes, 10, 'stats.totalBytes after')
assert.equal(stats2.deletedBytes, 0, 'stats.deletedBytes after')
await new Promise((resolve, reject) => {
const arr = []
log.scan(
(offset, data, size) => {
arr.push(data)
},
(err) => {
if (err) return reject(err)
assert.deepEqual(arr, [buf2], 'only second record exists')
resolve()
}
)
})
await p(log.close)()
})
await t.test('delete last record, compact, stream', async (t) => {
const file = '/tmp/pzp-db-log-compaction-test-' + Date.now() + '.log'
const log = Log(file, { blockSize: 15 })
const buf1 = Buffer.from('first')
const buf2 = Buffer.from('second')
const buf3 = Buffer.from('third')
const offset1 = await p(log.append)(buf1)
const offset2 = await p(log.append)(buf2)
const offset3 = await p(log.append)(buf3)
await p(log.onDrain)()
assert('append three records')
await p(log.del)(offset3)
await p(log.onOverwritesFlushed)()
assert('delete third record')
await new Promise((resolve, reject) => {
const arr = []
log.scan(
(offset, data, size) => {
arr.push(data)
},
(err) => {
if (err) return reject(err)
assert.deepEqual(arr, [buf1, buf2, null], 'all blocks')
resolve()
}
)
})
await p(log.compact)()
await new Promise((resolve, reject) => {
const arr = []
log.scan(
(offset, data, size) => {
arr.push(data)
},
(err) => {
if (err) return reject(err)
assert.deepEqual(arr, [buf1, buf2], 'last block truncated away')
resolve()
}
)
})
await p(log.close)()
})
})