Preserve redo log for mutable objects

Replay it during time travel debugging
This commit is contained in:
Dmitry Vasilev
2024-01-01 18:33:46 +08:00
parent acd24fe5b7
commit 2830a160af
23 changed files with 1575 additions and 280 deletions

View File

@@ -0,0 +1,61 @@
import {Multiversion} from './multiversion.js'
// https://stackoverflow.com/a/29018745
function binarySearch(arr, el, compare_fn) {
let m = 0;
let n = arr.length - 1;
while (m <= n) {
let k = (n + m) >> 1;
let cmp = compare_fn(el, arr[k]);
if (cmp > 0) {
m = k + 1;
} else if(cmp < 0) {
n = k - 1;
} else {
return k;
}
}
return ~m;
}
export class LetMultiversion extends Multiversion {
constructor(cxt, initial) {
super(cxt)
this.latest = initial
this.versions = [{version_number: cxt.version_counter, value: initial}]
}
rollback_if_needed() {
if(this.needs_rollback()) {
this.latest = this.get_version(this.cxt.version_counter)
}
}
get() {
this.rollback_if_needed()
return this.latest
}
set(value) {
this.rollback_if_needed()
const version_number = ++this.cxt.version_counter
if(this.is_created_during_current_expansion()) {
this.versions.push({version_number, value})
}
this.latest = value
}
get_version(version_number) {
if(version_number == null) {
throw new Error('illegal state')
}
const idx = binarySearch(this.versions, version_number, (id, el) => id - el.version_number)
if(idx >= 0) {
return this.versions[idx].value
} else if(idx == -1) {
throw new Error('illegal state')
} else {
return this.versions[-idx - 2].value
}
}
}