mirror of https://codeberg.org/pzp/pzp-db.git
Log: fix concurrent overwrite() and compact()
This commit is contained in:
parent
844b808e78
commit
9e41400cdc
|
@ -634,6 +634,11 @@ function Log(filename, opts) {
|
|||
* @param {CB<void>} cb
|
||||
*/
|
||||
function overwrite(offset, data, cb) {
|
||||
if (compacting) {
|
||||
waitingCompaction.push(() => overwrite(offset, data, cb))
|
||||
return
|
||||
}
|
||||
|
||||
let encodedData = codec.encode(data)
|
||||
if (typeof encodedData === 'string') encodedData = b4a.from(encodedData)
|
||||
|
||||
|
@ -707,10 +712,6 @@ function Log(filename, opts) {
|
|||
* @param {CB<void>?} cb
|
||||
*/
|
||||
async function compact(cb) {
|
||||
if (compacting) {
|
||||
if (cb) waitingCompaction.push(cb)
|
||||
return
|
||||
}
|
||||
cb ??= logError
|
||||
const debug2 = debug.extend('compact')
|
||||
if (deletedBytes === 0) {
|
||||
|
@ -724,9 +725,13 @@ function Log(filename, opts) {
|
|||
// prettier-ignore
|
||||
return cb(new Error('Compact failed to pre-flush overwrites', { cause: err1 }))
|
||||
}
|
||||
if (compacting) {
|
||||
if (cb) waitingCompaction.push(cb)
|
||||
return
|
||||
}
|
||||
compacting = true
|
||||
|
||||
const startCompactTimestamp = Date.now()
|
||||
compacting = true
|
||||
if (compactionProgress.value.done) {
|
||||
compactionProgress.set(COMPACTION_PROGRESS_START)
|
||||
}
|
||||
|
@ -734,6 +739,7 @@ function Log(filename, opts) {
|
|||
const filenameNew = filename + '.compacting'
|
||||
const [err2] = await p(fs.unlink.bind(fs))(filenameNew)
|
||||
if (err2 && err2.code !== 'ENOENT') {
|
||||
compacting = false
|
||||
// prettier-ignore
|
||||
return cb(new Error('Compact failed to get rid of previous compacting log', { cause: err2 }))
|
||||
}
|
||||
|
@ -846,15 +852,16 @@ function Log(filename, opts) {
|
|||
const nextSince = latestBlockIndex * blockSize + nextOffsetInBlock
|
||||
const sizeDiff = oldTotalBytes - getTotalBytes()
|
||||
lastRecOffset.set(nextSince)
|
||||
compacting = false
|
||||
const duration = Date.now() - startCompactTimestamp
|
||||
debug2('Completed in %d ms', duration)
|
||||
deletedBytes = 0
|
||||
const [err7] = await p(saveStats)()
|
||||
if (err7) {
|
||||
compacting = false
|
||||
return cb(new Error('Compact failed to save stats file', { cause: err7 }))
|
||||
}
|
||||
compactionProgress.set({ percent: 1, done: true, sizeDiff, holesFound })
|
||||
compacting = false
|
||||
for (const callback of waitingCompaction) callback()
|
||||
waitingCompaction.length = 0
|
||||
cb()
|
||||
|
|
|
@ -30,7 +30,6 @@ test('Log compaction', async (t) => {
|
|||
})
|
||||
|
||||
await p(log.compact)()
|
||||
await p(log.onDrain)()
|
||||
|
||||
assert.deepEqual(
|
||||
progressArr,
|
||||
|
@ -88,7 +87,6 @@ test('Log compaction', async (t) => {
|
|||
assert('delete first record')
|
||||
|
||||
await p(log.compact)()
|
||||
await p(log.onDrain)()
|
||||
|
||||
assert.deepEqual(
|
||||
progressArr,
|
||||
|
@ -153,7 +151,6 @@ test('Log compaction', async (t) => {
|
|||
})
|
||||
|
||||
await p(log.compact)()
|
||||
await p(log.onDrain)()
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const arr = []
|
||||
|
|
Loading…
Reference in New Issue